table

          RMI實用教程

          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介紹

          RMI(Remote 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的強大功能。

           

          posted on 2009-08-11 17:50 小卓 閱讀(145) 評論(0)  編輯  收藏 所屬分類: EJB


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 恭城| 五河县| 威海市| 北碚区| 临漳县| 阳曲县| 青川县| 尉犁县| 昌平区| 郯城县| 呈贡县| 玛沁县| 中宁县| 漾濞| 方山县| 乐平市| 宜阳县| 孝昌县| 含山县| 即墨市| 盘锦市| 焉耆| 永嘉县| 广宗县| 奎屯市| 南部县| 大余县| 寿阳县| 大渡口区| 通州市| 米脂县| 鞍山市| 渝北区| 辽阳县| 洞口县| 比如县| 外汇| 崇文区| 抚远县| 常熟市| 阿尔山市|