RMI(Remote Method Invocation,远程方法调用),用于不同虚拟机之间的通信,允许运行在一个java虚拟机的对象去调用运行在另外一个java虚拟机对象的方法。
JRMP(Java Remote Messaging Protocol)是专为Java制定的远程对象协议,所以,RMI是分布式应用系统的纯Java解决方案。
客户端:请求服务端的远程对象,并尝试调用远程对象的方法。
服务端:创建一个远程对象,把对象的引用注册到注册表中,提供给客户端使用。
Stub:位于客户端,是远程对象在本地的代理,也就是说虽然我们调用的是本地对象,实际上调用的是远程对象。
Skeleton:位于服务器端,是服务端对象的代理。Stub与之通信。
RRL(Remote Reference Layer,远程引用层):管理客户端对远程对象引用的层
Transport Layer(传输层):连接客户端和服务器。管理现有的连接及设置新的连接。
RMI Registry提供服务注册与服务获取。
服务器创建对象时,会通过 bind()
或 reBind()
方法向RMI Registry注册对象的信息,这个时候要提供RMI Registry的地址、端口以及对象的路径、对象的引用。
客户端需要调用远程对象时,调用 lookup()
方法,也是要提供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)); } }
运行结果: