RMI概述
远程方法调用就是本地对象能够调用远程对象的方法。它使得某一台计算机上的对象在调用另外一台计算机上的方法时,使用的程序语法规则和在本地机上对象间的方法调用的语法规则一样。
其优点在于这种机制给分布计算的系统设计、编程都带来了极大的方便。只要按照RMI规则设计程序,可以不必再过问在RMI之下的网络细节了(如TCP和Socket等)。任意两台计算机之间的通讯完全由RMI负责。调用远程计算机上的对象就像本地对象一样方便。现在流行的j2ee中的EJB的底层实现技术就是RMI,EJB的调用就是经过封装的,更高级的RMI调用。
创建RMI程序的步骤
1. 定义一个远程接口,该接口中的每一个方法必须声明它将产生一个RemoteException异常。
2. 定义一个实现该接口的类。
3. 使用rmic程序生成远程实现所需的Stub。
4. 创建一个服务端程序,用于发布(2)中的类。
5. 创建一个客户端程序进行RMI调用。
6. 启动rmiRegistry并运行远程服务端程序和客户端程序。
具体步骤及代码
1. 定义远程接口
package eric.rmi;
import java.rmi.*;
public interface MyRemote extends Remote {
public String sayHello() throws RemoteException;
}
2. 定义实现远程接口的类
package eric.rmi;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {
public MyRemoteImpl() throws RemoteException {}
public String sayHello() {
return "Server says, 'Hey'";
}
}
3. 使用rmic生成stub
在class文件所在的目录下(即bin目录下)执行以下命令。该命令将生成一个MyRemoteImpl_Stub.class文件。
rmic eric.rmi.MyRemoteImpl
4. 创建服务器端程序
package eric.rmi;
import java.rmi.Naming;
public class MyRemoteServer {
public static void main(String[] args) {
try {
MyRemote service = new MyRemoteImpl();
Naming.rebind("RemoteHello", service);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
5. 创建客户端程序
Naming.lookup()中的IP地址为服务器端的IP。如果是本地运行可以使用127.0.0.1。
package eric.rmi;
import java.rmi.*;
public class MyRemoteClient {
public static void main(String[] args) {
new MyRemoteClient().go();
}
public void go() {
try {
MyRemote service = (MyRemote) Naming.lookup("rmi://192.168.1.111/RemoteHello");
String s = service.sayHello();
System.out.println(s);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
6. 部署
(1) 在客户端需要有MyRemoteClient.class, Remote.class和MyRemoteImpl_Stub.class文件。不需要服务器端程序。
(2) 在服务器端需要有MyRemoteServer.class, Remote.class, MyRemoteImpl和MyRemoteImpl_Stub文件。
(3) 在服务器端开启RMI注册服务。
start rmiregistry
只有在启动了这个服务之后,server端程序才能调用rebind方法发布我们的类。
(4) 运行服务器端程序。(在bin目录下执行命令)
java -Djava.rmi.server.codebase=file:\E:\workspace\RMI/ eric.rmi.MyRemoteServer
如果不使用-D参数设置系统属性,系统可能会报找不到Stub类的错误,所以需要这个参数来指定Stub类的路径。
在所有部署中这一步最容易出错。
(5) 运行服务器端程序
java eric.rmi.MyRemoteClient
则将显示sayHello()中返回字符串,说明远程方法调用成功。