Java -- 远程程序调用(Remote Method Invocation RMI)
引言
一般Java的方法调用都是对运行在相同Java虚拟机上的对象进行的,也就是调用方法与被调用方法都是在同一个堆上。
如果要调用不同机器上的对象的方法呢?这就要用到RMI技术。
远程过程调用的设计
要创建出4种东西:服务器、客户端、服务器辅助设施、客户端辅助设施
1.创建客户端和服务器应用程序
2.创建服务器和客户端的 辅助设施(helper)。它们会处理所有客户端和服务器的低层网络输入/输出细节,让你的客户端和程序好像在处理本机的调用一样。
辅助设施的任务
辅助设施是个实际上执行通信的对象。让你的客户端和程序好像在处理本机的调用一样。客户端以为它调用的是远程服务,因为辅助设施假装成该服务对象。
但客户度辅助设施不是真正的远程服务,它没有真正客户端需要的方法逻辑。相反,辅助设施会去连接服务器,将调用信息传送过去(比如方法的名称和参数),然后等待服务器响应。
服务器端,服务器辅助设施通过socket连接来自客户端辅助设施的要求,解析打包来的信息,然后调用真正的服务。因此对服务对象来说此调用来自本地。
服务器辅助设施取得返回值后送回去(通过socket输出串流)给客户端辅助设施。客户端辅助设施会解开这些信息传给客户端对象。

Java RMI 提供客户端和服务器端的辅助设施对象
在Java中 RMI已经帮你创建好客户端和服务器端的辅助设施。
RMI中 客户端的辅助设施称为stub,服务器端的辅助设施称为skeleton
RMI 的协议
使用RMI时有2种协议: JRMP或是IIOP
JRMP:RMI的原生协议,它是为了Java对Java间的远程调用而设计的。
IIOP:为了CORBA(Common Object Request Broker Architecture)而产生的,它让你能够调用Java对象或其他类型的远程方法。
CORBA通常比RMI麻烦,因为若两端不全都是Java的话,就会发生一些可怕的转译和交谈操作。
创建远程服务
步骤1:创建远程接口
// 1.继承java.rmi.Remote
// Remote是个标记性接口,没有方法。接口是可以继承其他接口的,使用extends关键字。
// 2.声明所有方法都会抛出java.rmi.RemoteException
// 3.确定所有参数和返回值类型都是基本类型或可序列化的对象
// 任何远程方法的参数都会被打包通过网络传送,而这是通过序列化实现的。返回值也一样。
public interface MyRemote extends Remote {
public String sayHello() throws java.rmi.RemoteException;
}
步骤2:实现远程接口
// 继承java.rmi.server.UnicastRemoteObject
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {
// 1.实现MyRemote接口
// 2.提供一个无参构造器,调用父类的无参构造器
public MyRemoteImpl() throws java.rmi.RemoteException {
}
// 3.实现sayHello方法
@Override
public String sayHello() {
return "Server says, 'Hey there!'";
}
public static void main(String[] args) {
try {
// 4.创建MyRemoteImpl对象
MyRemoteImpl remote = new MyRemoteImpl();
// 5.注册远程对象到RMI注册表.RMI系统会把stub加到注册表中
java.rmi.Naming.rebind("Remote Hello", remote);
System.out.println("Server is ready.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
步骤3:产生stub和skeleton
1.对实现出的类执行rmic。 从实现类所在目录执行rmic。
rmic 编译 器 (JDK自带)根据 编译 后的 Java 类 (含有 远 程 对 象 实现 )名,为远程对象生成 stub 和 skeleton( 远 程 对 象是指 实现 java.rmi .Remote 接口的 对 象)。在 rmic 命令中所 给 的 类 必 须 是 经 javac 命令成功 编译 且是完全包限定的 类 。
命令代码:rmic MyRemoteImpl
从 Java 11 开始,rmic 工具已被移除
步骤4:执行rmiregistry
从类这个目录来运行。
命令代码:rmiregistry
RMI registry 必须在同一台机器上与远程服务一块执行,且必须在对象的注册之前启动。
步骤5:启动服务
调用另一个命令行来启动服务
命令代码:java MyRemoteImpl
客户端程序代码
public class MyRemoteClient {
public static void main(String[] args) {
new MyRemoteClient().go();
}
public void go() {
try {
// 1.客户端查找RMI注册表中的远程对象
// Naming.lookup()方法的参数是一个URL字符串,格式为"rmi://host:port/name"。
// 2.RMI注册表返回stub对象
MyRemote service = (MyRemote) Naming.lookup("rmi:127.0.0.1/Remote Hello");
String s = service.sayHello(); // 2.调用远程方法
System.out.println("Server says: " + s); // 3.输出结果
} catch (Exception e) {
e.printStackTrace();
}
}
}
以上是RMI的简单示例,如果深入探索,也许你会加入Jini查询服务等待,具体如何使用需要读者自己去发现了。
本文来自博客园,作者:NE_STOP,转载请注明原文链接:https://www.cnblogs.com/alineverstop/p/18970587
浙公网安备 33010602011771号