Java RMI使用简记

因为课内作业第一次接触到了Java RMI的使用,感觉是一个很棒的工具,所以在此记录一下用法,方便以后再用。
这里以在线的会议管理为例,为了看起来简洁所以随便删了一部分不是很重要的代码;
众所周知,RMI是面向对象的分布式调用,所以对象的概念尤为重要,所以第一个包就是定义用得到的对象类:
User类
为了简单只要name和password两个属性;
这里要注意的是,因为要在网络上引用这个对象,所以传输的时候一定要能够串行化,否则难以传输,这里继承了Serializable 就是这个目的。

package ssd8.rmi.bean;

import java.io.Serializable;

/**
 * @author ly
 */
public class User implements Serializable {
    private String name;
    private String password;

    public User(String name, String password) {
        super();
        this.name = name;
        this.password = password;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;

        User user = (User) o;

        if (!name.equals(user.name)) return false;
        return password != null ? password.equals(user.password) : user.password == null;
    }

    //get或者set操作
}

再来一个Meeting类:

package ssd8.rmi.bean;

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

/**
 * @author ly
 */
public class Meeting implements Serializable{

    /**
     * the id for meeting
     */
    private int meetingID;

    /**
     * the title for meeting
     */
    private String title;

    /**
     * the time for the meeting
     */
    private Date startTime;
    private Date endTime;

    /**
     * the sponsor and the joiner
     */
    private User launchUser;
    private ArrayList<User> otherUsers;

    /**
     * 
     * @param meetingID 
     * @param title 
     * @param startTime 
     * @param endTime 
     * @param launchUser 
     * @param otherUsers 
     */
    public Meeting(int meetingID, String title, Date startTime, Date endTime, User launchUser, ArrayList<User> otherUsers) {
        this.meetingID = meetingID;
        this.title = title;
        this.startTime = startTime;
        this.endTime = endTime;
        this.launchUser = launchUser;
        this.otherUsers = otherUsers;
    }

    //get set equal toString操作
}

类实体定义完了,接下来就是为了统一协调收发端(服务器和客户端)而特意定义的接口MeetingInterface接口:
这里要注意的是
1、因为是定义接口,所以用interface extends Remote由此继承Remote接口的特性;
2、所有的方法都必须抛出RemoteException异常类型,否则运行时会出错;

package ssd8.rmi.rface;

import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.ArrayList;

/**
 * @author ly
 */
public interface MeetingInterface extends Remote {

    /**
     * register
     *
     * @param username 
     * @param password 
     * @return true if register successfully
     * @throws RemoteException
     */
    public boolean registerUser(String username, String password) throws RemoteException;

    /**
     * add meeting
     *
     * @param username 
     * @param password 
     * @param otherusers 
     * @param start 
     * @param end 
     * @param title 
     * @return the result information
     * @throws RemoteException
     */
    public String addMeeting(String username, String password, String[] otherUsers,
                             String start, String end, String title) throws RemoteException;

    /**
     * query meeting
     *
     * @param username 
     * @param password 
     * @param start 
     * @param end 
     * @return 
     * @throws RemoteException
     */
    public String queryMeeting(String username, String password, String start, String end) throws RemoteException;

    /**
     * delete meeting
     *
     * @param username 
     * @param password 
     * @param meetingID 
     * @return true if delete successfully 
     * @throws RemoteException
     */
    public boolean deleteMeeting(String username, String password, int meetingID) throws RemoteException;

    /**
     * clear meeting
     *
     * @param username 
     * @param password 
     * @return true if clear
     * @throws RemoteException
     */
    public boolean clearMeeting(String username, String password) throws RemoteException;
}

定义好接口以后,就是接口的实现;
MeetingInstance:
这里不要忘记前面的接口要继承过来,而且同时还要继承UnicastRemoteObject类

package ssd8.rmi.server;

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

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

/**
 * @author ly
 */
public class MeetingInstance extends UnicastRemoteObject implements MeetingInterface {

    private ArrayList<User> users = new ArrayList<>();
    private ArrayList<Meeting> meetings = new ArrayList<>();

    private static int meetingID = 0;
    private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH:mm");



    public MeetingInstance() throws RemoteException {
        super();
    }

    @Override
    public boolean registerUser(String username, String password) throws RemoteException {
        for (User user : users) {
            if (isUserExist(username)) {
                System.out.println(userRegisterFailure);
                return false;
            }
        }
        User user = new User(username, password);
        users.add(user);
        System.out.println(user.toString() + userRgisterSuccessfully);
        return true;
    }

    @Override
    public String addMeeting(String username, String password, String[] otherUserNames, String start, String end, String title) throws RemoteException {

        String info = null;

        ArrayList<User> otherUsers = new ArrayList<>();
        User launchUser = new User(username, password);

        Date startTime = null;
        Date endTime = null;

/*
 * judge if the format is correct
 */
        try {
            startTime = dateFormat.parse(start);
            endTime = dateFormat.parse(end);
        } catch (ParseException e) {
            info = timeFormatInvalid;
            e.printStackTrace();
            return info;
        }


       /*
        * judge if the time overlap
        */
        if (isOverlap(startTime, endTime)||isReversed(startTime, endTime)) {
            info = wrongTime;
            return info;
        }

      /*
       * judge if the user exist
       */
        if (!isUserExist(launchUser)) {
            info = unregisterUser;
            return info;
        }

      /*
       * judge if the other user exist and the number is correct
       */
        if (otherUserNames.length < 1 || !isUsersExist(otherUserNames)) {
            info = unregisterUser;
            return info;
        }else {
            for (String temp : otherUserNames){
                for (User user : users){
                    if (user.getName().equals(temp)){
                        otherUsers.add(user);
                    }
                }
            }
        }

      /*
       * add meeting
       */
        Meeting meeting = new Meeting(meetingID++, title, startTime, endTime, launchUser, otherUsers);
        meetings.add(meeting);
        info = addMeetingSuccessfully;

        return info;
    }



    /**
     *
     * @param startTime 
     * @param endTime   
     * @return whether overlap
     */
    private boolean isOverlap(Date startTime, Date endTime) {
        boolean isOverlap = false;
        for (Meeting meeting : meetings) {
            if (isOverlap(meeting.getStartTime(), meeting.getEndTime(), startTime, endTime)) {
                isOverlap = true;
                return isOverlap;
            }
        }
        return isOverlap;
    }

    /**
     * judge if the time reverse
     *
     * @param former 
     * @param latter 
     * @return 
     */
    private boolean isReversed(Date former, Date latter){
        return former.after(latter);
    }

    /**
     * judge if [st1 et1] overlap [st2 et2]
     *
     * @param st1 
     * @param et1 
     * @param st2 
     * @param et2 
     * @return whether overlap
     */
    private boolean isOverlap(Date st1, Date et1, Date st2, Date et2) {
        boolean isOverlap = isBetween(st2, st1, et1) || isBetween(et2, st1, et1) || isBetween(st1, st2, et2) ||
                st1.equals(st2) || et1.equals(et2);
        return isOverlap;
    }

    /**
     * judge if the date in range [former latter]
     *
     * @param date   
     * @param former 
     * @param latter 
     * @return 
     */
    private boolean isBetween(Date date, Date former, Date latter) {
        boolean isBetween = (date.after(former) && date.before(latter))
                || date.equals(former) && date.equals(latter);
        return isBetween;
    }

    /**
     *
     * @param usernames
     * @return
     */
    private boolean isUsersExist(String[] usernames) {
        boolean isAllExist = true;
        for (String username : usernames) {
            if (!isUserExist(username)) {
                isAllExist = false;
                break;
            }
        }
        return isAllExist;
    }

    /**
     * judge if the user exist
     *
     * @param username 
     * @return whether exist or not
     */
    private boolean isUserExist(String username) {
        boolean isExist = false;
        for (User user : users) {
            if (user.getName().equals(username)) {
                isExist = true;
                break;
            }
        }
        return isExist;
    }

    /**
     * judge if the user exist
     *
     * @param user 
     * @return exist or not
     */
    private boolean isUserExist(User user) {
        boolean isExist = false;
        for (User temp : users) {
            if (temp.equals(user)) {
                isExist = true;
                break;
            }
        }
        return isExist;
    }
}

最后就是客户端和服务器的实现:
首先说服务器RMIServer

package ssd8.rmi.server;

import ssd8.rmi.rface.MeetingInterface;

import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;

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

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

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

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

最后就是客户端RMIClient:

package ssd8.rmi.client;

import ssd8.rmi.rface.MeetingInterface;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.Arrays;

/**
 * 
 *
 * @author ly
 *
 */
public class RMIClient {

	private static final String inputWrongParameter = "wrong parameter!";
	private static final String operateSuccess = "operate successfully!";
	private static final String operateFailure = "operate failed!";
	private static final String timeFormat = "time format:yyyy-MM-dd-HH:mm";
	private static BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));

	/**
	 * 
	 */

	private static String username = null;
	private static String password = null;

	public static MeetingInterface rmi;

	public static void main(String[] args) {
		/**
		 * get the console command
		 */
		try {
			if (args.length < 3) {
				System.err.println(inputWrongParameter);
				System.exit(0);
			}
			String host = args[0];
			String port = args[1];

			/*
			 * connect the server according to the ip and port 这里就是根据主机端口号寻找名字服务器
			 */
			rmi = (MeetingInterface) Naming.lookup("//" + host + ":" + port + "/Meeting");

			/**
			 * check the register mainloop
			 */
			if (args[2].equals("register")) {
				if (args.length != 5) {
					System.err.println(inputWrongParameter);
					System.exit(0);
				}
				boolean flag = rmi.registerUser(args[3], args[4]);
				if (!flag) {
					System.err.println(operateFailure);
				} else {
					username = args[3];
					password = args[4];
					System.out.println("register "+username+" " + operateSuccess);
				}
			} else {
				//other mainloop
				username = args[3];
				password = args[4];
				String[] cmds = Arrays.copyOfRange(args, 5, args.length);
				mainloop(cmds);
			}
			/**
			 * the help menu
			 */
			helpMenu();

			/**
			 * other mainloop
			 */
			while (true) {
				System.out.println("Input an operation: ");
				String operation = bufferedReader.readLine();
				String[] cmds = operation.split(" ");
				mainloop(cmds);
			}

		} catch (RemoteException e) {
			e.printStackTrace();
		} catch (NotBoundException e) {
			e.printStackTrace();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * deal with the command
	 *
	 * @param cmds
	 *            
	 */
	private static void mainloop(String[] cmds) throws RemoteException {

		if (cmds[0].equals("add")) {
			dealAdd(cmds);
		} else if (cmds[0].equals("delete")) {
			dealDelete(cmds);
		} else if (cmds[0].equals("clear")) {
			dealClear();
		} else if (cmds[0].equals("query")) {
			dealQuery(cmds);
		} else if (cmds[0].equals("help")) {
			helpMenu();
		} else if (cmds[0].equals("quit")) {
			System.exit(0);
		} else if (cmds[0].equals("register")) {
			boolean flag = rmi.registerUser(cmds[1], cmds[2]);
			if (!flag) {
				System.err.println(operateFailure);
			} else {
				username = cmds[1];
				password = cmds[2];
				System.out.println("register "+username+" " + operateSuccess);
			}
		}else
			System.err.println(inputWrongParameter);
	}



	/**
	 * add the meeting according to the command 
	 *
	 * @param cmds
	 *            
	 * @throws RemoteException
	 */
	private static void dealAdd(String[] cmds) throws RemoteException {
		String info;
		if (cmds.length < 5) {
			info = inputWrongParameter;
			System.err.println(info);
		} else {
			String[] otherUserNames = Arrays.copyOfRange(cmds, 1, cmds.length - 3);
			info = rmi.addMeeting(username, password, otherUserNames, cmds[cmds.length - 3], cmds[cmds.length - 2],
					cmds[cmds.length - 1]);
			System.out.println(info);
		}
	}

	/**
	 * delete the meeting according to the command
	 *
	 * @param cmds
	 *            
	 * @throws RemoteException
	 */
	private static void dealDelete(String[] cmds) throws RemoteException {
		if (cmds.length != 2) {
			System.err.println(inputWrongParameter);
		} else {
			boolean flag = rmi.deleteMeeting(username, password, Integer.parseInt(cmds[1]));
			if (flag) {
				System.out.println(operateSuccess);
			} else
				System.err.println(operateFailure);
		}
	}

	/**
	 * clear the meeting according to the command
	 *
	 * @throws RemoteException
	 */
	private static void dealClear() throws RemoteException {
		boolean flag = rmi.clearMeeting(username, password);
		if (flag) {
			System.out.println(operateSuccess);
		} else
			System.err.println(operateFailure);
	}

	/**
	 * query the meeting according to the command
	 *
	 * @param cmds
	 *            
	 * @throws RemoteException
	 */
	private static void dealQuery(String[] cmds) throws RemoteException {
		if (cmds.length != 3) {
			System.err.println(inputWrongParameter);
		} else {
			String info = rmi.queryMeeting(username, password, cmds[1], cmds[2]);
			System.out.println(info);
		}
	}
}
/*
 *  2018-12-28-12:00 2018-12-28-13:00
 *  
 *  test case:
 *  register a a
 *  add a 2018-12-28-12:00 2018-12-28-13:00 test
 *  query 2018-12-28-11:00 2018-12-28-14:00
 *  delete 0
 *  query 2018-12-28-11:00 2018-12-28-14:00
 *  add a 2018-12-28-12:00 2018-12-28-13:00 test
 *  query 2018-12-28-11:00 2018-12-28-14:00
 *  clear
 *  query 2018-12-28-11:00 2018-12-28-14:00
 *  
 *  restart:
 *  register a a
 *  register c c
 *  add a c b 2018-12-28-12:00 2018-12-28-13:00 test
 *  add a c 2018-12-28-12:00 2018-12-28-13:00 test1
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值