爲通過網絡執行其他機器上的代碼,傳統的方法不僅難以學習,而且易出錯。解決這個問題的最佳方法是:某些對象正好位諏硪惶ɑ鰨頤強梢苑⑺鴕惶蹕ⅲ⒒竦梅禱亟峁拖裎揮謐約旱謀淨饕謊?span lang="EN-US">Java遠程方法調用(RMI)特性使客戶機上運行的程序可以調用遠程服務器上的對象。遠程方法調用特性使Java編程人員能夠在網絡環境中分佈操作。
下面介紹一下必要的步驟,創建自己的RMI對象。
一、遠程接口概念:
RMI對接口有着強烈的依賴。在需要創建一個遠程對象的時候,我們通過傳遞一個接口來隱藏基層的實施細節。所以客戶得到遠程對象的一個句柄正好同一些本地的根代碼連接,有後者負責通過網絡通信。但我們並不關心這些事情,通過自己的接口句柄發送消息即可。
創建一個遠程接口時,必須遵守下列規則:
1) 遠程接口必須爲public屬性(不能有“包訪問”;也就是說,他不能是“友好的”)。否則,一旦客戶試圖裝載一個實現了遠程接口的遠程對象,就會得到一個錯誤。
2) 遠程接口必須擴展接口java.rmi.Remote。
3) 除與應用程序本身有關的違例,遠程接口中的每個方法都必須在自己的throws從句中聲明java.rmi.RemoteException.
4) 作爲參數或返回值傳遞的一個遠程對象(不管是直接,還是本地對象中嵌入)必須聲明爲遠程接口,不可聲明爲實施類。
下面是一個遠程接口示例,
//PerfectTimeI.java<?XML:NAMESPACE PREFIX = O />
//The PerfectTime remote interface
package test;
import java.rmi.*;
public interface PerfectTimeI extends Remote {
long getPerfectTime() throws RemoteException;
}
它表面上與其他的接口類似,只是對Remote進行了擴展,而且所有的方法都會“擲”出RemoteException.接口和方法都是Public的。
編譯PerfectTimeI.java,生成PerfectTimeI.class(test是包,編譯時注意路徑)
G:/RMI>javac test/PerfectTimeI.java
二、遠程接口的實施:
服務器必須包含一個擴展了UnicastRemoteObject類,並實現遠程接口。這個類也可以含有附加的方法,但客戶只能使用遠程接口中的方法。因爲客戶是指向接口的一個句柄,而不是它的哪個類。
必須爲遠程對象定義構件器,即使只准備定義一個默認構件器,用它調用基礎類構件器。必須把它明確地編寫出來,因爲它必須“擲”出RemoteException違例。
下面列出遠程接口PerfectTime的事實過程:他代表精確計時服務
//PerfectTime.java
//The implementation of the PerfectTime remote object
package test;
import java.net.*;
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
public class PerfectTime extends UnicastRemoteObject implements PerfectTimeI
{
//默認構件器,也要“擲”出RemoteException違例。
public PerfectTime() throws RemoteException {
super();
}
public long getPerfectTime() throws RemoteException {
return System.currentTimeMillis();
}
public static void main(String[] args) {
/*創建和安裝一個安全管理器,令其支持RMI.作爲Java開發包的一部分,適用於RMI唯一一個是RMISecurityManager.*/
System.setSecurityManager(new RMISecurityManager());
try {
/*創建遠程對象的一個或多個實例,下面是PerfectTime對象*/
PerfectTime pt = new PerfectTime();
/*向RMI遠程對象註冊表註冊至少一個遠程對象。一個遠程對象擁有的方法即可生成指向其他遠程對象的句柄,這樣,客戶到註冊表裏訪問一次,得到第一個遠程對象即可.*/
Naming.bind("PerfectTime", pt);
System.out.println("Ready to do Time");
} catch (Exception e) {
e.printStackTrace();
}
}
}
編譯PerfectTime.java,生成PerfectTime.class(test是包,編譯時注意路徑)
G:/RMI>javac test/PerfectTime.java
三、創建根和幹:
創建RemoteObject的主幹和框架。要完成這個工作可使用rmic編譯器,rmic編譯器生成遠程對象的存根和骨架。存根(Stub)是遠程對象在客戶端的代理,它將RMI調用傳遞給服務器端的骨架(Skeleton),後者負責將該調用傳遞給實際的遠程方法輸入如下:
G:/RMI>rmic -d G:/RMI test.PerfectTime
執行這個命令,
若rmic成功運行,test目錄裏就會多出兩個新類:
PerfectTime_Stub.class
PerfectTime_Skel.class
它們分別對應的是根(stub)和幹(skeleton).
四、使用遠程對象:
RMI全部的宗旨就是可能簡化遠程接口對象的使用。我們客戶程序中要做的唯一一件額外事情是查找從服務器取回遠程接口。下面就是編寫的Java程序:將消息發給對象:
//DisplayPerfectTime.java
//Users remote object PerfectTime
package test;
import java.rmi.*;
import java.rmi.registry.*;
public class DisplayPerfectTime {
/*** DisplayPerfectTime 構造子註解。*/
public DisplayPerfectTime() {
super();
}
public static void main(String[] args) {
System.setSecurityManager(new RMISecurityManager());
try {
PerfectTimeI t = (PerfectTimeI) Naming.lookup("PerfectTime");
for (int i = 0; i < 10; i++) {
System.out.println("PerfectTime:" + t.getPerfectTime());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
編譯DisplayPerfectTime.java.
G:/RMI>javac test/DisplayPerfectTime.java
五、啓動註冊並運行代碼:
在運行PerfectTime類和DisplayPectTime類之前,用戶必須首先在將要宿主PerfectTime的計算機上啓動RMI註冊(Registry)程序,即使將要運行PerfectTime的計算機與運行DisplayPerfectTime的是同一臺機器,這一步也是必須的。註冊表服務器的名字是rmiregistry.在32位Windows環境中,可使用: start rmiregistry 令其在後臺運行。然後分別開兩個不同的進程運行Server端和Client端:啓動註冊表服務器:
G:/RMI>start rmiregistry
綁定PerfectTime到註冊,運行服務端程序:在Windows下,輸入下列命令,在後臺啓動PerfectTime程序:
G:/RMI>java test.PerfectTime
Ready to do Time
運行客戶端程序:如下
G:/RMI>java test.DisplayPerfectTime
PerfectTime:961722589649
PerfectTime:961722589669
PerfectTime:961722589679
PerfectTime:961722589679
PerfectTime:961722589689
PerfectTime:961722589689
PerfectTime:961722589689
PerfectTime:961722589699
PerfectTime:961722589699
PerfectTime:961722589699