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.rebind向Register 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.
產生stub和skeleton程式:
產生stub和skeleton程式的方法是透過rmic指令,如下…
rmic FundServer
執行上述指令後,會產生FundServer_Stub.class和FundServer_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