程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 遠程接口的實施

遠程接口的實施

編輯:關於JAVA

服務器必須包含一個擴展了UnicastRemoteObject的類,並實現遠程接口。這個類也可以含有附加的方法,但客戶只能使用遠程接口中的方法。這是顯然的,因為客戶得到的只是指向接口的一個句柄,而非實現它的那個類。
必須為遠程對象明確定義構建器,即使只准備定義一個默認構建器,用它調用基礎類構建器。必須把它明確地編寫出來,因為它必須“擲”出RemoteException違例。
下面列出遠程接口PerfectTime的實施過程:

 

//: PerfectTime.java
// The implementation of the PerfectTime 
// remote object
package c15.ptime;
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
import java.net.*;

public class PerfectTime 
    extends UnicastRemoteObject
    implements PerfectTimeI {
  // Implementation of the interface:
  public long getPerfectTime() 
      throws RemoteException {
    return System.currentTimeMillis();
  }
  // Must implement constructor to throw
  // RemoteException:
  public PerfectTime() throws RemoteException {
    // super(); // Called automatically
  }
  // Registration for RMI serving:
  public static void main(String[] args) {
    System.setSecurityManager(
      new RMISecurityManager());
    try {
      PerfectTime pt = new PerfectTime();
      Naming.bind(
        "//colossus:2005/PerfectTime", pt);
      System.out.println("Ready to do time");
    } catch(Exception e) {
      e.printStackTrace();
    }
  }
} ///:~


在這裡,main()控制著設置服務器的全部細節。保存RMI對象時,必須在程序的某個地方采取下述操作:
(1) 創建和安裝一個安全管理器,令其支持RMI。作為Java發行包的一部分,適用於RMI唯一一個是RMISecurityManager。
(2) 創建遠程對象的一個或多個實例。在這裡,大家可看到創建的是PerfectTime對象。
(3) 向RMI遠程對象注冊表注冊至少一個遠程對象。一個遠程對象擁有的方法可生成指向其他遠程對象的句柄。這樣一來,客戶只需到注冊表裡訪問一次,得到第一個遠程對象即可。

1. 設置注冊表
在這兒,大家可看到對靜態方法Naming.bind()的一個調用。然而,這個調用要求注冊表作為計算機上的一個獨立進程運行。注冊表服務器的名字是rmiregistry。在32位Windows環境中,可使用:
start rmiregistry
令其在後台運行。在Unix中,使用:
rmiregistry &
和許多網絡程序一樣,rmiregistry位於機器啟動它所在的某個IP地址處,但它也必須監視一個端口。如果象上面那樣調用rmiregistry,不使用參數,注冊表的端口就會默認為1099。若希望它位於其他某個端口,只需在命令行添加一個參數,指定那個端口編號即可。對這個例子來說,端口將位於2005,所以rmiregistry應該象下面這樣啟動(對於32位Windows):
start rmiregistry 2005
對於Unix,則使用下述命令:
rmiregistry 2005 &
與端口有關的信息必須傳送給bind()命令,同時傳送的還有注冊表所在的那台機器的IP地址。但假若我們想在本地測試RMI程序,就象本章的網絡程序一直測試的那樣,這樣做就會帶來問題。在JDK 1.1.1版本中,存在著下述兩方面的問題(注釋⑦):
(1) localhost不能隨RMI工作。所以為了在單獨一台機器上完成對RMI的測試,必須提供機器的名字。為了在32位Windows環境中調查自己機器的名字,可進入控制面板,選擇“網絡”,選擇“標識”卡片,其中列出了計算機的名字。就我自己的情況來說,我的機器叫作“Colossus”(因為我用幾個大容量的硬盤保存各種不同的開發系統——Clossus是“巨人”的意思)。似乎大寫形式會被忽略。
(2) 除非計算機有一個活動的TCP/IP連接,否則RMI不能工作,即使所有組件都只需要在本地機器裡互相通信。這意味著在試圖運行程序之前,必須連接到自己的ISP(因特網服務提供者),否則會得到一些含義模糊的違例消息。

⑦:為找出這些信息,我不知損傷了多少個腦細胞。

考慮到這些因素,bind()命令變成了下面這個樣子:
Naming.bind("//colossus:2005/PerfectTime", pt);
若使用默認端口1099,就沒有必要指定一個端口,所以可以使用:
Naming.bind("//colossus/PerfectTime", pt);
在JDK未來的版本中(1.1之後),一旦改正了localhost的問題,就能正常地進行本地測試,去掉IP地址,只使用標識符:
Naming.bind("PerfectTime", pt);
服務名是任意的;它在這裡正好為PerfectTime,和類名一樣,但你可以根據情況任意修改。最重要的是確保它在注冊表裡是個獨一無二的名字,以便客戶正常地獲取遠程對象。若這個名字已在注冊表裡了,就會得到一個AlreadyBoundException違例。為防止這個問題,可考慮堅持使用rebind(),放棄bind()。這是由於rebind()要麼會添加一個新條目,要麼將同名的條目替換掉。
盡管main()退出,我們的對象已經創建並注冊,所以會由注冊表一直保持活動狀態,等候客戶到達並發出對它的請求。只要rmiregistry處於運行狀態,而且我們沒有為名字調用Naming.unbind()方法,對象就肯定位於那個地方。考慮到這個原因,在我們設計自己的代碼時,需要先關閉rmiregistry,並在編譯遠程對象的一個新版本時重新啟動它。
並不一定要將rmiregistry作為一個外部進程啟動。若事前知道自己的是要求用以注冊表的唯一一個應用,就可在程序內部啟動它,使用下述代碼:
LocateRegistry.createRegistry(2005);
和前面一樣,2005代表我們在這個例子裡選用的端口號。這等價於在命令行執行rmiregistry 2005。但在設計RMI代碼時,這種做法往往顯得更加方便,因為它取消了啟動和中止注冊表所需的額外步驟。一旦執行完這個代碼,就可象以前一樣使用Naming進行“綁定”——bind()。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved