體驗RMI(實踐文章)

來源:互聯網
上載者:User
    遠程方法調用(RMI)機制可以把物件導向的思想進一步擴充,因為你可以調用的對象不僅可以在本機上,也可以在別的主機上。本文就簡單介紹rmi的編程方法。

  首先介紹一些簡單的rmi的概念。

  1, 伺服器和客戶:在rmi中,如果有一個對象進行遠程方法調用,這個對象就叫做客戶機對象,而遠程對象則被稱為伺服器對象。

  2, 建立伺服器對象的伺服器程式:這個程式用來建立伺服器對象,註冊這個對象,使得客戶可以通過註冊的名稱訪問伺服器對象。

  3, 介面(interface),介面可以讓用戶端瞭解伺服器所能做的工作。更具體的說,就是它列出了可以在伺服器上執行的所有方法。用戶端程式必須能夠找到這個類,否則就不能執行對伺服器函數的調用。

  4, 客戶樁(stub),有的書中翻譯成為程式碼端,它給用戶端程式提供一個樁,這個樁上"綁"著伺服器對象。當客戶程式需要調用遠程對象時,這個樁被下載到用戶端(如果用戶端有這個類,則不需要下載)。然後客戶就可以像調用本地方法一樣調用遠端方法了。

  這個客戶樁的作用是將客戶向伺服器的請求進行編碼、進行傳輸,伺服器執行這次調用後將結果返回到客戶樁,客戶樁進行解碼,將解碼後的結果傳送到客戶程式中。對於編寫用戶端的程式員來說,他不需要知道其中的具體過程。

  客戶樁不需要自己編寫,後面會說明它的產生方法。它實現了前述的介面(interface)。

  下面就通過一個例子來說明編寫的過程。

  1, 編寫伺服器的介面:這一步是最主要的部分,因為介面是串連客戶機與伺服器的關鍵區段。在這個例子中,介面很簡單,代碼如下:

import java.rmi.*;
public interface Product extends Remote
{
 String getDescription() throws RemoteException;
}

在 這裡應注意的是,遠程對象的介面一定要擴充(extend)Java.rmi包的Remote介面。同時介面中的所有的方法都要聲明拋出 RemoteException異常。這是因為由於網路連接的不可靠性,遠程方法調用很可能失敗。如果不聲明異常,在遠程方法調用失敗後,應用程式就會無 法結束。

2, 編寫伺服器對象:

  Java中具有一個可以直接使用的伺服器類--UniCastRemoteObject。它存在於Java.rmi.server包中。我們可以直接擴充這個類,使它實現前述的介面。這樣就可以使伺服器滿足我們的需要。

import java.rmi.server.*;
import java.rmi.*;
public class ProductImpl extends UnicastRemoteObject implements Product
{
 public ProductImpl(String name) throws RemoteException
 {
  Desc = name;
 }
 public String getDescription() throws RemoteException
 {
  return "This is "+Desc+" product";
 }
 private String Desc;
}

  可以看到,rmi伺服器的實現和其他的方法代碼沒有什麼不同。

  3, 編寫建立伺服器對象的伺服器程式:

import java.rmi.*;
public class ProductServer
{
 public static void main(String[] args)
 {
  try
  {
   System.out.println("Constructin Server implementations ....");
   ProductImpl p1 = new ProductImpl("toaster");
   ProductImpl p2 = new ProductImpl("microwave");
   System.out.println("Binding server implementations to registry");
   Naming.rebind("toaster",p1);
   Naming.rebind("microwave",p2);
   System.out.println("waiting for clients...");
  }catch(Exception e)
  {
   System.out.println("Error "+e);
  }
 }
}

通 過代碼可以看到,這個伺服器首先建立了兩個伺服器對象。然後使用Naming.rebind()方法,將這個對象和一個名稱聯絡(綁定)在一起。這個名稱 就是客戶機尋找伺服器對象所使用的名稱。Naming是java.rmi包中的類。這個類的作用是建立一套尋找對象的命名機制。通過它就可以將綁定在特定 名稱上的對象找到。

  4, 編寫用戶端代碼:

import java.rmi.*;
import java.rmi.server.*;
public class ProductClient
{
 public static void main(String[] args)
 {
  System.out.println("begin to invoke remote method");
  System.setSecurityManager(new RMISecurityManager());
  String url = "rmi://91.1.1.119:1099/";
  try
  {
   file://尋找遠程對象
   System.out.println("1");
   Product c1 = (Product)Naming.lookup(url + "toaster");
   Product c2 = (Product)Naming.lookup(url + "microwave");
   file://調用遠程方法
   System.out.println("2");
   System.out.println(c1.getDescription());
   System.out.println("3");
   System.out.println(c2.getDescription());
  }catch (Exception ex)
  {
   System.out.println("error "+ex);
  }
 }
}

   在這段代碼中,首先定義了一個字串url。這個字串中儲存了找到遠程伺服器對象的協議和地址資訊。在rmi中,所使用的協議是rmi,連接埠號碼是 1099。這個例子中,我的伺服器對象存放在ip地址為91.1.1.119的主機上,所以,這個字串的值為rmi://91.1.1.119: 1099/。

  接著,使用Naming.lookup()方法尋找遠程對象。參數就是伺服器的位置資訊和伺服器對象所綁定的名稱。

  這裡需要注意的是,通過lookup方法得到其實不是伺服器對象本身的引用,而是下載到客戶機上的客戶樁。但是,這個方法得到的是Object類型,要使用這個對象,必須將它類型轉換成伺服器所實現的介面類型。

  隨後,就可以像調用本地方法一樣調用遠程方法。在這個例子中,遠程方法是getDescription()。

  因為這段代碼是對遠程對象進行操作,所以,它被放到一個try…catch塊中,來捕獲遠程調用過程中的異常。

最後,就要將伺服器和客戶機部署到機器上。

  1,將所有的類檔案編譯為class檔案。然後在dos方式下使用

rmic ProductImpl

   就可以產生客戶樁,名為ProductImpl_Stub.class。

  2,把用戶端代碼和介面代碼拷貝到客戶機器上。

  3,運行rmiregistry程式,啟動註冊系統,使得伺服器可以註冊在機器上,以供客戶調用。

  4,啟動http服務。將介面類和客戶樁類放在http伺服器上,使得客戶可以下載。假設這兩個檔案的下載目錄是http://91.1.1.119/download/

  5,使用start java -Djava.rmi.server.codebase= http://91.1.1.119/download/ ProductServer

  運行建立伺服器對象的程式。

  其中的-Djava.rmi.server.codebase= http://91.1.1.119/download/ 指明客戶程式下載客戶樁的地址。

  6,因為rmi有安全限制,所以在用戶端必須建立一個策略檔案。假設名為client.policy

  檔案的內容為

grant
{
 permission java.net.SocketPermission "91.1.1.119:1024-65535","connect";
 permission java.net.SocketPermission "91.1.1.119:80","connect";
};

   使用 start java -Djava.security.policy=client.policy ProductClient 啟動用戶端,用戶端就可以串連80連接埠(http連接埠)和1024-65535的連接埠(其中包含了rmi的預設連接埠1099)。之後就可以看到程式的執行 結果。

  以上就是使用rmi進行遠程方法調用的基本過程。

  但是,應該注意到,rmi有一個很大的限制,那就是只能在java編寫的對象之間使用,如果要在不同的語言寫成的對象之間通訊,那就需要CORBA的協助

博主註:
1.    我沒有使用後文介紹的啟動rmiregistry這種方法,而是在程式中的伺服器端
    LocateRegistry.createRegistry(連接埠號碼);
    Naming.rebind("rmi://localhost:"+連接埠號碼+"/TestService",ri);
    必須要註冊,否則會拋出java.rmi.ConnectException: Connection refused……的錯誤
2.   一般開發中我們採取保留stub端源碼的方法,這樣就在rmic 加上-keep參數,就會產生源碼,用IDE編譯可以帶到用戶端去更方便。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.