1、RMI的工作原理
(1)启动RMI注册对象在一个端口上监听对外提供的接口;
(2)客户端通过proxy代理访问服务器接口,RMI客户端将要访问的对象字符串、方法、参数封装成一个序列化对象传到RMI服务器端
(3)服务器端接到请求后,反序列化接收到的对象,并从RMI注册对象上找到提供服务的对象,传入客户端发送来的参数完成服务端对象的调用,返回结果给客户端
(4)客户端接收到服务器端发送来的流之后,反序列化接收流得到对象给调用者
2、RMI的实现
(1)定义一个接口,继承Remote接口
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Bussiness extends Remote{
public String echo(String message) throws RemoteException; //此处要抛出RemoteException异常
}
(2)定义一个类,实现上面定义的接口
import java.rmi.RemoteException;
public class BussinessImpl implements Bussiness{
@Override
public String echo(String message) throws RemoteException {
// TODO Auto-generated method stub
if("quit".equals(message)){
System.out.println("client is shutdown");
System.exit(0);
}
System.out.println("message From client is "+message);
return "Server Response"+message;
}
}
(3)定义一个Server类,提供RMI服务
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.concurrent.ConcurrentHashMap;
public class Server {
/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
int port = 9000;
String name = "businessDemo"; //定义与提供服务接口相对应的名字
Bussiness bussiness = new BussinessImpl();
UnicastRemoteObject.exportObject(bussiness,port); //在port接口注册bussiness接口
Registry registry = LocateRegistry.createRegistry(1099); //此端口号不可变
registry.bind(name, bussiness); //把bussiness接口与name绑定在一起
}
}
(4)定义一个Client类,调用Server提供的方法
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Client {
/**
* @param args
*/
public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
Registry registry = LocateRegistry.getRegistry("localhost"); //获取制定地址的注册器
String name = "businessDemo";
Bussiness bussiness = (Bussiness)registry.lookup(name); //通过名字来查找相对应的接口服务
bussiness.echo("hello lixia"); //调用远程方法
}
}
3、总结
基于远程调用方式实现系统间的通信存在的缺点:
1、由于远程调用带来的网络问题
2、超时问题
3、序列化/反序列化问题
4、调试复杂问题