概述
Java远程方法调用(Remote Method Invocation, RMI)是Java的一个核心API和类库,
允许一个Java虚拟机上运行的Java程序调用不同虚拟机上运行的对象中的方法,即使这两个
虚拟机运行于物理隔离的不同主机上。在某种程度上,RMI可以看成RPC的Java升级版。
和RPC一样,存在服务端和客户端
典型服务器端应用程序 创建多个远程对象(Remote Object),使这些对象能被客户端引用,并等待客户端调用远程对象的方法
典型的客户端程序 从服务器获得一个或多个远程对象的引用,然后调用远程对象的方法
Java远程方法调用依赖于Java序列化,调用远程方法传的参数、返回值都是序列化对象
远程方法调用实例
1 2 3 4 5 6 7 8 9
| import java.rmi.Remote; import java.rmi.RemoteException;
public interface RMIQueryStatus extends Remote {
String getStatus(String name) throws RemoteException;
}
|
RMIQueryStatus的定义要求
- 远程接口必须声明为public,否则客户端试着装载“实现远程接口”的远端对象时,会收到错误的消息。
- 远程接口必须继承自java.rmi.Remote。
- 远程接口中的每-一个方法,除了自定义的异常之外,必须将java.rmi.RemoteException
声明于其throws子句中。
- 在远程方法声明中,作为参数或者返回值的远程对象,或者包含在其他非远程对象中
的远程对象,必须声明为其对应的远程接口,而不是实际的实现类。(这点在String类中并没有体现)
RMIQueryStatus的实现类
1 2 3 4 5 6 7 8 9 10 11 12
| import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject;
public class RMIQueryStatusImp extends UnicastRemoteObject implements RMIQueryStatus { protected RMIQueryStatusImp() throws RemoteException { }
public String getStatus(String name) throws RemoteException { return "I'm " + name + "."; } }
|
客户端和服务端的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry;
public class RMIDemoServer { public static void main(String[] args) throws RemoteException, MalformedURLException { RMIQueryStatusImp queryService = new RMIQueryStatusImp();
LocateRegistry.createRegistry(12090);
Naming.rebind("rmi://localhost:12090/queryTest", queryService); System.out.println("Server is running!"); } }
import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException;
public class RMIDemoClient { public static void main(String[] args) throws RemoteException, NotBoundException, MalformedURLException { RMIQueryStatus queryStatus = (RMIQueryStatus) Naming.lookup("rmi://localhost:12090/queryTest");
String status = queryStatus.getStatus("KiKi");
System.out.println(status); } }
|
先运行服务端然后运行客户端查看结果
Java远程调用实例类图
客户端RMIQueryStatusClient的工作依赖于RMI存根(Stub),这个存根是通过Java的代理机制 java.lang.reflect.Proxy