Java RMI
Java RMI
什么是Java RMI
Java远程方法调用,即Java RMI(Java Remote Method Invocation)是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口。它使客户机上运行的程序可以调用远程服务器上的对象。远程方法调用特性使Java编程人员能够在网络环境中分布操作。RMI全部的宗旨就是尽可能简化远程接口对象的使用。
Java RMI极大地依赖于接口。在需要创建一个远程对象的时候,程序员通过传递一个接口来隐藏底层的实现细节。客户端得到的远程对象句柄正好与本地的根代码连接,由后者负责透过网络通信。这样一来,开发者只需关心如何通过自己的接口句柄发送消息。
接口的两种常见实现方式是:最初使用JRMP(Java Remote Message Protocol,Java远程消息交换协议)实现;此外还可以用与CORBA兼容的方法实现。RMI一般指的是编程接口,也有时候同时包括JRMP和API(应用程序编程接口),而RMI-IIOP则一般指RMI接口接管绝大部分的功能,以支持CORBA的实现。
最初的RMI API设计为通用地支持不同形式的接口实现。后来,CORBA增加了传值(pass by value)功能,以实现RMI接口。然而RMI-IIOP和JRMP实现的接口并不完全一致。
所使用Java包的名字是java.rmi
。
RMI应用程序的概念
RMI应用程序可以分为两部分,客户端程序和服务器程序。一个服务器程序创建一些远程对象,使其可用于客户端的引用调用方法就可以了。一个客户端的远程程序申请数据服务器和调用它们的方法的对象。存根和骨架是用于与远程对象通信的两个重要对象。
Stub(存根)
在RMI中,Stub
是一个对象,用作客户端的网关。 所有传出的请求都通过它发送。 当客户端在存根对象上调用该方法时,将在内部执行以下操作:
- 使用远程虚拟机建立连接。
- 然后,它将参数传输到远程虚拟机。 这也称为法警
- 在第二步之后,它将等待输出。
- 现在,它读取作为输出来的值或异常。
- 最后,它将值返回给客户端。
Skeleton(骨架)
在RMI中,Skeleton
是一个对象,用作服务器端的网关,所有传入的请求都通过它发送。 当服务器在Skeleton
对象上调用该方法时,将在内部执行以下操作:
- 读取所有参数以获取远程方法。
- 该方法在远程对象上调用。
- 然后,它写入并传输结果的参数。
Stub 和 Skeleton
Stub
充当客户端程序的网关。 它位于客户端,并与Skeleton对象通信。 它建立远程对象之间的连接并向其发送请求。
Skeleton
对象驻留在服务器程序上。 它负责将请求从存根传递到远程对象。
创建一个简单RMI应用示例步骤
- 定义一个远程接口。
- 实现远程接口。
- 创建并启动远程应用程序
- 创建并启动客户端应用程序
定义一个远程接口
远程接口指定客户端可以远程调用的方法。 客户端程序与远程接口通信,而不是与实现它的类通信。 要成为远程接口,接口必须扩展java.rmi
包的Remote
接口。
Remote 接口
1 | package java.rmi; |
创建远程接口
AddServiceInterface.java
1 | import java.rmi.Remote; |
实现远程接口
为了实现远程接口,类必须扩展UnicastRemoteObject
或使用UnicastRemoteObject
类的exportObject()
方法。
Adder.java
1 | import java.rmi.RemoteException; |
创建 RegistryServer服务
RMI注册表是一个放置所有服务器对象的名称空间。 每次服务器创建一个对象时,它将向RMIregistry注册该对象(使用bind() 或reBind() 方法)。 这些使用唯一的名称(称为绑定名称)注册。
要调用远程对象,客户端需要该对象的引用。 那时,客户端使用其绑定名称(使用lookup() 方法)从注册表中获取对象。
下图说明了整个过程:
RegistryServer.java
1 | import java.io.IOException; |
创建AddServer服务
需要创建一个服务器应用程序并在其中托管rmi服务Adder
。 这是使用java.rmi.Naming
类的rebind()
方法完成的。 rebind
方法带有两个参数,第一个表示对象引用的名称,第二个参数是对Adder
实例的引用。
1 | import java.rmi.AlreadyBoundException; |
创建客户端程序
客户端应用程序包含一个Java程序,该程序调用Naming类的lookup()
方法。 此方法接受一个参数rmi URL,并返回对AddServerInterface
类型的对象的引用。 所有远程方法调用都在此对象上完成。
1 | import java.rmi.NotBoundException; |
RMI 的目标
- 为了最小化应用程序的复杂性。
- 为了保持类型安全。
- 分布式垃圾回收。
- 最小化使用本地对象和远程对象之间的差异。
总结
Java RMI是远程过程调用(RPC)的纯Java解决方案,用于在Java中创建分布式应用程序。Stub和Skeleton对象用于客户端和服务器端之间的通信。