RMI实用教程

    技术2022-05-11  81

         Java Remote Method Invocation ( RMI -- Java远程方法调用)允许您使用Java编写分布式对象。本文将介绍RMI的优点以及如何将其连接到现有的和原有的系统中,以及与用Java 编写的组件的连接,同时给出了一个详细的例子,可以给初学者提供一个学习范本。  

    一、RMI(远程方法调用)的组成

          一个正常工作的RMI系统由下面几个部分组成:

          1、远程服务的接口定义       2、远程服务接口的具体实现       3、桩(Stub)和框架(Skeleton)文件       4、一个运行远程服务的服务器       5、一个RMI命名服务,它允许客户端去发现这个远程服务       6、类文件的提供者(一个HTTP或者FTP服务器)       7、一个需要这个远程服务的客户端程序

    二、RMI(远程方法调用)的工作原理

    RMI系统结构,在客户端和服务器端都有几层结构。 --------- ---------- | 客户 | | 服务器| ---------- ---------- | | ------------- ---------- | 占位程序 | | 骨干网 | -------------- ----------- | | ------------------------------------ | 远 程 引 用 层 | ------------------------------------ | | ------------------------------------ | 传 输 层 | ------------------------------------

         方法调用从客户对象经占位程序(Stub)、远程引用层(Remote Reference Layer)和传输层(Transport Layer)向下,传递给主机,然后再次经传 输层,向上穿过远程调用层和骨干网(Skeleton),到达服务器对象。 占位程序扮演着远程服务器对象的代理的角色,使该对象可被客户激活。 远程引用层处理语义、管理单一或多重对象的通信,决定调用是应发往一个服务器还是多个。传输层管理实际的连接,并且追追踪可以接受方法调用的远程对象。服务器端的骨干网完成对服务器对象实际的方法调用,并获取返回值。返回值向下经远程引用层、服务器端的传输层传递回客户端,再向上经传输层和远程调用层返回。最后,占位程序获得返回值。

          要完成以上步骤需要有以下几个步骤:

          1、生成一个远程接口       2、实现远程对象(服务器端程序)       3、编写服务器程序 、注册远程对象、启动远程对象      4、编写客户程序 在JDK1.5之后,用java提供的API将会更加的简单,可以参照下面的例子;

    三、例子

    1、远程接口

    接口名:com.liuxiang.rmi.download.IRMI

    该接口定义了一个方法,用于提供远程服务;

    /**  *   */ package  com.liuxiang.rmi.download; import  java.rmi.Remote; import  java.rmi.RemoteException; /**  * 远程对象接口 *  @author  liuxiang * 2007-8-30 下午09:39:15     *  */ public   interface  IRMI  extends  Remote{     public  Object invoke(ITask task)  throws  RemoteException;}

    2、实现远程对象(服务器端程序)

    类名:com.liuxiang.rmi.download.IRMIImpl

    实现了远程接口定义的方法;该实现远程对象中,调用了传入参数的task.doWork()方法,同时执行一个本地调用,调用一个播放Mp3的代码段ProcessCaller.callMp3();

    /**  *   */ package  com.liuxiang.rmi.download; import  java.rmi.RemoteException; import  java.rmi.server.UnicastRemoteObject; import  com.liuxiang.callwindow.ProcessCaller; /**  * 远程对象的实现 *  @author  liuxiang * 2007-8-30 下午09:41:32     *  */ public   class  IRMIImpl  extends  UnicastRemoteObject  implements  IRMI {     protected  IRMIImpl()  throws  RemoteException {         super ();    }     /**      *       */      private   static   final   long  serialVersionUID  =   6131922116577454476L ;     /*  (non-Javadoc)     * @see com.liuxiang.rmi.download.IRMI#invoke(com.liuxiang.rmi.download.ITask)      */      public  Object invoke(ITask task)  throws  RemoteException {        System.out.println( " 注意:这是一个远程调用 " );        Object obj  =  task.doWork();        System.out.println( " 调用ITask.doWork()方法的返回值: " + obj.toString());         // 客户端调用,可以在服务器端播放需要的音乐         ProcessCaller.callMp3();         return  obj;    }}

    3、播放Mp3代码段的源代码如下:

    /**  *   */ package  com.liuxiang.callwindow; /**  * 在java中调用windows程序 *  @author  liuxiang 2007-8-30 下午10:26:20 *   */ public   class  ProcessCaller {     /**      * 调用Windows程序     * 利用Windows Media Player播放mp3音乐      */      public   static   void  callMp3() {        Runtime ru  =  Runtime.getRuntime();         try  {             //  调用播放器文件播放指定MP3             Process p1  =  ru                    .exec( " C:/Program Files/Windows Media Player/wmplayer F:/music/lx/刘若英-后来.mp3 " );        }  catch  (Exception e) {        }    }     /**      *  @param  args      */      public   static   void  main(String[] args) {        callMp3();    }}

    4、任务接口

    该接口定义了远程方法需要传递的参数

    /**  *   */ package  com.liuxiang.rmi.download; import  java.io.Serializable; /**  * 任务接口 *  @author  liuxiang * 2007-8-30 下午09:35:53     *  */ public   interface  ITask  extends  Serializable{     public  Object doWork();}

    5、任务接口实现

    该实现定义了远程方法需要传递的参数

    package  com.liuxiang.rmi.download; /**  * 任务实现类 *  @author  liuxiang * 2007-8-31 上午09:08:57     *  */ public   class  TaskImpl  implements  ITask{     public  Object doWork() {        System.out.println( " 当前程序处于远程调用中 " );         return   " 动态上载对象的返回值 " ;    }    }

    6、编写服务器程序 、注册远程对象、启动远程对象

    代码:远程对象的注册类 该类应该在服务器端执行 执行之后, 该机器将变为RMI服务器 客户端可以通过正确的url来访问;服务器上的远程对象;执行对外报露的方法

    /**  *   */ package  com.liuxiang.rmi.download; import  java.rmi.Naming; import  java.rmi.registry.LocateRegistry; import  java.rmi.registry.Registry; /**  * 远程对象的注册类 该类应该在服务器端执行 执行之后, * 该机器将变为RMI服务器 客户端可以通过正确的url来访问 * 服务器上的远程对象;执行对外报露的方法 *  *  @author  liuxiang 2007-8-30 下午09:44:54 *   */ public   class  RMIServer {     /**      * 如果没有创建一个Registry,Naming是不会帮助你创建的。 还是自己手工创建的比较的好     *      * 尽量用下面的自己封装的bind方法来注册远程对象     *      *  @throws  Exception      */      public   static   void  registRemoteObject()  throws  Exception {        IRMIImpl impl  =   new  IRMIImpl();        Naming.rebind( " rmi://219.233.8.97:1111/mytask " , impl);        System.out.println( " bound success! " );    }     /**      * 创建一个Registry对象     *      *  @return  返回一个Registry对象      */      private   static  Registry createRegistry() {        Registry registry  =   null ;         int  port  =   1111 ;         try  {            registry  =  LocateRegistry.getRegistry(port);            registry.list();            System.out.println( " Register the exist server! " );        }  catch  ( final  Exception e) {             try  {                registry  =  LocateRegistry.createRegistry(port);                System.out.println( " Register the exist server!port= "   +  port);            }  catch  ( final  Exception ee) {                ee.printStackTrace();            }        }         return  registry;    }     /**      * 将对象注册到rmi服务器上      */      public   static   void  bind() {        Registry registry  =   null ;        registry  =  createRegistry();         try  {            IRMIImpl impl  =   new  IRMIImpl();            registry.rebind( " mytask " , impl);            System.out.println( " mytask server start! " );        }  catch  (Exception e) {            e.printStackTrace();        }    }     /**      *  @param  args      */      public   static   void  main(String[] args) {         try  {            bind();        }  catch  (Exception e) {            e.printStackTrace();        }    }}

    运行该服务端代码后,将会注册一个远程服务对象,通过恰当的URL可以访问远程对象中的方法;运行后的结果如下:

    Register the exist server ! port = 1111 mytask server start !

    7、编写客户程序

    代码首先获取一个远程对象,然后如同本地调用一样,调用远程对象中的方法。

    /**  *   */ package  com.liuxiang.rmi.download; import  java.rmi.Naming; /**  *  @author  liuxiang * 2007-8-30 下午09:47:41     *  */ public   class  RMIClient {     /**      * 调用远程对象中的方法     *  @throws  Exception      */      public   static   void  getRemoteObject()  throws  Exception{        IRMI obj  =  (IRMI)Naming.lookup( " rmi://localhost:1111/mytask " );     // 得到远程发布的服务         TaskImpl task  =   new  TaskImpl();        Object result  =  obj.invoke(task);     // 调用远程服务的方法         System.out.println(result.toString());    }     /**      *  @param  args      */      public   static   void  main(String[] args) {         try  {            getRemoteObject();        }  catch  (Exception e) {            e.printStackTrace();        }    }}

    最后,运行客户端代码,可以看到控制台分别输出了如下的内容:

    Server端输出了更多的内容,如下:

    Register the exist server ! port = 1111 mytask server start ! 注意:这是一个远程调用当前程序处于远程调用中调用ITask.doWork()方法的返回值:动态上载对象的返回值

    同时可以看到,会调用了Windows的Mediaplay播放本地磁盘的Mp3歌曲;

    Client端输入了如下内容:

    动态上载对象的返回值

    四、RMI介绍

    RMIRemote Method Invocation远程方法调用)是用Java在JDK1.1中实现的,它大大增强了Java开发分布式应用的能力。Java作为一种风靡一时的网络开发语言,其巨大的威力就体现在它强大的开发分布式网络应用的能力上,而RMI就是开发百分之百纯Java的网络分布式应用系统的核心解决方案之一。其实它可以被看作是RPC的Java版本。但是传统RPC并不能很好地应用于分布式对象系统。而Java RMI 则支持存储于不同地址空间的程序级对象之间彼此进行通信,实现远程对象之间的无缝远程调用。  

    RMI目前使用Java远程消息交换协议JRMP(Java Remote Messaging Protocol)进行通信。JRMP是专为Java的远程对象制定的协议。因此,Java RMI具有Java的"Write Once,Run Anywhere"的优点,是分布式应用系统的百分之百纯Java解决方案。用Java RMI开发的应用系统可以部署在任何支持JRE(Java Run Environment Java,运行环境)的平台上。但由于JRMP是专为Java对象制定的,因此,RMI对于用非Java语言开发的应用系统的支持不足。不能与用非Java语言书写的对象进行通信。

    RMI为采用Java对象的分布式计算提供了简单而直接的途径。这些对象可以是新的Java对象,也可以是围绕现有API的简单的Java包装程序。Java体现了“编写一次就能在任何地方运行的模式。而RMI可将Java模式进行扩展,使之可在任何地方运行”。

      因为RMI是以Java为核心的,所以,它将Java的安全性和可移植性等强大功能带给了分布式计算。您可将代理和梢?务逻辑等属性移动到网络中最合适的地方。如果您要扩展Java在系统中的使用,RMI将使您充分利用其强大功能。

      RMI可利用标准Java本机方法接口JNI与现有的和原有的系统相连接。RMI还可利用标准JDBC包与现有的关系数据库连接。RMI/JNI和RMI/JDBC相结合,可帮助您利用RMI与目前使用非Java语言的现有服务器进行通信,而且在您需要时可扩展Java在这些服务器上的使用。RMI可帮助您在扩展使用时充分利用Java的强大功能。

     可以自由的传播本文,但必须注明出处!!

     <script type="text/javascript"><!--google_ad_client = "pub-0052806401033607";google_ad_width = 728;google_ad_height = 90;google_ad_format = "728x90_as";google_ad_type = "text_image";google_ad_channel = "";//--></script><script type="text/javascript"  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>


    最新回复(0)