对 RMI 的简单理解
RMI (远程方法)是 Java 平台中建立分布式计算的基础, 2 年前我刚开始接触 J2EE 时,怎么看书都是不得要领,最近这几天闲着没事又翻了翻以前没有看懂的书,突然之间顿悟了。
一、 简单的 RMI 示例:
要快速入门,最简单的方法就是看简单的例子。下面是我写的一个简单的示例:
首先,定义一个接口 IServer ,代码如下:
IServer.java
需要注意的是,这个接口从java.rmi.Remote接口扩展,并且这个接口中定义的方法都需要抛出java.rmi.RemoteException异常。
接着,我们要根据这个接口来实现自己的服务器对象,所谓服务器对象,就是我们大脑中想的远程对象,这个对象中定义的方法都是被别人来调用的。代码如下:
ServerImp.java
这个类很容易理解, doSomeThing() 方法只简单的输出被调用的信息。唯一的难点就在 main() 函数中,我们通过 java.rmi.Naming.rebind() 把我们的远程对象注册到 rmi 注册表中,这样,别人就可以通过 java.rmi.Naming.lookup() 来查找我们的远程对象。那么, rmi 注册表在哪里呢? J2SDK 的 bin 目录下有一个程序 rmiregistry ,运行它就可以得到一个注册表进程,我们可以通过它来绑定或者查找远程对象, java.rmi.Naming.rebind 函数的第一个参数就是要指定注册表进程的位置,因为我这里运行在自己的机器上,所以是 //localhost/ ,如果是在别的机器上,可以用 IP 地址代替。
最后,我们写一个客户机,来调用这个远程对象的方法。代码如下:
Client.java
可以看到,我们的客户端程序只用到了 IServer 接口,而不需要 ServerImp 类,它只通过 java.rmi.Naming.lookup() 来查找远程对象的引用。
下面,我们就可以开始测试我们的程序了。先编译以上程序,然后:
第一步,要先启动 Rmi 注册表,如下:
第二步,使用 rmic 对 ServerImp.class 进行编译,生成代理类 ServerImp_Stub.class ,如下:
第三步,启动服务器端程序,如下:
第四步,启动客户端程序,我们多调用几次,如下:
这个时候,我们再看看服务器端是什么反应:
可以看到,服务器端的方法被调用,在服务器端的控制台上打印出了这样几行消息。
下面,我们使用一个简单的图表来表示客户机、服务器和 RMI 注册表之间的关系,绿色的数字代表顺序:
二、参数传递 前面的例子没有涉及到参数的传递。如果我们需要向远程方法传递参数,或者要从远程方法接受返回值,是不是有什么特殊的约定呢?不错,如果我们要在客户机和服务器之间传递参数,则该对象要么是实现Serializable接口的对象,要么是扩展自UnicastRemoteObject的对象,这两种对象是有差别的。 如果参数是实现Serializable接口的对象,则该对象是按值传递的,也就是把这整个对象传递到远程方法中。请看下面的例子,我们定义了一个ISerializableWorker接口,扩展自Serializable接口,客户端创建一个SerializableWorkerImp对象wk,并把它传递到服务器端,服务器端调用wk.work()方法,这个方法在服务器端执行,这就说明了我们成功把这个对象传递到了服务器端。服务器端返回的String对象,也可以成功传递到客户端。ISerializableWorker.java
然后,我们需要在服务器端程序中载入安全管理器,我们这里使用默认的RMISecurityManager,下面是经过修改了的ServerImp.java中的mian()函数:
Powered by: BlogJava Copyright © 京山游侠