RMI 的基础是接口,RMI 构架基于一个重要的原理:定义接口和定义接口的具体实现是分开的。下面我们通过具体的例子,建立一个简单的远程计算服务和使用它的客户程序
一个正常工作的 RMI 系统由下面几个部分组成:
● 远程服务的接口定义
● 远程服务接口的具体实现
● 桩(Stub)和框架(Skeleton)文件
● 一个运行远程服务的服务器
● 一个 RMI 命名服务,它允许客户端去发现这个远程服务
● 类文件的提供者(一个 HTTP 或者 FTP 服务器)
● 一个需要这个远程服务的客户端程序
下面我们一步一步建立一个简单的 RMI 系统。首先在你的机器里建立一个新的文件夹,以便放置我们创建的文件,为了简单起见,我们只使用一个文件夹存放客户端和服务端代码,并且在同一个目录下运行服务端和客户端。
如果所有的 RMI 文件都已经设计好了,那么你需要下面的几个步骤去生成你的系统:
1、 编写并且编译接口的 Java 代码
2、 编写并且编译接口实现的 Java 代码
3、 从接口实现类中生成桩(Stub)和框架(Skeleton)类文件
4、 编写远程服务的主运行程序
5、 编写 RMI 的客户端程序
6、 安装并且运行 RMI 系统
一 、 接口 远程对象的本地接口声明(RMIOperate.java)
· 该类仅仅是一个接口声明,RMI客户机可以直接使用它,RMI服务器必须通过一个远程对象来实现它,并用某个专有的URL注册它的一个实例。
java.rmi.Remote
接口。 java.rmi.RemoteException
(或 RemoteException
的父类)。*/
import java.rmi.*;
// RMI本地接口必须从Remote接口派生
public interface Hello extends Remote {
// 接口中的具体方法声明,注意必须声明抛出RemoteException
String helloWorld(String message) throws RemoteException;
}
import javax.rmi.PortableRemoteObject;
public class HelloImpl extends PortableRemoteObject implements Hello {
/* 构造函数 */
public HelloImpl() throws RemoteException {
super();
}
/* 实现本地接口中声明的'helloWorld()'方法 */
public String helloWorld(String message) throws RemoteException {
System.out.println("我在RMI的服务器端,客户端正在调用'sayHello'方法。 ");
System.out.println("Hello " + message);
return message;
}
}
该类创建远程对象实现类HelloImpl的一个实例,然后通过一个专有的URL来注册它。所谓注册就是通过Java.rmi.Naming.bind()方法或Java.rmi.Naming.rebind()方法,将HelloImpl实例绑定到指定的URL上。
public class HelloServer {
public static void main(String[] args) {
try {
System.out.println("开始 RMI Server ...");
/* 创建远程对象的实现实例 */
HelloImpl hImpl = new HelloImpl();
System.out.println("将实例注册到专有的URL ");
Naming.rebind("HelloService", hImpl);
System.out.println("等待RMI客户端调用...");
System.out.println("");
} catch (Exception e) {
System.out.println("错误: " + e);
}
}
}
请注意有关 rebind
方法调用的下列参数:
- 第一个参数是 URL 格式的
java.lang.String
,表示远程对象的位置和名字。- 需要将
myhost
的值更改为服务器名或 IP 地址。否则,如果在 URL 中省略,则主机缺省值为当前主机,而且在 URL 中无需指定协议(例如“HelloServer
”)。 - 在 URL 中,可以选择提供端口号:例如“/
/myhost:1234/HelloServer”。
端口缺省值为 1099。除非服务器在缺省 1099 端口上创建注册服务程序,否则需要指定端口号。
- 需要将
- 第二个参数为从中调用远程方法的对象实现引用。
- RMI 运行时将用对远程对象 stub 程序的引用代替由
hImpl
参数指定的实际远程对象引用。远程实现对象(如HelloImpl
实例)将始终不离开创建它们的虚拟机。因此,当客户机在服务器的远程对象注册服务程序中执行查找时,将返回包含该实现的 stub 程序的对象。
· RMI客户使用java.rmi.Naming.lookup()方法,在指定的远程主机上查找RMI服务对象,若找到就把它转换成本地接口RMIOperate类型。它与CORBA不同之处在于RMI客户机必须知道提供RMI服务主机的URL,这个URL可以通过rmi://host/path或rmi://host:port/path来指定,如果省略端口号,就默认使用1099。
public class HelloClient {
public static void main(String[] args) {
// 在服务器端设置安全机制
/*
if (System.getSecurityManager() == null) {
System.setSecurityManager(new RMISecurityManager());
}
*/
/* 默认为本地主机和默认端口 */
String host = "localhost:1099";
/* 带输入参数时,将host设置为指定主机 */
if (args.length > 0)
host = args[0];
try {
/* 根据指定的URL定位远程实现对象 */
/* “h”是一个标识符,我们将用它指向实现“Hello”接口的远程对象 */
Hello h = (Hello) Naming.lookup("rmi://" + host + "/HelloService");
System.out.println("实现“Hello”接口的远程对象: " + h);
System.out.println("我在客户端,开始调用RMI服务器端的'sayHello'方法");
System.out.println("欢迎, " + h.helloWorld("javamxj blog"));
} catch (Exception ex) {
System.out.println("错误 " + ex);
}
}
}
D:/RMISample/server>rmiregistry
● 在服务器上执行HelloServer
D:/RMISample/server>java HelloServer
D:/RMISample/client>java HelloClient
java HelloClient 222.222.34.34

