使用Java/CORBA實現分佈應用程式設計
一、學習JAVA與CORBA
■CORBA技術簡介
簡單地說,CORBA允許應用之間相互通訊,而不管它們存在於哪裡以及是誰設計的。CORBA1.1於1991年由OMG釋出,其中定義了介面定義語言(IDL)以及在物件請求代理(ORB)中實現客戶物件與伺服器物件之間互動的應用程式設計介面(API)。CORBA2.0於1994年釋出,規定了各個供應商之間的ORB的通訊規則。
CORBA標準主要分為三個部分:介面定義語言(IDL)、物件請求代理(ORB)以及ORB之間的互操作協議IIOP。
ORB是物件之間建立Client/Server關係的中介軟體。使用ORB,客戶可以透明地呼叫一個服務物件上的方法,這個服務物件可以在本地,也可以在通過網路連線的其他機器上。ORB截獲這一呼叫同時負責查詢實現服務的物件並向其傳遞引數、呼叫方法返回最終結果。客戶並不知道服務物件位於什麼地方,它的程式語言和作業系統是什麼,也不知道不屬於物件介面的其他系統部分。這樣,ORB在異構分佈環境下為不同機器上的應用提供了互操作性,並無縫地集成了多種物件系統。
在開發傳統的Client/Server應用時,開發者使用他們自己設計的或一個公認的標準來定義用於裝置之間通訊的協議。協議的定義依賴於實現語言、網路傳輸和許多其他因素,而ORB的出現簡化了這一過程。使用ORB時,協議是使用介面定義語言(IDL)定義的,而IDL是獨立於語言的。並且ORB提供很強的靈活性,它使程式設計師選擇最適合的作業系統、執行環境,甚至系統各個元件也可以採用不同的程式語言實現。更重要的是,它允許現有元件的整合。在一個基於ORB的解決方案中,開發者可以使用與建立新物件一樣的IDL對遺留系統進行建模,他們建立“包裝”程式碼以在標準化的軟體匯流排與遺留系統介面之間傳遞資訊。
使用
■CORBA與JAVA的相互關係
CORBA不只意味著物件請求代理(ORB),它還是非常全面的分散式物件平臺。CORBA使JAVA應用可以跨越網路、語言以及作業系統,併為JAVA提供了一組分佈服務,如分散式自我觀察、動態發現、事務、關係、安全和命名等。
JAVA不僅是一種語言,它還是一個動態程式碼系統,它對執行物件來說是一個可移植的虛擬機器(JVM)。JAVA為開發、管理、釋出Client/Server應用提供了更簡單的方式。人們可以通過將應用放在一個Web伺服器上將這一應用釋出給成千上萬個使用者,而不必關心它的安裝和升級。JAVA還非常適合伺服器的開發,它可以動態地將服務程式碼移向最需要它們的地方。
JAVA將會使CORBA物件能夠執行在從主機、網路計算機到蜂窩電話等可程式設計的各種機器上,並簡化了大型CORBA系統的程式碼釋出。對客戶和服務物件來說JAVA是很理想的程式語言,JAVA內建的多執行緒、垃圾收集和錯誤處理使編寫健壯的網路物件變得很容易。
這兩種物件模型可以很好地相互補充,CORBA處理網路的透明性,JAVA處理實現的透明性,CORBA為JAVA可移植應用環境提供了一個分散式的結構。
二、按照網上教程配置CORBA環境
三、構建程式程式碼
1.使用IDL語言為遠端物件定義介面,根據題目要求,需要兩個介面,一個實現使用者的註冊和登入,一個實現使用者對list的增刪改查
creator.idl:
module CreatorModule{
interface Creator{
boolean login(in string name,in string password);
boolean register(in string name,in string password);
};
};
userOperation.idl:
module UserModule{
interface UserOperation{
boolean add(in string startTime,in string endTime,in string label);
string query(in string startTime,in string endTime);
boolean delete(in string key);
boolean clear();
string show();
};
};
2. 編譯介面並生成CORBA支援檔案
對CreatorModule目錄下的六個檔案說明如下:
(1) Creator.java:此介面包含IDL介面的Java版本。它繼承自org.omg.CORBA.Object,提供標準的CORBA物件功能。
(2)CreatorHelper.java : 此類提供輔助功能,Helper類負責讀寫資料型別到CORBA流,以及插入和提取資料型別。
(3)CreatorHolder.java : 此類是一個終態類,其中含有Creator型別的公有資料成員。
(4)CreatorOperations.java : 這是一個介面類,其中含有在creator.idl檔案中編寫的介面方法。
(5)CreatorPOA.java : 此抽象類是基於流的伺服器Skeleton,為伺服器提供基本的CORBA功能。它繼承org.omg.PortableServer.Servant, 實現了InvokeHandler介面和CreatorOperations介面。以後編寫的伺服器類要繼承CreatorPOA。
(6)_CreatorStub.java : 此類是客戶端stub,為客戶端提供CORBA功能。它繼承org.omg.CORBA.Object,提供標準CORBA物件功能。還擴充套件了 CreatorOperations介面和org.omg.CORBA.portable.IDLEntity介面。
UserModule目錄下的檔案意義和上面類似。
3. 編寫User類和Item類來分別儲存使用者以及list內的Item
import java.io.Serializable;
public class User implements Serializable {
private String name;
private String password;
public User(String name, String password) {
this.name = name;
this.password = password;
}
public String getName() {
return name;
}
public String getPassword() {
return password;
}
}
import java.io.Serializable;
import java.util.Date;
public class Item implements Serializable {
private Date startTime;
private Date endTime;
private String label;
public Item(Date startTime, Date endTime, String label) {
this.startTime = startTime;
this.endTime = endTime;
this.label = label;
}
public Date getStartTime() {
return startTime;
}
public Date getEndTime() {
return endTime;
}
public String getLabel() {
return label;
}
}
4. 建立CreatorImpl類和UserOperationImpl來實現兩個介面
import CreatorModule.CreatorPOA;
import org.omg.CORBA.ORB;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
public class CreatorImpl extends CreatorPOA {
private List<User> userList;
private ORB orb;
private CORBAServer cServer;
public CreatorImpl() {
init();
}
//read all users from the file
private void init() {
//從檔案中讀取使用者列表,轉化為HashMap
try (ObjectInputStream oin = new ObjectInputStream(new FileInputStream("User.file"))) {
Object object = oin.readObject();
userList = (List<User>) object;
} catch (Exception e) {
userList = new ArrayList<>();
}
}
public void setORB(ORB orb) {
this.orb = orb;
}
public void setToDoListServer(CORBAServer cServer) {
this.cServer = cServer;
}
//save the all users into the file
private void saveUsers() {
try (ObjectOutputStream oout = new ObjectOutputStream(new FileOutputStream("person.file"))) {
oout.writeObject(userList);
oout.flush();
} catch (Exception e) {
System.out.println("cant save the user");
e.printStackTrace();
}
}
//register user on the server
private void registerService(String name) {
cServer.registerUserName(name);
}
@Override
public boolean login(String name, String password) {
for (User user : userList) {
if (user.getName().equals(name) && user.getPassword().equals(password)) {
registerService(name);
return true;
}
}
return false;
}
@Override
public boolean register(String name, String password) {
for (User user : userList) {
//already have this user
if (user.getName().equals(name)) {
return false;
}
}
userList.add(new User(name, password));
saveUsers();
return true;
}
}
import UserModule.UserOperationPOA;
import org.omg.CORBA.ORB;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
public class UserOperationImpl extends UserOperationPOA {
private List<Item> userList; //this users list
private Map<String, List<Item>> allUserListMap; //all users List
private ORB orb;
public UserOperationImpl(String name) {
init();
userList = allUserListMap.get(name);
if (userList == null) {
userList = new ArrayList<>();
allUserListMap.put(name, userList);
}
}
private void init() {
//read user list
try(ObjectInputStream oin = new ObjectInputStream(new FileInputStream("item.file"))) {
Object object = oin.readObject();
allUserListMap = (HashMap<String, List<Item>>) object;
} catch (Exception e) {
allUserListMap = new HashMap<>();
}
}
public void setORB(ORB orb) {
this.orb = orb;
}
//save user list
private void saveUserList() {
try(ObjectOutputStream oout = new ObjectOutputStream(new FileOutputStream("item.file"))) {
oout.writeObject(allUserListMap);
oout.flush();
} catch (Exception e) {
System.out.println("cant save the list");
e.printStackTrace();
}
}
@Override
public boolean add(String startTime, String endTime, String label) {
try {
java.text.SimpleDateFormat formatter = new SimpleDateFormat( "yyyy-MM-dd hh:mm:ss");
Date startDate=formatter.parse(startTime);
Date endDate=formatter.parse(endTime);
Item item = new Item(startDate, endDate, label);
userList.add(item);
saveUserList();
return true;
}catch (ParseException e){
System.out.println("please input the right date(yyyy-MM-dd hh:mm:ss)");
e.printStackTrace();
}
return false;
}
@Override
public String query(String startTime, String endTime) {
String queryResult = "";
try{
SimpleDateFormat formatter = new SimpleDateFormat( "yyyy-MM-dd hh:mm:ss");
Date startDate=formatter.parse(startTime);
Date endDate=formatter.parse(endTime);
for (Item item : userList) {
if (item.getStartTime().after(startDate) && item.getEndTime().before(endDate)) {
queryResult +=item.getLabel()+":"+ item.getStartTime() +
"--" + item.getEndTime()+ "\n";
}
}
}catch (ParseException e){
System.out.println("please input the right date(yyy-MM-dd hh:mm:ss)");
e.printStackTrace();
}
return queryResult;
}
@Override
public boolean delete(String num) {
int index = Integer.parseInt(num);
if (index <= userList.size() && index >= 1) {
userList.remove(index - 1);
saveUserList();
return true;
} else {
return false;
}
}
@Override
public boolean clear() {
int index = userList.size()-1;
if (index < 0) {
return false;
} else {
while (index >= 0) {
userList.remove(index);
index--;
}
saveUserList();
return true;
}
}
@Override
public String show() {
String result = "";
if (userList.size() > 0) {
for (Item item : userList) {
result += item.getLabel()+":"+ item.getStartTime() +
"--" + item.getEndTime()+ "\n";
}
}
return result;
}
}
5. 編寫伺服器端程式碼
import UserModule.UserOperation;
import UserModule.UserOperationHelper;
import org.omg.CORBA.ORB;
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAHelper;
import CreatorModule.Creator;
import CreatorModule.CreatorHelper;
import java.util.Properties;
public class CORBAServer {
private ORB orb;
private POA rootPOA;
private org.omg.CORBA.Object obj;
private CreatorImpl creatorImpl;
private UserOperationImpl userOperationImpl;
private org.omg.CORBA.Object ref;
private Creator creatorhref;
private UserOperation userhref;
private org.omg.CORBA.Object objRef;
private NamingContextExt ncRef;
public static void main(String[] args) {
CORBAServer toDoListServer = new CORBAServer();
toDoListServer.init();
}
//初始化,註冊Creator到服務中
private void init() {
try {
String[] args = {};
Properties properties = new Properties();
properties.put("org.omg.CORBA.ORBInitialHost", "127.0.0.1"); //指定ORB的ip地址
properties.put("org.omg.CORBA.ORBInitialPort", "8080"); //指定ORB的埠
//建立一個ORB例項
orb = ORB.init(args, properties);
//拿到根POA的引用,並激活POAManager,相當於啟動了server
obj = orb.resolve_initial_references("RootPOA");
rootPOA = POAHelper.narrow(obj);
rootPOA.the_POAManager().activate();
//建立一個CreatorImpl例項
creatorImpl = new CreatorImpl();
creatorImpl.setToDoListServer(this);
//從服務中得到物件的引用,並註冊到服務中
ref = rootPOA.servant_to_reference(creatorImpl);
creatorhref = CreatorHelper.narrow(ref);
//得到一個根命名的上下文
objRef = orb.resolve_initial_references("NameService");
ncRef = NamingContextExtHelper.narrow(objRef);
//在命名上下文中繫結這個物件
String name = "Creator";
NameComponent path[] = ncRef.to_name(name);
ncRef.rebind(path, creatorhref);
System.out.println("server is ready and waiting....");
//啟動執行緒服務,等待客戶端呼叫
orb.run();
} catch (Exception e) {
e.printStackTrace();
}
}
//對使用者名稱進行註冊服務
public void registerUserName(String name) {
try {
//建立一個UserImpl例項
userOperationImpl = new UserOperationImpl(name);
userOperationImpl.setORB(orb);
//從服務中得到物件的引用,並註冊到服務中
ref = rootPOA.servant_to_reference(userOperationImpl);
userhref = UserOperationHelper.narrow(ref);
//在命名上下文中繫結這個物件
NameComponent path[] = ncRef.to_name(name);
ncRef.rebind(path, userhref);
} catch (Exception e) {
e.printStackTrace();
}
}
}
6. 編寫客戶端程式碼
import UserModule.UserOperation;
import UserModule.UserOperationHelper;
import org.omg.CORBA.ORB;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.CosNaming.NamingContextPackage.CannotProceed;
import org.omg.CosNaming.NamingContextPackage.NotFound;
import CreatorModule.Creator;
import CreatorModule.CreatorHelper;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Properties;
public class CORBAClient {
private Creator creator;
private UserOperation userOperation;
private BufferedReader reader;
private ORB orb;
private org.omg.CORBA.Object objRef;
private NamingContextExt ncRef;
public CORBAClient() {
reader = new BufferedReader(new InputStreamReader(System.in));
}
public static void main(String[] args) {
CORBAClient CORBAClient = new CORBAClient();
CORBAClient.init();
CORBAClient.procedure();
}
private void init() {
System.out.println("Client init config starts....");
String[] args = {};
Properties properties = new Properties();
properties.put("org.omg.CORBA.ORBInitialHost", "127.0.0.1"); //指定ORB的ip地址
properties.put("org.omg.CORBA.ORBInitialPort", "8080"); //指定ORB的埠
//建立一個ORB例項
orb = ORB.init(args, properties);
//獲取根名稱上下文
try {
objRef = orb.resolve_initial_references("NameService");
} catch (InvalidName e) {
e.printStackTrace();
}
ncRef = NamingContextExtHelper.narrow(objRef);
String name = "Creator";
try {
//通過ORB拿到server例項化好的Creator類
creator = CreatorHelper.narrow(ncRef.resolve_str(name));
} catch (NotFound e) {
e.printStackTrace();
} catch (CannotProceed e) {
e.printStackTrace();
} catch (org.omg.CosNaming.NamingContextPackage.InvalidName e) {
e.printStackTrace();
}
System.out.println("Client init config ends...");
}
//與使用者互動
public void procedure() {
String choice;
String startTime, endTime, label;
String index;
try {
while (true) {
System.out.println("1.Register\n2.Login\n3.Exit");
choice = reader.readLine();
switch (choice) {
case "1":
while (true) {
if (register()) {
break;
}
}
break;
case "2":
while (true) {
if (login()) {
System.out.println("Login Successful!");
do {
System.out.println("Please choose following command:");
System.out.println("1.Add item\n" +
"2.Query item\n" +
"3.Show items\n" +
"4.Delete item\n" +
"5.Clear items\n" +
"6.Logout");
choice = reader.readLine();
switch (choice) {
case "1":
System.out.println("please input startTime (like this:2018-05-19 08:20:00):");
startTime = reader.readLine();
System.out.println("please input endTime (like this:2018-05-19 08:20:00):");
endTime = reader.readLine();
System.out.println("please input label:");
label = reader.readLine();
if (userOperation.add(startTime, endTime, label)) {
System.out.println("Add item successful!");
} else {
System.out.println("Add item fail!");
}
break;
case "2":
System.out.println("please input startTime (like this:2018-05-19 08:20:00):");
startTime = reader.readLine();
System.out.println("please input endTime (like this:2018-05-19 08:20:00):");
endTime = reader.readLine();
System.out.println(userOperation.query(startTime, endTime));
break;
case "3":
System.out.println(userOperation.show());
break;
case "4":
System.out.println("please input index:");
index = reader.readLine();
if (userOperation.delete(index)) {
System.out.println("Delete item successful!");
} else {
System.out.println("Delete item fail!");
}
break;
case "5":
if (userOperation.clear()) {
System.out.println("Clear items done!");
}
break;
}
} while (!choice.equals("6"));
break;
} else {
System.out.println("Login fail!");
break;
}
}
break;
case "3":
return;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
//註冊
private boolean register() {
String username, password;
try {
System.out.println("please input username:");
username = reader.readLine();
System.out.println("please input password:");
password = reader.readLine();
if (creator.register(username, password)) {
System.out.println("Register successful!");
return true;
} else {
System.out.println("Register fail!");
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
//登入
private boolean login() {
String username, password;
try {
System.out.println("please input username:");
username = reader.readLine();
System.out.println("please input password:");
password = reader.readLine();
if (creator.login(username, password)) {
try {
//通過ORB拿到server例項化好的User類
userOperation = UserOperationHelper.narrow(ncRef.resolve_str(username));
} catch (NotFound e) {
e.printStackTrace();
} catch (CannotProceed e) {
e.printStackTrace();
} catch (org.omg.CosNaming.NamingContextPackage.InvalidName e) {
e.printStackTrace();
}
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}