1,什么是 RMI?
(1)RMI(Remote Method Invocation)是 Java 的一种远程方法调用技术,它允许你从一个 Java 程序调用另一个 Java 程序的方法,即使这两个程序位于不同的计算机上。
(2)RMI 是一种用于实现远程过程调用(RPC,Remote procedure call)的 Java API, 能直接传输序列化后的 Java 对象和分布式垃圾收集。它的实现依赖于Java虚拟机(JVM),因此它仅支持从一个 JVM 到另一个 JVM 的调用。
(3)RMI 使得开发人员可以创建分布式应用程序,其中一个 Java 程序可以调用另一个 Java 程序上的方法,就好像调用本地对象的方法一样。
2,RMI 的工作流程
(1)首先,服务器创建一个远程对象并将其注册到注册表中。
(2)客户端可以获取注册表中存储的对象的引用
(3)当客户端调用远程对象的方法时,实际上会在与客户端 JVM 在同一 JVM 中的存根对象(Stub)上调用该方法。
(4)存根对象(Stub)会创建一条消息,其中包含方法的名称以及其参数(称为封装),并将此消息发送到位于服务器 JVM 中的相关骨架对象(Skeleton)。
(5)骨架对象(Skeleton)会从消息中提取方法名和参数(称为解封装),并调用与其关联的远程对象上的适当方法。
(6)远程对象执行该方法并将返回值传回骨架对象(Skeleton)。
(7)骨架对象(Skeleton)再将返回值封装在消息中并将此消息发送到存根对象(Stub)。
(8)存根对象(Stub)从消息中解封装返回值,并将该值返回给客户端程序
3,基本用法
(1)首先,我们需要定义一个远程接口,该接口中包含要在远程调用的方法:
注意:可以远程的接口必须扩展 RMI 定义的 Remote 接口。并且该接口中的每个方法都必须声明抛出 java.rmi.RemoteException 异常,因为这些方法是远程调用的,存在许多可能导致失败的因素,例如网络故障等。
1 2 3 |
|
(2)接下来,我们需要实现该接口,并提供实际的方法实现:
注意:远程对象必须继承 UniCastRemoteObject 类,保证客户端访问获得远程对象时,该远程对象将会把自身的一个拷贝以 Socket 的形式传输给客户端。
1 2 3 4 5 6 7 8 9 10 11 |
|
(3)接下来,我们需要创建一个 RMI 服务器来提供远程访问:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
- 启动服务器运行结果如下:
(4)接下来,我们可以创建一个客户端来远程调用服务器上的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
- 在保持服务端运行的情况下,运行客户端。如果一切顺利,客户端将输出如下内容:
你好,henry
4,序列化传输对象
(1)如果需要传输自定义对象时,传输的类一定要实现序列化接口(Serializable),不然传输时会报错。
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 |
|
(2)我们修改下远程接口以及接口的实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
(3)客户端代码修改如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
- 在保持服务端运行的情况下,运行客户端。如果一切顺利:
5,超时设置
(1)在使用 RMI 时,可能会遇到连接超时的情况。我们可以设置超时时间,这样当客户端在尝试连接服务器时等待的时间超过了预定义的超时时间时便会抛出异常。
提示:在 RMI 中,可以通过设置系统属性 sun.rmi.transport.tcp.responseTimeout 来设置连接超时时间。该属性控制 RMI 在接收到服务器的响应之前等待的时间(以毫秒为单位)。
(2)我们可以在启动 JVM 时使用 -D 选项来设置该属性(这将设置超时时间为 10 秒):
1 |
|
(3)也可以通过调用 System.setProperty 方法来设置该属性:
1 |
|