最近在看《Head First设计模式》一书的代理模式时,提到了Java RMI,即Java远程方法调用这个概念。于是上网找了一些关于Java RMI的资料加以学习。
一、Java RMI概观
RMI英文全称为:Remote Method Invocation,中文意思为:远程方法调用。它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。可以用此方法调用的任何对象必须实现该远程接口。
RMI将客户辅助对象成为stub(桩),服务辅助对象成为skeleton(骨架)。
RMI结构图如下:
二、Java中如何利用RMI进行远程方法调用呢?
步骤如下:
1、制作远程接口
2、制作远程的实现
3、利用rmic产生stub和skeleton
4、启动RMI registry(rmiregistry)
5、开始远程服务
三、例子程序
MyRemote.java
/** * 服务器端 远程接口 */ package RMIDemo; /* * RemoteException和远程接口在java.rmi包中 * */ import java.rmi.*; /* * 定义一个远程接口,它必须扩展自java.rmi.Remote接口。 * */ public interface MyRemote extends Remote { /** * 所有的远程方法都必须抛出RemoteException异常。 * @return * @throws RemoteException */ public String sayHello() throws RemoteException; }
MyRemoteImpl.java
/** * 远程服务(实现) */ package RMIDemo; import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; /** * * @author ccf * */ /** * 要想创建一个远程对象,扩展UnicastRemoteObject是最容易的方法。 * 其中,MyRemote接口是你必须实现的远程接口 */ public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote { /** * 你必须实现远程接口。当然你必须实现所有的接口方法,但请注意:可以不需要声明RemoteException。 */ @Override public String sayHello() throws RemoteException { // TODO Auto-generated method stub return "Server says: 'Hey' "; } /** * 你的超类(UnicastRemoteObject)构造器声明了异常,所以你必须写一个构造器, * 因为这意味着你的构造器正在调用不安全的代码(它的超构造器)。 * @throws RemoteException */ public MyRemoteImpl() throws RemoteException{} /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub try{ /** * 先产生远程对象,再使用Naming.rebind()绑定到rmiregistry。 * 客户将使用你所注册的名称在RMI Registry中寻找它。 */ MyRemote service = new MyRemoteImpl(); Naming.rebind("RemoteHello", service); }catch(Exception ex){ ex.printStackTrace(); } } }
MyRemoteClient.java
package RMIDemo; /** * 用来做rmiregister lookup的Naming类在java.rmi包中。 * 客户端测试,在客户端调用远程对象的远程方法,并返回结果。 */ import java.rmi.*; public class MyRemoteClient { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub } public void go(){ try{ /* * 返回值是Object类型,所以别忘记转换类型。 * 其次,在lookup函数中你需要IP地址或主机名,还有服务器被绑定/重绑定时用的名称。 */ MyRemote service = (MyRemote)Naming.lookup("rmi://127.0.0.1/RemoteHello"); String s = service.sayHello(); System.out.println(s); }catch(Exception ex){ ex.printStackTrace(); } } }
博客园博主ninahan的博客Java RMI之HelloWorld篇的例子和我从《Head First设计模式》中的摘抄的例子差不多,他讲解得比较清晰!
四、 参考资料:
1、《Head First设计模式》第440-450页。
2、Java RMI 服务器框架:使用异步进程管理器来包含 RMI 服务器应用程序
3、Java RMI之HelloWorld篇:Java RMI之HelloWorld篇
4、JAVA RMI线程模型及内部实现机制 :JAVA RMI线程模型及内部实现机制
5、JDK_API_1_6_zh_CN.CHM参考手册