RMI
远程调用的时候,其核心就是远程调用其他主机上或者jvm上的类的相关方法,而远程调用过程中传输的数据内容是以序列化的形式传输的,必要的时候可能还会传输对象的引用等(当然也是以序列化的方式传输),传输的格式是基于JRMP协议的。
JRMP是 Java Remote Message Protocol 的缩写,java远程通信协议。主要就是为进程间、主机间java进程之间通信制定的协议,其是基于TCP的流量协议。
RMI中由三部分构成,Registry、Server 、Client
Server:
定义一个接口类,这个接口类要继承Remote接口,其中定义一个接口方法(此方法就是之后要远程调用的方法)并且该接口方法要爬出RemoteException异常,然后在其实现类中重写接口方法的实现,并且实现类要继承UnicastRemoteObject类(这个类的相关方法作用于导出对象(存根/Stub)的处理以及JRMP的处理,当然这里其实也不是说一定要继承这个类,也可以通过其他方法手动导出,但是后文中都是以继承UnicastRemoteObject类这种方法)
接口类Hello:
1 2 3 4 5 6 7 8 9
| package newrmi; import java.rmi.Remote; import java.rmi.RemoteException; public interface Hello extends Remote {
public String welcome(String name) throws RemoteException; }
|
实现类Helloimp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package com.javatest; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject;
public class Helloimp extends UnicastRemoteObject implements Hello{ public Helloimp() throws RemoteException { } @Override public String welcome(String name) throws RemoteException { return "hello"+name; } }
|
准备好之后还需要把这个远程对象绑定到Registry中,所以这里我们接下来先看下Registry实现
Registry:
使用LocateRegistry.createRegistry方法开启一个注册中心,然后server将刚刚准备的远程对象绑定到注册中心:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package com.javatest;
import java.rmi.AlreadyBoundException; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry;
public class RmiRegistryAndServer { public static void main(String args) { try { Registry registry = LocateRegistry.createRegistry(9999); Hello hello = new Helloimp(); registry.bind("hellos",hello); System.out.println("open port for rmi for 9999:hellos"); } catch (RemoteException | AlreadyBoundException e) { e.printStackTrace(); } } }
|
Client:
客户端 去注册中心获取相关对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.javatest;
import java.rmi.NotBoundException; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry;
public class Client { public static void main(String[] args) { try { Registry registry = LocateRegistry.getRegistry("localhost", 9999); Hello hello = (Hello) registry.lookup("hellos"); System.out.println(hello.welcome("axin")); } catch (RemoteException e) { e.printStackTrace(); } catch (NotBoundException e) { e.printStackTrace(); } } }
|
运行client:如下,可以看到相关方法被调用了:

以上是rmi过程中我们见到最多的常见,客户端向Registry lookup一个名称,最终实现对某个远程方法的调用。
