头几天有一个小学妹找我帮她写实验报告,内容一大堆,主要是利用RMI实现通信,RMI我以前一直没有用过,这次也算学习了,就把心得写出来,网上主要都是如何用RMI写代码,但是在eclipse下开发RMI和详细解释不是很多,我就把我主要理解的一些东西写出来把。
先展示一下本人用命令行运行的代码流程和解释,我也是参考人家的。
远程方法调用( RMI,Remote Method Invocation)是jdk1.1中引入的分布式对象软件包,它的出现大大简化了分布异构环境中Java应用之间的通信。
要使用RMI,必须构建四个主要的类:远程对象的本地接口、远程对象实现、RMI客户机和RMI服务器。RMI服务器生成远程对象实现的一个实例,并用一个专有的URL注册。RMI客户机在远程RMI服务器上查找服务对象,并将它转换成本地接口类型,然后像对待一个本地对象一样使用它。
下面是一个简单的RMI实例,RMI客户机通过RMI服务器提供的方法输出一个语句。例子虽然很简单,但掌握了Java RMI调用的基本原理和方法,在实现复杂应用时,我们需要做的也只是完善远程对象的实现类而已。
1. 远程对象的本地接口声明(RMIOperate.java)
· 该类仅仅是一个接口声明, RMI客户机可以直接使用它,RMI服务器必须通过一个远程对象来实现它,并用某个专有的URL注册它的一个实例。
- Hello.java
- /* * @author javamxj (CSDN Blog) 创建日期 2004-12-27 */
- import java.rmi.*; // RMI本地接口必须从Remote接口派生
- public interface Hello extends Remote { // 接口中的具体方法声明,注意必须声明抛出RemoteException
- String sayHello(String name) throws RemoteException; }
2.远程对象实现类
这个类应实现RMI客户机调用的远程服务对象的本地接口,它必须从UnicastRemoteObject继承,构造函数应抛出RemoteException异常。
- HelloImpl.java
- /*
- * @author javamxj (CSDN Blog) 创建日期 2004-12-27
- */
- import java.rmi.*;
- import javax.rmi.PortableRemoteObject;
- public class HelloImpl extends PortableRemoteObject implements Hello {
- /* 构造函数 */
- public HelloImpl() throws RemoteException {
- super();
- }
- /* 实现本地接口中声明的'sayHello()'方法 */
- public String sayHello(String message) throws RemoteException {
- System.out.println("我在RMI的服务器端,客户端正在调用'sayHello'方法。 ");
- System.out.println("Hello " + message);
- return message;
- }
- }
3.RMI服务器类
该类创建远程对象实现类HelloImpl的一个实例,然后通过一个专有的URL来注册它。所谓注册就是通过Java.rmi.Naming.bind()方法或Java.rmi.Naming.rebind()方法,将HelloImpl实例绑定到指定的URL上。
- HelloServer.java
- /*
- * @author javamxj (CSDN Blog) 创建日期 2004-12-27
- */
- import java.rmi.*;
- public class HelloServer {
- public static void main(String[] args) {
- // 在服务器端设置安全机制
- /*
- if (System.getSecurityManager() == null) {
- System.setSecurityManager(new RMISecurityManager());
- }
- */
- 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。
- HelloClient.java
- /*
- * @author javamxj (CSDN Blog) 创建日期 2004-12-27
- */
- import java.rmi.*;
- 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.sayHello("javamxj blog"));
- } catch (Exception ex) {
- System.out.println("错误 " + ex);
- }
- }
- }
(2).生成客户端存根和服务器框架
D:\RMISample\server>rmiregistry
● 在服务器上执行 HelloServer
D:\RMISample\server>java HelloServer
D:\RMISample\client>java HelloClient
java HelloClient 222.222.34.34
permission java.security.AllPermission "", "";
};
将解压后得到的features和plugins文件夹拷贝至Eclipse安装根目录下,覆盖原有文件夹。 我自己已下载到插件包,在附件里面 启动Eclipse(如果已经启动,请重新启动Eclipse),这时在工具栏上会发现多了一个工具图标,里面有Registry的管理选项,这个就是RMI Registry的管理器。说明已经安装成功了。
二、设置开发环境
在安装好插件包后,我们来设置RMI开发环境。启动Eclipse,在菜单window->preferences对话框中,选中左边树菜单java->rmi,右边窗口会出现RMI Plugin的默认设置信息。 最上面的Path to RMI registry设置java的RMI Registry的路径,如这里设置的是C:/Program Files/Java/jdk1.5.0_05/bin/rmiregistry.exe,一般不用管它。下面的一个框是RMI的服务端口,默认是 1099,这个类似tomcat的服务端口8080一样,链接的时候需要找到对应的端口才能链接上。其实RMI的最低层是socket。 这里需要特别指出的是RMI Plugin是个收费的Eclipse插件,有15天的免费试用期。而RMI属性中最大的窗口就是填使用授权信息的。
这也就是开发环境的基本设置,主要是需要RMI的插件和设置。
三、运行调试项目
在运行之前需要进行一下设置,否则,会提示错误信息,说找不到stub类。
1、启动RMIRegistry
Eclipse菜单window->show view->others,在弹出菜单中选择RMI Views>RMI Registry Inspector,这是会多出来一个窗口,这里可以显示已经注册的RMI应用。点击工具条上的RMI Plugin图标,在菜单中选择Start Local Registry。注意这个只需要启动一次,除非你把它关掉。
2、配置运行RMI服务 右键点击左边树中的RMI_Server.java文件,菜单Debug As ->RMI Application。在弹出对话框中找到RMI Properties标签页。 这时这里前两项显示红色。 选中java.security.police项的value框,点击选择按钮会出现文件选择对话框,我们这里设置成C:/Program Files/Java/jre1.5.0_05/lib/security/java.security。就是jre的安全策略配置文件,要选择成泥当前用的jdk的侧略文件。选中第二项java.rmi.server.codebase的value项,这里选择编译后类包所在的文件夹。点击选择按钮->add按钮->pick from workspace,选择当前工程RMITest的bin文件夹。这里是file:/E:/workspace/RMITest/bin/。(这里有点要补充一下,还可以 点击选择按钮->add按钮->compute from classpath)。
以上是运行RMI Application,但是我的电脑没显示RMI Application,当时这个窗口也显示不到任何RMI项目
这时无法启动RMIRegistry ,因此只能手动启动RMIRegistry
这里启动完成RMI注册,并且会在工程的bin路径下生成先关的stub类。在运行服务器类和客户端类就完成了。注意这个RMI注册只只能启动一次,除非你把它关掉。