RMI实例(实现分布式议程共享服务)

主要功能

1) 使用Java RMI创建一个分布式议程共享服务。不同的用户可以使用这个共享议程服务执行查询、添加和删除会议的操作。服务器支持会议的登记和清除等功能;

2) 议程共享服务包括以下功能:用户注册、添加会议、查询会议、删除会议、清除会议;

3) 用户注册
新用户注册需要填写用户名和密码,如果用户名已经存在,则注册失败并打印提示信息,否则注册成功并打印成功提示。使用如下命令进行用户注册:

4) 添加会议
已注册的用户可以添加会议。会议必须涉及到两个已注册的用户,一个只涉及单个用户的会议无法被创建。会议的信息包括开始时间、结束时间、会议标题、会议参与者。当一个会议被添加之后,它必须出现在创建会议的用户和参加会议的用户的议程中。如果一个用户的新会议与已经存在的会议出现时间重叠,则无法创建会议。最终,用户收到会议添加结果的提示。使用如下命令进行会议的添加:

5) 查询会议
已注册的用户通过给出特定时间区间(给出开始时间和结束时间)在议程中查询到所有符合条件的会议记录。返回的结果列表按时间排序。在列表中,包括开始时间、结束时间、会议标题、会议参与者等信息。使用如下命令进行会议的查询:

6) 删除会议
已注册的用户可以根据会议的信息删除由该用户创建的会议。使用如下命令进行删除会议操作:

7) 清除会议
已注册的用户可以清除所有由该用户创建的会议。使用如下命令进行清除操作:

具体代码实现

启动 RMI 注册服务并进行对象注册


import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
import ssd8.rmi.rface.HelloInterface;

/**
 * RMI Hello Server
 * 
 * @author Sardar
 *
 */
public class HelloServer {

    /**
     * 启动 RMI 注册服务并进行对象注册
     */
    public static void main(String[] args) {
        try {
            // 启动RMI注册服务,指定端口为1099 (1099为默认端口)
            // 也可以通过命令 $java_home/bin/rmiregistry 1099启动
            // 这里用这种方式避免了再打开一个DOS窗口
            // 而且用命令rmiregistry启动注册服务还必须事先用RMIC生成一个stub类为它所用
            LocateRegistry.createRegistry(1099);

            // 创建远程对象的一个或多个实例,下面是hello对象
            // 可以用不同名字注册不同的实例
            HelloInterface hello = new Hello();

            // 把hello注册到RMI注册服务器上,命名为Hello
            Naming.rebind("Hello", hello);

            // 如果要把hello实例注册到另一台启动了RMI注册服务的机器上
            // Naming.rebind("//192.168.1.105:1099/Hello",hello);
            System.out.println("Hello Server is ready.");

        } catch (Exception e) {
            System.out.println("Hello Server failed: " + e);
        }
    }

}

创建远程接口,此接口必须扩展接口java.rmi.Remote


import java.rmi.Remote;
import java.rmi.RemoteException;
import java.text.ParseException;
import java.util.ArrayList;
import ssd8.rmi.bean.Meeting;
import ssd8.rmi.bean.User;

/**
 * 远程接口必须扩展接口java.rmi.Remote 
 * @author Sarda
 */
public interface HelloInterface extends Remote {

    /**
     * 注册用户
     * 如果用户名存在,返回false,否则注册新用户,返回true
     */
    public boolean register(String name, String password)throws java.rmi.RemoteException;

    /**
     * 添加新会议
     * 账号密码不正确,返回0
     * 会议发起者和参与者是同一个用户,返回-1
     * 会议参与者没有注册,返回-2
     * 会议时间与发起者时间冲突,返回-3
     * 会议时间与参与者时间冲突,返回-4
     * 添加成功,返回1
     * @throws ParseException 
     */
    public int addMeeting(String name, String password, String start, String end, String title, String otherusername)throws java.rmi.RemoteException, ParseException;

    /**
     * 查询相应时间段内是否有会议
     * 账号密码不正确,返回null
     * 查询成功,返回查询内容
     * @throws ParseException 
     */
    public String[][] search(String name, String password, String start, String end)throws java.rmi.RemoteException, ParseException;

    /**
     * 删除用户发起的某一个会议
     * @param name
     * @param password
     * @param id
     * @return 账号密码错误返回false,添加成功,返回true
     * @throws java.rmi.RemoteException
     */
    public boolean delete(String name, String password, int id)throws java.rmi.RemoteException;

    /**
     * 清楚用户发起的所有会议
     * @param name
     * @param password
     * @return 账号密码错误返回false,清除成功,返回true
     * @throws java.rmi.RemoteException
     */
    public boolean clear(String name, String password)throws java.rmi.RemoteException;
}

创建远程方法,扩展UnicastRemoteObject类,并实现远程接口HelloInterface

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import ssd8.rmi.bean.Meeting;
import ssd8.rmi.bean.User;
import ssd8.rmi.rface.HelloInterface;

/**
 * 扩展UnicastRemoteObject类,并实现远程接口HelloInterface 
 * 
 * @author wben
 *
 */
public class Hello extends UnicastRemoteObject implements HelloInterface {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private String status = "0000";

    private int id = 0;

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private List<User> userList = new ArrayList<User>();

    private List<Meeting> meetingList = new ArrayList<Meeting>();

    /**
     * 必须定义构造方法,即使是默认构造方法,也必须把它明确地写出来,因为它必须抛出出RemoteException异常
     */
    public Hello() throws RemoteException {

//      userList.add(new User("peter","peter"));
    }

    /**
     * 远程接口方法的实现
     */

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    @Override
    public boolean register(String name, String password) throws RemoteException {
        if(exist(name)){
            return false;
        }
        userList.add(new User(name, password));
        return true;
    }
    /**
     * 检查用户是否已注册
     * @param name
     * @return
     */
    private boolean exist(String name) {
         for (User u : userList) {
            if(u.getName().equals(name)) {
                return true;
            }
        }  
        return false;
    }

    @Override
    public int addMeeting(String name, String password, String startTime, String endTime, 
            String title, String otherusername)
            throws RemoteException, ParseException {
        User sponsor = findUser(name);
        User otheruser = findUser(otherusername);
        Date start = sdf.parse(startTime);
        Date end = sdf.parse(endTime);

        if(!checkUser(name, password)) return 0;
        if(name == otherusername) return -1;
        if(!exist(otherusername)) return -2;
        if(overlap(sponsor, start, end)) return -3;
        if(overlap(otheruser, start, end)) return -4;

        Meeting meeting = new Meeting(sponsor, otheruser, start, end, title);
        meeting.setId(id++);
        meetingList.add(meeting);
        sponsor.getSchedule().add(meeting);
        otheruser.getSchedule().add(meeting);
        return 1;
    }
    /**
     * 检查时间是否与已经存在的会议出现时间重叠
     * @param name
     * @param start
     * @param end
     * @return
     */
    private boolean overlap(User user, Date start, Date end) {
        if(user.getSchedule().size()==0) {
            return false;
        }
        for (Meeting meeting : user.getSchedule()) 
            if(max(meeting.getStart(),start).compareTo(min(meeting.getEnd(),end))<=0) 
                return true;

        return false;
    }

    private Date max(Date start, Date start2) {
        if(start.after(start2)) {
            return start;
        }else {
            return start2;
        }
    }

    private Date min(Date end, Date end2) {
        if(end.before(end2)) {
            return end;
        }else {
            return end2;
        }
    }

    @Override
    public String[][] search(String name, String password, String startTime, String endTime) 
            throws RemoteException, ParseException {
        if(!checkUser(name, password)) return null;
        User user = findUser(name);
        Date start = sdf.parse(startTime);
        Date end = sdf.parse(endTime);
        ArrayList<Meeting> list = new ArrayList<Meeting>();
        for (Meeting meeting : meetingList) {
            if(meeting.getStart().compareTo(start)>=0&&meeting.getStart().before(end)) {
                list.add(meeting);
            }
        }
        sort(list);
        int n = list==null?0:list.size();
        String[][] s = new String[n][5];
        for(int j=0; j<list.size(); j++) {
            s[j][0] = String.valueOf(list.get(j).getId());
            s[j][1] = sdf.format(list.get(j).getStart());
            s[j][2] = sdf.format(list.get(j).getEnd());
            s[j][3] = list.get(j).getTitle();
            s[j][4] = list.get(j).getSponsor().getName() + ", " + list.get(j).getOtheruser().getName();
        }
        return s;
    }

    /**
     * 会议按开始时间升序排序
     * @param list
     */
    private void sort(ArrayList<Meeting> list) {
        for(int i=0; i<list.size(); i++) {
            for(int j=i; j<list.size(); j++) {
                if(list.get(j).getStart().before(list.get(i).getStart())) {
                    swap(list.get(j),list.get(i));
                }
            }
        }
    }

    /**
     * 交换两个会议内容
     * @param m1
     * @param m2
     */
    private void swap(Meeting m1, Meeting m2) {
        User user = m1.getSponsor();
        m1.setSponsor(m2.getSponsor());
        m2.setSponsor(user);

        user = m1.getOtheruser();
        m1.setOtheruser(m2.getOtheruser());
        m2.setOtheruser(user);

        Date date = m1.getStart();
        m1.setStart(m2.getStart());
        m2.setStart(date);

        date = m1.getEnd();
        m1.setEnd(m2.getEnd());
        m2.setEnd(date);

        String title = m1.getTitle();
        m1.setTitle(m2.getTitle());
        m2.setTitle(title);
    }

    @Override
    public boolean delete(String name, String password, int id) throws RemoteException {
        if(!checkUser(name, password)) return false;
        User user = findUser(name);
        for (int i = 0; i < meetingList.size(); i++) {
            if(meetingList.get(i).getSponsor().equals(user) && meetingList.get(i).getId() == id) {
                meetingList.get(i).getSponsor().getSchedule().remove(meetingList.get(i));
                meetingList.get(i).getOtheruser().getSchedule().remove(meetingList.get(i));
                meetingList.remove(meetingList.get(i));
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean clear(String name, String password) throws RemoteException {
        if(!checkUser(name, password)) return false;
        int flag = 0;
        User user = findUser(name);
        List<Meeting> m = new ArrayList<Meeting>();
        for (Meeting meeting : meetingList) {
            if(meeting.getSponsor().equals(user)) {
                m.add(meeting); 
            }
        }
        for (Meeting meeting : m) {
            meetingList.remove(meeting);
            flag = 1;
        }
        if(flag == 0) {
            return false;
        }else {
            return true;
        }

    }
    /**
     * 按用户名查找用户
     * @param name
     * @return
     * @throws RemoteException
     */
    public User findUser(String name) throws RemoteException {
        for (User u : userList) {
            if(u.getName().equals(name))
                return u;
        } 
        return null;
    }
    /**
     * 检查用户输入的账号密码是否正确
     * @param name
     * @param password
     * @return
     */
    private boolean checkUser(String name, String password) {
        for (User u : userList) {
            if(u.getName().equals(name)&&u.getPassword().equals(password))
                return true;
        } 
        return false;
    }
}

创建Client 远程调用hello实例的方法

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.rmi.Naming;
import java.util.List;
import ssd8.rmi.rface.HelloInterface;

public class HelloClient {
    public static void main(String[] argv) {
        BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
        try {
            HelloInterface hello = (HelloInterface) Naming.lookup("Hello");

            // 如果要从另一台启动了RMI注册服务的机器上查找hello实例
            // HelloInterface hello =
            // (HelloInterface)Naming.lookup("//192.168.1.105:1099/Hello");

             //控制台输入提示
            System.out.println("请选择操作");
            System.out.println("register");
            System.out.println("add");
            System.out.println("query");
            System.out.println("delete");
            System.out.println("clear");

            while(true){
                String request = keyboard.readLine();
                //注册用户
                if(request.startsWith("regist")){
                    System.out.println("请输入用户名和密码(用逗号隔开)");
                    String r = keyboard.readLine();
                    String[] s = r.split(",", 2);
                    String name = s[0];
                    String password = s[1];
                    if(hello.register(name, password)) {
                        System.out.println("注册成功!");
                    }else {
                        System.out.println("注册失败!");
                    }
                    //添加会议
                }else if(request.startsWith("add")){
                    System.out.println("请输入用户名,密码,会议开始时间,会议结束时间,会议标题,会议参与者姓名(用逗号隔开)");
                    String r = keyboard.readLine();
                    String[] s = r.split(",", 6);                   
                    String name = s[0];
                    String password = s[1];
                    String start = s[2];
                    String end = s[3];
                    String title = s[4];
                    String otherusername = s[5];
                    int i = hello.addMeeting(name, password, start, end, title, otherusername);
                    switch (i) {
                    case 0:
                        System.out.println("用户名或密码错误!");
                        break;
                    case -1:
                        System.out.println("用户名未注册!");
                        break;
                    case -2:
                        System.out.println("会议参与者未注册!");
                        break;
                    case -3:
                        System.out.println("用户时间冲突!");
                        break;
                    case -4:
                        System.out.println("会议参与者时间冲突!");
                        break;
                    case 1:
                        System.out.println("添加会议成功!");
                        break;
                    default:
                        break;
                    }
                    //查询会议
                }else if(request.startsWith("query")){
                    System.out.println("请输入用户名,密码,开始时间,结束时间(用逗号隔开)");
                    String r = keyboard.readLine();
                    String[] s = r.split(",", 4);
                    String name = s[0];
                    String password = s[1];
                    String start = s[2];
                    String end = s[3];
                    String[][] list = hello.search(name, password, start, end);
                    if(list != null) {
                        for (String[] i : list) {
                            System.out.print("ID: "+ i[0] + " ");
                            System.out.print("开始时间: "+ i[1] + " ");
                            System.out.print("结束时间: "+ i[2] + " ");
                            System.out.print("标题: "+ i[3] + " ");
                            System.out.print("参与者: "+ i[4] + " ");
                            System.out.println();
                        }
                    }else {
                        System.out.println("查询失败!");
                    }
                    //删除会议
                }else if(request.startsWith("delete")){
                    System.out.println("请输入用户名,密码,id(用逗号隔开)");
                    String r = keyboard.readLine();
                    String[] s = r.split(",", 3);
                    String name = s[0];
                    String password = s[1];
                    int id = Integer.parseInt(s[2]);
                    if(hello.delete(name, password, id)) {
                        System.out.println("删除成功!");
                    }else {
                        System.out.println("删除失败!");
                    }
                    //清除会议
                }else if(request.startsWith("clear")){
                    System.out.println("请输入用户名,密码(用逗号隔开)");
                    String r = keyboard.readLine();
                    String[] s = r.split(",", 2);
                    String name = s[0];
                    String password = s[1];
                    if(hello.clear(name, password)) {
                        System.out.println("清除成功!");
                    }else {
                        System.out.println("清除失败!");
                    }
                }else{
                    System.out.println("bad request!");
                }
            }
        } catch (Exception e) {
            System.out.println("HelloClient exception: " + e);
        }
    }
}

自定义User对象

import java.io.Serializable;
import java.util.ArrayList;

public class User implements Serializable{
    private String name;
    private String password;
    private ArrayList<Meeting> schedule;

    public User(String name, String password) {
        super();
        this.name = name;
        this.password = password;
        this.schedule = new ArrayList<Meeting>();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public ArrayList<Meeting> getSchedule() {
        return schedule;
    }
}

自定义Meeting对象

import java.util.Date;

public class Meeting {

    private User sponsor;
    private User otheruser;
    private Date start;
    private Date end;
    private String title;
    private int id;

    public Meeting(User sponsor, User otheruser, Date start, Date end, String title) {
        super();
        this.sponsor = sponsor;
        this.otheruser = otheruser;
        this.start = start;
        this.end = end;
        this.title = title;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public User getSponsor() {
        return sponsor;
    }
    public void setSponsor(User sponsor) {
        this.sponsor = sponsor;
    }
    public User getOtheruser() {
        return otheruser;
    }
    public void setOtheruser(User otheruser) {
        this.otheruser = otheruser;
    }
    public Date getStart() {
        return start;
    }
    public void setStart(Date start) {
        this.start = start;
    }
    public Date getEnd() {
        return end;
    }
    public void setEnd(Date end) {
        this.end = end;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
}

运行示例

先运行HelloServer注册RMI实例,接着运行HelloClient远程调用Hello定义的方法
先注册两个用户,添加三个会议,其中前两个分别是每个用户发起的会议,第三个是时间冲突的会议
这里写图片描述
再启动一个HelloClient客户端,完成删除和清除操作。
这里写图片描述

  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值