因为课程的需要,学习了下用java和CORBA来实现分布应用编程,具体的CORBA是什么以及它的框架结构我就不多说了,这里我是给出一个比较完整的例子来展示下代码要怎么写。
使用java和CORBA构建一个关于制订to-do-list的分布式应用。不同的客户端可以通过连接到服务器来管理自己的to-do-list,比如有add list items、query list items、delete list items、clear to-do lists、show total list等功能。同时服务器可以管理用户,比如有登录和注册功能。每个to-do list的内容有该做的事、开始时间、结束时间。
一、编写IDL接口定义文件
使用IDL语言为远程对象定义接口,根据题目要求,定义IDL文件如下:
(1)在文件creator.idl中:
module CreatorModule{
interface Creator{
boolean login(in string name,in string password);
boolean register(in string name,in string password);
};
};
这是用来管理用户的,提供了注册和登陆接口。
(2)在文件user.idl中:
mmodule UserModule{
interface User{
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();
};
};
add()、query()、delete()、clear()、show()分别为客户端对to-do-list中的item进行增查删清的操作。
二、将接口定义文件编译为相应高级语言源代码,产生服务器框架与客户端存根
定义好IDL接口文件后,使用idlj编译器生成Java语言的stub和skeleton源文件。idlj编译器缺省只生成客户端的binding代码。如果同时需要客户端的bindings和服务器端的skeletons,必须加上-fall选项。
所以在shell中先后输入命令
idlj -fall /home/huxijie/IntelliJIDEAProjects/ToDoListApp/src/creator.idl
和命令
idlj -fall /home/huxijie/IntelliJIDEAProjects/ToDoListApp/src/user.idl
后会生成目录CreatorModule和UserModule。两个目录的文件如下:
对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目录下的文件意义和上面类似。
三、编写对象类
根据题意,需要编写Person类来抽象化用户以及Item类来抽象化to-do-list中的事项。因为我是将用户列表和事项列表存在本地文件中,所以需要让Person类和Item类实现Serializable序列化。
/**
* Created by huxijie on 17-5-3.
* 用户类
*/
public class Person implements Serializable{
private String name;
private String password;
public Person(String name, String password) {
this.name = name;
this.password = password;
}
public String getPassword() {
return password;
}
}
/**
* Created by huxijie on 17-5-3.
* 事项类
*/
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;
}
}
四、接口实现
(一)实现creator.idl中定义的接口
/**
* Created by huxijie on 17-5-3.
* 实现用户管理creator.idl中定义的接口
*/
public class CreatorImpl extends CreatorPOA {
private Map personsMap;
private String name = null;
private ORB orb;
private ToDoListServer toDoListServer;
private UserImpl userImpl;
public CreatorImpl() {
init();
}
//初始化
private void init() {
//从文件中读取用户列表,转化为HashMap
try {
FileInputStream fin = new FileInputStream("person.file");
ObjectInputStream oin = new ObjectInputStream(fin);
try {
Object object = oin.readObject();
personsMap = (HashMap) object;
} catch (ClassNotFoundException e) {
System.out.println("object cast error");
personsMap = new HashMap();
}
oin.close();
fin.close();
} catch (Exception e) {
personsMap = new HashMap();
}
}
//将用户表保存到本地文件中
private void saveData() {
try {
FileOutputStream fout = new FileOutputStream("person.file");
ObjectOutputStream oout = new ObjectOutputStream(fout);
oout.writeObject(personsMap);
oout.flush();
fout.flush();
oout.close();
fout.close();
} catch (Exception e) {
System.out.println("save error.");
e.printStackTrace();
}
}
public void setORB(ORB orb) {
this.orb = orb;
}
public void setToDoListServer(ToDoListServer toDoListServer) {
this.toDoListServer = toDoListServer;
}
//对用户名进行注册服务
private void registerService(String name) {
toDoListServer.registerUserName(name);
}
@Override
public boolean login(String name, String password) {
Person p = personsMap.get(name);
if (p != null && p.getPassword().equals(password)) {
this.name = name;
//登录成功后对用户名进行注册服务
registerService(name);
return true;
} else {
return false;
}
}
@Override
public boolean register(String name, String password) {
Person person = personsMap.get(name);
if (person != null) { //表中用户名为name的已存在
return false;
} else {
personsMap.put(name, new Person(name, password));
saveData();
return true;
}
}
}
(二)实现user.idl中定义的接口
/**
* Created by huxijie on 17-5-3.
* 实现to-do-list管理user.idl中定义的接口
*/
public class UserImpl extends UserPOA{
private Date date;
private DateFormat dateFormat;
private String dateRegex;
private List- personalList; //单个用户的to-do-list
private Map
> allPersonListMap; //所有用户的to-do-list
private ORB orb;
public UserImpl(String name) {
init();
personalList = allPersonListMap.get(name);
if (personalList == null) {
personalList = new ArrayList- ();
allPersonListMap.put(name, personalList);
}
date = new Date();
dateFormat = DateFormat.getDateInstance();
//日期格式规定为:xxxx-xx-xx,xx:xx
dateRegex = "\\d{4}-\\d{1,2}-\\d{1,2},\\d{2}:\\d{2}";
}
private void init() {
//从文件中读取to-do-list列表,转化为HashMap
try {
FileInputStream fin = new FileInputStream("item.file");
ObjectInputStream oin = new ObjectInputStream(fin);
try {
Object object = oin.readObject();
allPersonListMap = (HashMap
>) object;
} catch (ClassNotFoundException e) {
System.out.println("object cast error");
allPersonListMap = new HashMap>();
}
oin.close();
fin.close();
} catch (Exception e) {
allPersonListMap = new HashMap>();
}
}
public void setORB(ORB orb) {
this.orb = orb;
}
//将to-do-list表保存到本地文件中
private void saveData() {
try {
FileOutputStream fout = new FileOutputStream("item.file");
ObjectOutputStream oout = new ObjectOutputStream(fout);
oout.writeObject(allPersonListMap);
oout.flush();
fout.flush();
oout.close();
fout.close();
} catch (Exception e) {
System.out.println("save error.");
e.printStackTrace();
}
}
//判断输入日期是否符合格式要求
private boolean isFormatMatch(String dateStr) {
return dateStr.matches(dateRegex);
}
//将字符串转化为日期
private Date turnToDate(String dateStr) {
String[] str = dateStr.split("[,|:]");
try {
date = dateFormat.parse(str[0]);
date.setHours(Integer.parseInt(str[1]));
date.setMinutes(Integer.parseInt(str[2]));
} catch (Exception e) {
e.printStackTrace();
}
return date;
}
@Override
public boolean add(String startTime, String endTime, String label) {
Date startDate,endDate;
if (isFormatMatch(startTime) && isFormatMatch(endTime)) {
startDate = turnToDate(startTime);
endDate = turnToDate(endTime);
Item item = new Item(startDate, endDate, label);
personalList.add(item);
saveData();
return true;
} else {
return false;
}
}
@Override
public String query(String startTime, String endTime) {
Date startDate,endDate;
int index = 0;
String queryResult = "";
if (isFormatMatch(startTime) && isFormatMatch(endTime)) {
startDate = turnToDate(startTime);
endDate = turnToDate(endTime);
for (Item item : personalList) {
if (item.getStartTime().after(startDate)
&& item.getEndTime().before(endDate)) {
index++;
queryResult += index + " : " + item.getStartTime() +
"-->" + item.getEndTime() +
" " + item.getLabel() + "\n";
}
}
} else {
queryResult = "Date format is wrong!\n";
}
return queryResult;
}
@Override
public String show() {
String result = "";
int index = 0;
if (personalList.size() > 0) {
for (Item item : personalList) {
index++;
result += index + " : " + item.getStartTime() +
"-->" + item.getEndTime() +
" " + item.getLabel() + "\n";
}
} else {
result = "Empty to-do-list!\n";
}
return result;
}
@Override
public boolean delete(String key) {
int index = Integer.parseInt(key);
if (index <= personalList.size() && index >= 1) {
personalList.remove(index - 1);
saveData();
return true;
} else {
return false;
}
}
@Override
public boolean clear() {
int index = personalList.size()-1;
if (index < 0) {
return false;
} else {
while (index >= 0) {
personalList.remove(index);
index--;
}
saveData();
return true;
}
}
}
五、基于服务器框架,编写服务对象实现程序
/**
* Created by huxijie on 17-5-3.
* 基于服务器框架,编写服务器对象
*/
public class ToDoListServer {
private ORB orb;
private POA rootPOA;
private org.omg.CORBA.Object obj;
private CreatorImpl creatorImpl;
private UserImpl userImpl;
private org.omg.CORBA.Object ref;
private Creator creatorhref;
private User userhref;
private org.omg.CORBA.Object objRef;
private NamingContextExt ncRef;
public static void main(String[] args) {
ToDoListServer toDoListServer = new ToDoListServer();
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.ToDoListServer is ready and waiting....");
//启动线程服务,等待客户端调用
orb.run();
} catch (Exception e) {
e.printStackTrace();
}
}
//对用户名进行注册服务
public void registerUserName(String name) {
try {
//创建一个UserImpl实例
userImpl = new UserImpl(name);
userImpl.setORB(orb);
//从服务中得到对象的引用,并注册到服务中
ref = rootPOA.servant_to_reference(userImpl);
userhref = UserHelper.narrow(ref);
//在命名上下文中绑定这个对象
NameComponent path[] = ncRef.to_name(name);
ncRef.rebind(path, userhref);
} catch (Exception e) {
e.printStackTrace();
}
}
}
六、基于客户端存根,编写客户对象调用程序
/**
* Created by huxijie on 17-5-3.
* 基于客户端存根,编写客户对象调用程序
*/
public class ToDoListClient {
private Creator creator;
private User user;
private BufferedReader reader;
private ORB orb;
private org.omg.CORBA.Object objRef;
private NamingContextExt ncRef;
public ToDoListClient() {
reader = new BufferedReader(new InputStreamReader(System.in));
}
public static void main(String[] args) {
ToDoListClient toDoListClient = new ToDoListClient();
toDoListClient.init();
toDoListClient.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("Welcome to to_do_list_APP!Please choose:");
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:2017-04-19,08:20):");
startTime = reader.readLine();
System.out.println("please input endTime (like this:2017-04-19,08:20):");
endTime = reader.readLine();
System.out.println("please input label:");
label = reader.readLine();
if (user.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:2017-04-19,08:20):");
startTime = reader.readLine();
System.out.println("please input endTime (like this:2017-04-19,08:20):");
endTime = reader.readLine();
System.out.println(user.query(startTime, endTime));
break;
case "3":
System.out.println(user.show());
break;
case "4":
System.out.println("please input index:");
index = reader.readLine();
if (user.delete(index)) {
System.out.println("Delete item successful!");
} else {
System.out.println("Delete item fail!");
}
break;
case "5":
if (user.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类
user = UserHelper.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;
}
}
}
七、启动orbd服务
在shell里输入命令(注意orbd命令是在%JAVA_HOME%/bin下):
orbd -ORBInitialPort 8080 -ORBInitialHost 127.0.0.1
八、启动server
九、启动client
一、服务器端
二、客户端
(一)注册
(二)登录
(三)Add
(四)Show
(五)Query
(六)Delete
(七)Clear
代码已放在github上:https://github.com/loveEason/ToDoListApp