使用java和CORBA實現分佈應用編程

因爲課程的需要,學習了下用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<String, Person> 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<String, Person>) object;
            } catch (ClassNotFoundException e) {
                System.out.println("object cast error");
                personsMap = new HashMap<String, Person>();
            }
            oin.close();
            fin.close();
        } catch (Exception e) {
            personsMap = new HashMap<String, Person>();
        }
    }

    //將用戶表保存到本地文件中
    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<Item> personalList;                  //單個用戶的to-do-list
    private Map<String, List<Item>> allPersonListMap;   //所有用戶的to-do-list
    private ORB orb;

    public UserImpl(String name) {
        init();
        personalList = allPersonListMap.get(name);
        if (personalList == null) {
            personalList = new ArrayList<Item>();
            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<String, List<Item>>) object;
            } catch (ClassNotFoundException e) {
                System.out.println("object cast error");
                allPersonListMap = new HashMap<String, List<Item>>();
            }
            oin.close();
            fin.close();
        } catch (Exception e) {
            allPersonListMap = new HashMap<String, List<Item>>();
        }
    }

    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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章