My First RMI Program

RMI,远程方法调用(Remote Method Invocation)是 Enterprise JavaBeans 的支柱,是建立分布式Java 应用程序的方便途径。RMI是非常容易使用的,但是它非常的强大。

  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 接口。 · 除了所有应用程序特定的例外之外,每个方法还必须在 throws 子句中声明 java.rmi.RemoteException(或 RemoteException 的父类)。 /*
 */
import java.rmi.*;
// RMI本地接口必须从Remote接口派生
public interface Hello extends Remote {
   
// 接口中的具体方法声明,注意必须声明抛出RemoteException
    String helloWorld(String message) throws RemoteException;
}
二、 接口的具体实现 这个类应实现RMI客户机调用的远程服务对象的本地接口,它必须从UnicastRemoteObject继承,构造函数应抛出RemoteException异常。 import java . rmi . * ;
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;
    }
}
三、RMI服务器类
    该类创建远程对象实现类HelloImpl的一个实例,然后通过一个专有的URL来注册它。所谓注册就是通过Java.rmi.Naming.bind()方法或Java.rmi.Naming.rebind()方法,将HelloImpl实例绑定到指定的URL上。 import java . rmi . * ;
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客户机类

· RMI客户使用java.rmi.Naming.lookup()方法,在指定的远程主机上查找RMI服务对象,若找到就把它转换成本地接口RMIOperate类型。它与CORBA不同之处在于RMI客户机必须知道提供RMI服务主机的URL,这个URL可以通过rmi://host/path或rmi://host:port/path来指定,如果省略端口号,就默认使用1099。 · Java.rmi.Naming.lookup()方法可能产生三个异常:Java.rmi.RemoteException、Java.rmi.NotBoundException、java.net. MalformedURLException,三个异常都需要捕获。 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.helloWorld( "javamxj blog"));
        } catch ( Exception ex) {
            System.out.println( "错误 " + ex);
        }
    }
} 五、 编译代码与运行系统: 在MS-DOS环境下,创建一个D:/RMISample目录,把上面4个文件复制到这个目录下,然后在此目录下新建两个文件夹:client和server(把它们分别看作是客户端与服务端)。 (1).编译所有的源代码 D:/RMISample> javac *.java (2).生成客户端存根和服务器框架 D:/RMISample> rmic HelloImpl 这将生成HelloImpl_Stub.class和HelloImpl_Skel.class。 ( :如果需要查看这两个类的源代码,可以使用“ rmic -keep HelloImpl”语句) (3).把Hello.class、HelloClient.class、HelloImpl_Stub.class复制到client目录; 把Hello.class、HelloServer.class、HelloImpl_Skel.class、HelloImpl_Stub.class 复制到server目录。 (4).启动RMI注册
D:/RMISample/server>rmiregistry (注: 我是在命令控制台下运行这个系统的,必须开启三个控制台窗口,一个运行RMIRegistry,一个运行服务器,还有一个运行客户端。) (5).运行和调用
● 在服务器上执行HelloServer
D:/RMISample/server>java HelloServer ● 在本地客户机上运行HelloClient
D:/RMISample/client>java HelloClient ● 在远程客户机上运行HelloClient(须指明RMI服务器主机名或IP地址)
java HelloClient 222.222.34.34 运行rmiregistry和server后的结果: 再运行Client后的结果:


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部