(转)JAVA RMI 实例

Java RMI 快速入门
本文档提供了Java RMI的快速入门实例,包括创建远程接口、实现远程方法、启动RMI注册服务以及客户端调用远程方法等步骤,旨在帮助初学者快速掌握RMI的基本用法。

JAVA RMI 快速入门实例

本实例为参考多篇文章写就而成,网上及书上各类文章介绍如何使用RMI有多种实例可参考,譬如有:

1. 用命令rmiregistry启动RMI注册服务的
2. 同时创建存根(stub)和骨架(skeleton)的
3. 只创建存根类的的(jdk1.2以后版本)
4. 通过RemoteRef和rmi://协议字串方式的
5. 比较少讲到的用LocateRegistry直接在代码上启动RMI注册服务的。

以上描述并非明显分类,比如,你总是可以选择用rmiregistry或者代码LocateRegistry启动RMI注册服务

下面我将介绍一个完整的实例,让初学者能快速体验RMI的功用。

分为以下四个步骤

1. 创建远程接口及声明远程方法(HelloInterface.java)
2. 实现远程接口及远程方法(继承UnicastRemoteObject)(Hello.java)
3. 启动RMI注册服务,并注册远程对象(HelloServer.java)
4. 客户端查找远程对象,并调用远程方法(HelloClient)
5. 执行程序:启动服务HelloServer;运行客户端HelloClient进行调用

具体代码及对应步骤如下:

1. 创建远程接口及声明远程方法(HelloInterface.java)

java 代码
  1. package com.unmi;   
  2.   
  3. import java.rmi.*;   
  4.   
  5. /**  
  6.  * 远程接口必须扩展接口java.rmi.Remote  
  7.  */  
  8. public interface HelloInterface extends Remote   
  9. {   
  10.    /**  
  11.     * 远程接口方法必须抛出 java.rmi.RemoteException  
  12.     */  
  13.    public String say() throws RemoteException;   
  14. }   

2. 实现远程接口及远程方法(继承UnicastRemoteObject)Hello.java

java 代码
  1. package com.unmi;   
  2.   
  3. import java.rmi.*;   
  4. import java.rmi.server.*;   
  5.   
  6. /**  
  7.  * 扩展了UnicastRemoteObject类,并实现远程接口 HelloInterface  
  8.  */  
  9. public class Hello extends UnicastRemoteObject implements HelloInterface   
  10. {   
  11.    private String message;   
  12.   
  13.    /**  
  14.     * 必须定义构造方法,即使是默认构造方法,也必须把它明确地写出来,因为它必须抛出出RemoteException异常  
  15.     */  
  16.    public Hello(String msg) throws RemoteException   
  17.    {   
  18.       message = msg;   
  19.    }   
  20.   
  21.    /**  
  22.     * 远程接口方法的实现  
  23.     */  
  24.    public String say() throws RemoteException   
  25.    {   
  26.       System.out.println("Called by HelloClient");   
  27.       return message;   
  28.    }   
  29. }   

3. 启动RMI注册服务,并注册远程对象(HelloServer.java)

java 代码
  1. package com.unmi;   
  2.   
  3. import java.rmi.Naming;   
  4. import java.rmi.registry.LocateRegistry;   
  5.   
  6. public class HelloServer   
  7. {   
  8.    /**  
  9.     * 启动 RMI 注册服务并进行对象注册  
  10.     */  
  11.    public static void main(String[] argv)   
  12.    {   
  13.       try  
  14.       {   
  15.          //启动RMI注册服务,指定端口为1099 (1099为默认端口)   
  16.          //也可以通过命令 $java_home/bin/rmiregistry 1099启动   
  17.          //这里用这种方式避免了再打开一个DOS窗口   
  18.          //而且用命令rmiregistry启动注册服务还必须事先用RMIC生成一个stub类为它所用   
  19.          LocateRegistry.createRegistry(1099);   
  20.            
  21.          //创建远程对象的一个或多个实例,下面是hello对象   
  22.          //可以用不同名字注册不同的实例   
  23.          HelloInterface hello = new Hello("Hello, world!");   
  24.            
  25.          //把hello注册到RMI注册服务器上,命名为Hello   
  26.          Naming.rebind("Hello", hello);   
  27.             
  28.          //如果要把hello实例注册到另一台启动了RMI注册服务的机器上   
  29.          //Naming.rebind("//192.168.1.105:1099/Hello",hello);   
  30.            
  31.          System.out.println("Hello Server is ready.");   
  32.       }   
  33.       catch (Exception e)   
  34.       {   
  35.          System.out.println("Hello Server failed: " + e);   
  36.       }   
  37.    }   
  38. }  

4. 客户端查找远程对象,并调用远程方法(HelloClient)

java 代码
  1. package com.unmi;   
  2.   
  3. import java.rmi.Naming;   
  4.   
  5. public class HelloClient   
  6. {   
  7.    /**  
  8.     * 查找远程对象并调用远程方法  
  9.     */  
  10.    public static void main(String[] argv)   
  11.    {   
  12.       try  
  13.       {   
  14.          HelloInterface hello = (HelloInterface) Naming.lookup("Hello");   
  15.             
  16.          //如果要从另一台启动了RMI注册服务的机器上查找hello实例   
  17.          //HelloInterface hello = (HelloInterface)Naming.lookup("//192.168.1.105:1099/Hello");   
  18.             
  19.          //调用远程方法   
  20.          System.out.println(hello.say());   
  21.       }   
  22.       catch (Exception e)   
  23.       {   
  24.          System.out.println("HelloClient exception: " + e);   
  25.       }   
  26.    }   
  27. }   
  28.   

5. 执行程序:启动服务HelloServer;运行客户端HelloClient进行调用

代码如何编译这里就不细讲

(1)打开一个Dos窗口执行命令 java com.unmi.HelloServer 启动服务HelloServer

E:workspaceTestRMIbin>java com.unmi.HelloServer
Hello Server is ready.

运行成功则可以看到 Hello Server is ready

(2)打开另一个Dos窗口执行命令 java com.unmi.HelloClient 运行客户端程序

E:workspaceTestRMIbin>java com.unmi.HelloClient
Hello, world!

调用成功则可以看到 Hello, world!

并且在启动服务端的窗口中看到紧跟 Hello Server is ready. 打印出
Called by HelloClient

如果您能一路顺畅的执行到这里,恭喜!您已度过了一个轻快的RMI之旅。

最后来个说明:

本实例中并没有用到JDK所带的命令 rmic 编译实现类得到存根(Stub)类,也没用命令 rmiregistry 命令来启动RMI注册服务。在启动 rmiregistry之前必须能让它加载到相应的stub类,这就是造成**_Stub 类找不到的原因。

如果只是按上面的代码,则服务程序 HelloServer 和客户端程序 HelloClient 都必须运行在本机(如此则RMI有何意义呢?);别急,只要修改HelloClient类,使用第二种形式的lookup查找语句,注释第一条 lookup语句,取消注释第二条lookup语句

         //HelloInterface hello = (HelloInterface) Naming.lookup("Hello");
       
         //如果要从另一台启动了RMI注册服务的机器上查找hello实例
         HelloInterface hello = (HelloInterface)Naming.lookup("//192.168.1.105:1099/Hello");

其中的IP地址和端口号1099为 RMI 注册服务器的IP和端口号,这样你的HelloClient就可以在另一台机器运行了,当然HelloInterface类必须能找到(但也可指定参数- Djava.rmi.server.codebase从网络加载HelloInterface类)。lookup("Hello")默认为从本机 127.0.0.1的1099端口上查找Hello命令对象,如果第二条语句写成lookup("192.168.1.105/Hello")与原语句是同等的,因为默认端口号就是1099。

代码中 HelloServer 和 HelloClient 省略了设置安全管理器的过程 System.setSecurityManager(new RMISecurityManager()); ,如果设置的安全管理则必须编写相应的访问策略文件,并且在执行时指定参数

无论是启动服务端还是客户端都可以用参数 -Djava.rmi.server.codebase=http://unmi.blogcn.cn/bin 的形式,像JNP一样从网络上加载类,这样更方便于RMI客户端的部署,如RMI客户端是一个Applet

可以拿单独一台机器运行 rmiregistry (它需要能加载到相应的stub类,设置classpath)或用LocateRegistry.createRegistry(port),只作为 RMI远程对象的RMI集中注册的服务器,真正提供服务对象只往上注册,客户端只需从注册服务器上查找远程对象引用,然后调用远程方法,具体由谁提供服务由注册服务器来帮助联络。

还可以用 RMI Activation 编程方式来实现RMI远程方法调用,具体请参考 http://java.sun.com/j2se/1.4.2/docs/guide/rmi/activation.html

把HelloServer和HelloClient中的 "//192.168.1.105:1099/Hello 写成 rmi:/192.168.1.105:1099/Hello 感觉会好看一些,因为直接感觉就是在处理rmi协议。

参考资料:
1. JAVA RMI Tutorial
2. Getting Started Using RMI
3. JavaRMI入门实战
4. 使用RMI和CORBA进行分布式java程序设计
5. Think in java中网络编程RMI部分

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值