给个关注?宝儿!
给个关注?宝儿!
给个关注?宝儿!
1.RMI 是什么
RMI(Remote Method Invocation)即Java远程方法调用,RMI用于构建分布式应用程序,RMI实现了Java程序之间跨JVM的远程通信。
RMI底层通讯采用了Stub(运行在客户端)和Skeleton(运行在服务端)机制,RMI调用远程方法的大致如下:
1.RMI客户端在调用远程方法时会先创建2.Stub(sun.rmi.registry.RegistryImpl_Stub)。
Stub会将Remote对象传递给远程引用层(java.rmi.server.RemoteRef)并创建java.rmi.server.RemoteCall(远程调用)对象。
3.RemoteCall序列化RMI服务名称、Remote对象。
4.RMI客户端的远程引用层传输RemoteCall序列化后的请求信息通过Socket连接的方式传输到RMI服务端的远程引用层。
5.RMI服务端的远程引用层(sun.rmi.server.UnicastServerRef)收到请求会请求传递给6.Skeleton(sun.rmi.registry.RegistryImpl_Skel#dispatch)。
7.Skeleton调用RemoteCall反序列化RMI客户端传过来的序列化。
Skeleton处理客户端请求:bind、list、lookup、rebind、unbind,如果是lookup则查找RMI服务名绑定的接口对象,序列化该对象并通过RemoteCall传输到客户端。
8.RMI客户端反序列化服务端结果,获取远程对象的引用。
9.RMI客户端调用远程方法,RMI服务端反射调用RMI服务实现类的对应方法并序列化执行结果返回给客户端。
10.RMI客户端反序列化RMI远程方法调用结果。
Back
2.RMI远程方法调用测试
第一步我们需要先启动RMI服务端,并注册服务。
RMI服务端注册服务代码:
package com.anbai.sec.rmi;
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
public class RMIServerTest {
// RMI服务器IP地址
public static final String RMI_HOST = "127.0.0.1";
// RMI服务端口
public static final int RMI_PORT = 9527;
// RMI服务名称
public static final String RMI_NAME = "rmi://" + RMI_HOST + ":" + RMI_PORT + "/test";
public static void main(String[] args) {
try {
// 注册RMI端口
LocateRegistry.createRegistry(RMI_PORT);
// 绑定Remote对象
Naming.bind(RMI_NAME, new RMITestImpl());
System.out.println("RMI服务启动成功,服务地址:" + RMI_NAME);
} catch (Exception e) {
e.printStackTrace();
}
}
}
程序运行结果:
copyRMI服务启动成功,服务地址:rmi://127.0.0.1:9527/test
Naming.bind(RMI_NAME, new RMITestImpl())绑定的是服务端的一个类实例,RMI客户端需要有这个实例的接口代码(RMITestInterface.java),RMI客户端调用服务器端的RMI服务时会返回这个服务所绑定的对象引用,RMI客户端可以通过该引用对象调用远程的服务实现类的方法并获取方法执行结果。
RMITestInterface示例代码:
package com.anbai.sec.rmi;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* RMI测试接口
*/
public interface RMITestInterface extends Remote {
/**
* RMI测试方法
*
* @return 返回测试字符串
*/
String test() throws RemoteException;
}
这个区别于普通的接口调用,这个接口在RMI客户端中没有实现代码,接口的实现代码在RMI服务端。
服务端RMITestInterface实现代码示例代码:
package com.anbai.sec.rmi;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class RMITestImpl extends UnicastRemoteObject implements RMITestInterface {
private static final long serialVersionUID = 1L;
protected RMITestImpl() throws RemoteException {
super();
}
/**
* RMI测试方法
*
* @return 返回测试字符串
*/
@Override
public String test() throws RemoteException {
return "Hello RMI~";
}
}
RMI客户端示例代码:
package com.anbai.sec.rmi;
import java.rmi.Naming;
import static com.anbai.sec.rmi.RMIServerTest.RMI_NAME;
public class RMIClientTest {
public static void main(String[] args) {
try {
// 查找远程RMI服务
RMITestInterface rt = (RMITestInterface) Naming.lookup(RMI_NAME);
// 调用远程接口RMITestInterface类的test方法
String result = rt.test();
// 输出RMI方法调用结果
System.out.