Java远程方法调用 ,即Java RMI (Java Remote Method Invocation)是Java编程语言里,一种用于实现远程过程调用 的应用程序编程接口 。它使客户机上运行的程序可以调用远程服务器上的对象。远程方法调用特性使Java编程人员能够在网络环境中分布操作。RMI全部的宗旨就是尽可能简化远程接口对象的使用。
Java RMI极大地依赖于接口。在需要创建一个远程对象的时候,程序员通过传递一个接口来隐藏底层的实现细节。客户端得到的远程对象句柄正好与本地的根代码连接,由后者负责透过网络通信。这样一来,程序员只需关心如何通过自己的接口句柄发送消息。(此段摘自Wiki)
RMI其实是一个远程代理模式,程序员在本地调用的代码实质上是交给了服务器处理接口的请求,并将结果返回。对于程序而言看到的如同在本地调用接口一样的效果。
在这里,我将重点结合Eclipse来讲解如何编写Java RMI。
在讲解之前我们需要以下几个工具 :
Eclipse 3.0 or above
RMIC Eclipse Plugin -- 此工具用来生成RMI的Stub类,下载地址:https://rmic-eclipse-plugin.dev.java.net/
对于需要访问传入到接口的参数的对象都应使他成为一个序列化的对象,即实现Serializable接口,否则数据是无法传入到服务器中。接下来开始代码的讲解
一、首先编写一个接口中的参数类型,此类型也是一个接口
package remote.test;
public interface HelloTask {
public String execute();
}
二、实现这个接口,记住,实现的时候一定要实现Serializeable接口
package remote.test;
import java.io.Serializable;
public class HelloTaskImpl implements HelloTask,Serializable{
private static final long serialVersionUID = 1L;
public String execute() {
return "Hello World";
}
}
三、编写Remote接口
package remote.test;
import java.rmi.RemoteException;
public interface IHello extends java.rmi.Remote{
String say(HelloTask task) throws RemoteException;
}
四、编写Server类
package remote.test.server;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import remote.test.IHello;
import remote.test.HelloTask;
public class HelloServer extends java.rmi.server.UnicastRemoteObject implements
IHello{
private static final long serialVersionUID = 2279096828129284306L;
public HelloServer() throws RemoteException {
super();
}
public String say(HelloTask task) throws RemoteException {
String result = task.execute();
System.out.println("execute say,task.execute : " + result);
return result;
}
public static void main(String[] args) {
try {
HelloServer h = new HelloServer();
Registry registry = LocateRegistry.createRegistry(2500);
registry.bind("hello", h);
System.out.println("Start...");
} catch (Exception e) {
e.printStackTrace();
}
}
}
您看到在HelloServer将会实现IHello中的接口,并执行HelloTask的接口,HelloTask是从客户端那边传送过来,所以执行任务的逻辑将在say方法中由服务端来实现,客户端是不知道服务端如何执行这个HelloTask,他只需要知道执行的结果。
对于服务端代码的编写,这里需要注意的是Registry,Registry是由Java Security管理,如果没有权限getRegistry将会报错,如果使用如下方法获得
Registry registry = LocateRegistry.getRegistry(2500);
就需要注意,在Jar中需要有个*.policy策略文件,如果没有设置这些将会抛出"Access Denied "异常。此方式的编写这里不详细讲解,请搜索网络需找资料。
接下来registry只需要绑定一个名字空间和对象即可开启2500端口开始监听。
五、生成Stub对象
在java环境中生成这个对象需要使用rmic命令以及rmiregistry,这两个命令的用法其实也比较简单,但是无论如何使用起来还是会觉得有点麻烦,在Spring中也有rmi的功能,其实他也就是包装了一下rmi的类,但是他最大的优点在于它可以自动生成这些托管类,那么使用RMIC - Eclipse - Plugin也可以帮助我们自动生成。
装好RMIC - Eclipse之后,对着项目的根目录点击右键,您将会看到"Rmic Marcar/Desmarcar para Auto-Gerar Stubs "的选项,点击它,这时你将会在Bin文件夹下看到Hello_Stub 类,如果有接口继承了Remote 类,那么他将会自动搜索并生成。
六、编写Client类
package remote.test.client;
import java.rmi.Naming;
import remote.test.HelloTask;
import remote.test.HelloTaskImpl;
import remote.test.IHello;
public class HelloClient {
public static void main(String[] args) {
try {
IHello hi = (IHello) Naming.lookup("rmi://127.0.0.1:2500/hello");
HelloTask task = new HelloTaskImpl();
for (int i = 0; i < 10; i++) {
System.out.println(hi.say(task));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
在Client类中,首先需要使用JNDI的Naming来需找服务,并从服务中返回对象。URL的格式可以参考JDK中RMI URL。
七、运行
先运行Server类,成功以后,运行Cient类,您将会看到Server类接收到Client的请求,并将请求打印出来,同时Client类获得Server返回的结果,并打印出来。