RMI

(史帝芬, idealist@gcn.net.tw, 2002/08/31, jdk 1.4)

 

1.      RMI架構:

1 RMI架構圖

 

2.      PolicyTool:

RMI實際上是用socket溝通,只是實際運作細節由RMI隱藏,程式設計師不需要處理,但是因為是透過socket,需要透過PolicyTool開放權限,RMI才能使用。要修改socket的權限很簡單,只要在command line執行policytool即會出現如圖2畫面,開啟C:\j2sdk\jre\lib\security\java.policy,選擇編輯規則項目將會出現如圖3的畫面,選擇新增許可權後鍵入圖4的資料,如此就將port1024以上的socket權限開放了。

2

 

3

 

4

 

3.      定義遠端介面:

欲提供服務之前,需先定義一個遠端物件的服務介面,透過這個介面,Client端程式才可以運用Server端物件的方法。對於這個介面的撰寫有兩點規定…

A.     必須繼承java.rmi.Remote介面。

B.     必須定義Server端物件的方法,並且宣告拋出RemoteException的例外事件。

 

範例程式:

import java.rmi.*;

 

public interface FundIF extends Remote {

  public double getFund(int capital, double rate, int year) throws RemoteException;

}

 

4.      Server端程式設計:

定義好遠端物件介面後,接下來要實作Server端程式,Server端程式有如下規定…

A.     宣告實作上述定義的介面。

B.     需繼承UnicastRemoteObject類別。

C.     欲提供給Client端使用的方法,必須宣告拋出RemoteException例外事件。

D.     在程式中利用Naming.rebindRegister Server做登錄。

 

範例程式:

import java.rmi.server.UnicastRemoteObject;

import java.rmi.*;

import java.lang.Math;

 

public class FundServer extends UnicastRemoteObject implements FundIF {

 

  public FundServer() throws RemoteException {

    super();

  }

 

  public double getFund(int capital, double rate, int year) throws RemoteException {

    double money = capital * Math.pow((1+rate), year);

    return money;

  }

 

  public static void main(String[] args) {

    try {

      Naming.rebind("rmi://163.13.71.155:31326/FundObj", new FundServer());

      System.out.println("RMI Connecting...");

    }

    catch (Exception e) {

      System.out.println("RMI can't connect.. : " + e);

      System.exit(-1);

    }

  }

}

 

5.      產生stubskeleton程式:

產生stubskeleton程式的方法是透過rmic指令,如下…

rmic FundServer

執行上述指令後,會產生FundServer_Stub.classFundServer_Skel.class兩支程式。

 

6.      Client端程式設計:

Client端程式為防止可能發生的任何安全上的疏失,因為在程式中需透過System.setSecurityManager(new RMISecurityManager());設定系統安全相關的政策。同時Client端程式要找尋Register Server上的遠端物件應透過Naming類別中的lookup方法。

 

範例程式:

import java.awt.*;

import java.rmi.*;

 

public class FundClient {

  public static void main(String[] args) {

    double money = 0.0d;

    try {

      System.setSecurityManager(new RMISecurityManager());

      FundIF obj = (FundIF) Naming.lookup("rmi://163.13.71.155:31326/FundObj");

      money = obj.getFund(20000, (double) 0.3, 2);

      System.out.println("Total money is : " + money);

    }

    catch (Exception e) {

      System.out.println(e.getMessage());

    }

  }

}

 

7.      執行:

A.     啟動Register Server,指令為 start rmiregistry port

B.     啟動Server端程式,start java FundServer

C.     執行Client端程式,java FundClient