JAVA RMI 原理與實現

一、RMI的工作原理

RMI能讓一個Java程序去調用網絡中另一臺計算機的Java對象的方法,那麼調用的效果就像是在本機上調用一樣。

 

二、RMI遠程地調用的步驟

  1. 調用者用通常方式調用對應java的一個遠程對象的方法
  2. 客戶stub的功能是把相關的參數組裝成一個消息包或一組消息包。運行此方法的那個“站點”的地址和對象及方法的“標識符”、調用方法的參數都應包含在這條消息中。
  3. 將這條消息發送給對應的RMI運行時系統,該程序在轉至指定的站點。
  4. 在接受此消息時,遠程RMI運行時系統引用與被調用者對應的服務stub,並讓它來處理這條消息。
  5. 服務器stub來反序列化有關參數,並用本地方法調用方式調用所需方法,然後把調用結果序列化,向調用者返回結果。
  6. 調用方RMI運行時系統棘手返回結果。調用者stub反序列化參數,然後,返回結果到調用方法。

 

三、RMI應用的基本開發步驟

案例:開發一個遠程調用方法 rmb2Dollar(double rmb),它把客戶(調用者)提供的人民幣(rmb)數值傳送個服務器,服務器按照一定的美元匯率將其返回。

1、定義遠程服務接口類(Converter.java)

遠程服務接口類必須繼承java.rmi.Remote接口,並且在業務方法中拋出RemoteException異常

package cn.wzh;

import java.rmi.*;

public interface Converter extends Remote 

    public double rmb2Dollar(double rmb) throws RemoteException; 
}

2、定義遠程接口的實現類(ConverterImpl.java)

遠程接口必須實現服務接口並且繼承java.rmi.server.UnicastRemoteObject對象,構造方法必須拋出RemoteException

package cn.wzh;

import java.rmi.*; 
import java.rmi.server.*;

public class ConverterImpl extends UnicastRemoteObject implements Converter 

     public ConverterImpl() throws RemoteException 
     { 
         super(); 
     } 
  
     public double rmb2Dollar(double rmb) 
     { 
         return rmb * 0.125; 
     } 
}

3、編寫RMI服務器端代碼(RMIServer.java)

出於對RMI調用的安全考慮,需要對RMI應用設置安全管理器。使用命名綁定關鍵字到對象。

package cn.wzh;

import java.rmi.*;

public class RMIServer 

     // 由於這裏測試我們是最終用戶,所以直接將異常拋給虛擬機 
     public static void main(String[] args) throws Exception 
     { 
          System.setSecurityManager(new RMISecurityManager()); 
   
          Converter c = new ConverterImpl(); 
   
          Naming.bind("convert", c); 
   
          System.out.println("rmi server start ..."); 
     } 
}

4、編寫RMI客戶端調用類(RMIClient.java)

package cn.wzh;

import java.rmi.*; 
import java.net.MalformedURLException;

public class RMIClient 

    // 同樣爲了方便,直接異常拋出 
    public static void main(String[] args) throws Exception 
    { 
        System.setSecurityManager(new RMISecurityManager()); 
        try 
        { 
            // 這裏因爲是在本地所以省略了地址跟協議,若在網絡中的遠程方法調用,需要這樣寫 
            // Converter c = (Converter)Naming.lookup("rmi://192.168.0.13/convert");
 
            Converter c = (Converter)Naming.lookup("convert"); 
            double rmb = c.rmb2Dollar(1000); 
            System.out.println("converter result : " + rmb); 
        } 
        catch (MalformedURLException e) 
        { 
            e.printStackTrace(); 
        } 
        catch (RemoteException e) 
        { 
            e.printStackTrace(); 
        } 
        catch (NotBoundException e) 
        { 
            e.printStackTrace(); 
        } 
    } 
}

5、整體編譯代碼

javac –d . *.java

6、編譯生成stub

stub是什麼,stub是java爲rmi提供的封裝你遠程調用底層的一些細節處理(如socket和序列化操作),使你只需要去處理業務的實現而不必關注與底層網絡的處理(有興趣可以反編譯去看看它是如何實現的,其實也很簡單)。

rmic cn.wzh.ConverterImpl

其中rmic是RMI編譯器,ConverterImpl爲遠程接口實現類名,它是編譯過的class文件。

遠程方法實現接口類(ConverterImpl)生成的stub名字規定爲 `ConverterImpl` + `_stub`(ConverterImpl_stub.class)。

7、啓動RMI服務器(RMIServer)

java cn.wzh.RMIServer

若出現這樣的異常

image

需要在編寫權限文件(Converter.policy),這裏不對權限文件做太多講解,我將會另外用一邊文章來講解權限文件。

內容爲:

grant { 
    permission java.security.AllPermission; 
};

再次編譯運行,注意-D傳入權限文件位置

java -Djava.security.policy=cn/wzh/converter.policy cn.wzh.RMIServer

不好意思,又一次運行出錯

image

這是因爲你本地java RMI服務器沒有啓動,現在就啓動吧

start rmiregistry

再次運行 java -Djava.security.policy=cn/wzh/converter.policy cn.wzh.RMIServer

image

終於是啓動成功了,那麼開始運行RMI客戶端。

8、運行RMI客戶端

值得注意的是RMI客戶端也需要加入權限文件的位置,不然也會拋出權限異常。

java -Djava.security.policy=cn/wzh/converter.policy cn.wzh.RMIClient

image

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章