1. RMI概述
RMI(Remote MethodInvocation)是分布对象软件包,简化了在多台计算机上的Java应用之间的通信,使用的JDK版本必须在1.1以上。用到的类有两个:第一java.rmi.Remote,所有可以被远程调用的对象都必须实现该接口;第二java.rmi.server.UnicastRemoteObject,所有可以被远程调用的对象都必须扩展该类。
2. 什么是RMI
远程方法调用是一种计算机之间对象互相调用对方函数,启动对方进程的一种机制,使用这种机制,某台计算机上的对象在调用另外一台计算机方法时,使用的程序语法规则和在本地机上对象间的方法调用的语法规则一样。
3. 实现一个简单的RMI
必须构造四个主要的类:远程对象的本地接口、RMI客户、远程对象实现和RMI服务器。RMI服务器生成远程对象实例的一个实例,并用一个特殊的URL注册它,RMI客户在远程服务器上查找对象,若找到就把它转换成本地接口类型,然后像一个本地对象一样使用它。
以一个例子来说明:
远程对象的本地接口类
该类仅仅是一个接口,而不是实现,RMI客户机可以直接运行,RMI服务器必须通过一个远程对象来实现,并用某个URL注册它的一个实例.本地接口必须是公共的,否则客户机在加载一个实现该接口的远程对象时会出现错误。同时必须从java.rmi.Remote继承而来,接口中每一个方法都必须抛出异常java.rmi.RemoteException
packageremote; import java.rmi.*; //这是一个本地接口类,而不是实现 public interface LocalInterface extends Remote{ public String getString() throwsRemoteException; } |
RMI客户类
RMI 客户使用Naming.lookup在指定的远程主机上查找对象,若找到就将其转换为本地接口类型(在此例子中是LocalInterface),然后就可以像本地对象一样使用它。远程服务机的URL可以通过rmi://host/path或rmi://host:port/path来指定。Naming.lookup可能产生三个异常:RemoteException,NotBoundException和MalformedURLException,三个异常均需捕获。其中前两个异常在java.rmi.*中定义,最后一个异常在java.net.*中定义。另外客户机将向远程对象中传递串行化对象Serializable,所以还应在程序中输入java.io.*。
package remote; import java.rmi.*; import java.net.*; import java.io.*; publicclass ClientRemote { public static void main(String[] args){ try{ Stringhost=(args.length>0)?args[0]:"localhost";//从命令行读取需要连接的主机名 System.out.println(host); //通过URL在远程主机上查找对象,并把它转化为本地接口LocalInterface类型 LocalInterfacelocalObject=(LocalInterface)Naming.lookup("rmi://"+host+"/remote.LocalInterface"); System.out.println(localObject.getString());//调用远程对象的方法 }catch(RemoteExceptione){ System.out.println(e.toString()); }catch(NotBoundExceptionex){ System.out.println(ex.toString()); }catch(MalformedURLExceptionmfe){ System.out.println(mfe.toString()); } } |
远程对象实现类
这个类真正实现RMI客户调用的远程对象,它必须从UnicastRemotedObject继承,其构造函数应该抛出RemoteException异常。
packageremote; import java.rmi.*; import java.rmi.server.*; publicclass ImpleRemote extends UnicastRemoteObject implementsLocalInterface{ public ImpleRemote() throwsRemoteException{}//构造函数抛出RemoteException异常 public String getString() throwsRemoteException{ return("这是一个远程调用的消息");//想客户返回一个消息串 } } |
RMI服务器
该类创建远程对象实现ImpleRemote的一个实例,然后用一个特定的URL来注册,即通过Naming.bind或Naming.rebind来将刚创建的实例绑定到URL上。
packageremote; import java.rmi.*; import java.net.*; public class ServerRemote { public static void main(String[] args){ try{ ImpleRemotelocal=new ImpleRemote();//生成远程对象的一个实例 Naming.rebind("rmi:///remote.LocalInterface",local);//将远程对象实例绑定到LocalInterface }catch(RemoteExceptione){ System.out.println("RemoteException"+e); } catch(MalformedURLExceptionmfe){ System.out.println("MalformedURLException:"+mfe); } } } |
最后介绍一下编译和运行,共分为四步:
- 编译所有类
- 生成客户承接模块和服务器框架,在目录下运行rmicImpleRemote,这将构造RemImpl_stud.class
- 启动RMI注册:rmiregistry
- 运行:javaServerRemote(启动RMI服务器)和javaClientRemote(启动RMI客户)