RMI简介
RMI(Remote Method Invocation,远程方法调用),用于不同虚拟机之间的通信,允许运行在一个java虚拟机的对象去调用运行在另外一个java虚拟机对象的方法。
JRMP(Java Remote Messaging Protocol)是专为Java制定的远程对象协议,所以,RMI是分布式应用系统的纯Java解决方案。
RMI架构
客户端:请求服务端的远程对象,并尝试调用远程对象的方法。
服务端:创建一个远程对象,把对象的引用注册到注册表中,提供给客户端使用。
Stub:位于客户端,是远程对象在本地的代理,也就是说虽然我们调用的是本地对象,实际上调用的是远程对象。
Skeleton:位于服务器端,是服务端对象的代理。Stub与之通信。
RRL(Remote Reference Layer,远程引用层):管理客户端对远程对象引用的层
Transport Layer(传输层):连接客户端和服务器。管理现有的连接及设置新的连接。
RMI工作流程
- 当客户端调用远程对象时,由Stub将此请求传递给RRL。
- 当客户端RRL接收到请求时,它将调用remoteRef对象的invoke()方法,这个方法会将请求传递给服务端的RRL。
- 服务器端的RRL将请求传递给Skeleton,Skeleton再调用服务器上对应对象的方法。
- 将结果传回客户。
RMI Registry
RMI Registry提供服务注册与服务获取。
服务器创建对象时,会通过bind()
或reBind()
方法向RMI Registry注册对象的信息,这个时候要提供RMI Registry的地址、端口以及对象的路径、对象的引用。
客户端需要调用远程对象时,调用lookup()
方法,也是要提供RMI Registry的地址、端口,以及所调用远程对象的路径来获取远程对象信息。
服务端和客户端,提供RMI Registry的地址、端口是要找到对应的RMI Registry。
简单例子
创建RMI Registry
RMI Registry注册到9999端口中
public class RmiRegistry {
public static void main(String[] args) throws RemoteException, InterruptedException {
LocateRegistry.createRegistry(9999);
CountDownLatch latch=new CountDownLatch(1);
System.out.println("RmiRegistry已启动");
latch.await();
}
}
运行结果:
服务器注册
GoodsService接口,要继承Remote
public interface GoodsService extends Remote {
String get(int id) throws RemoteException;
}
GoodsServiceImpl实现类,要继承UnicastRemoteObject
public class GoodsServiceImpl extends UnicastRemoteObject implements GoodsService {
protected GoodsServiceImpl() throws RemoteException {
super();
}
@Override
public String get(int id) throws RemoteException{
return "商品ID:" + id;
}
}
RmiServer,先定义继承了UnicastRemoteObject的实现类,再通过ip、端口以及路径,把这个对象注册到RMI Registry。
public class RmiServer {
public static void main(String[] args) throws RemoteException, AlreadyBoundException, MalformedURLException {
GoodsService goodsService = new GoodsServiceImpl();
Naming.bind("//127.0.0.1:9999/goodsService",goodsService);
System.out.println("RmiServer已启动");
}
}
运行结果:
客户端调用
RmiClient,通过ip、端口以及路径,找到远程服务对象,并调用相应方法
public class RmiClient {
public static void main(String[] args) throws RemoteException, NotBoundException, MalformedURLException {
GoodsService goodsService = (GoodsService)Naming.lookup("//127.0.0.1:9999/goodsService");
System.out.println(goodsService.get(123));
}
}
运行结果:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。