熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

Java遠程方法調用 (4)

2013-11-23 19:19:26  來源: Java核心技術 

  與現有服務器的連接
  人們常說RMI主要是從Java到Java但這種說法掩蓋了這樣一個事實Java可使用被稱為JNI的本機方法接口很容易地與現有和原有系統連接JNI和RMI的混合使用與任何其它Java程序一樣簡單您可使用JDBC再結合RMI與現有的關系數據庫連接也就是說您可使用RMI連接二層次和三層次系統即使雙方都不是用Java 編寫的亦可這樣做有很大的好處和優勢下面會詳細闡述但首先讓我們看一看它是如何完成的
  
  假定您現在有一台在關系數據庫中存儲了有關客戶訂單信息的服務器在任何多層次系統中您都得設計一個遠程接口以便於客戶機訪問服務器利用作為Remote 接口的RMI
  
  import javarmi*;
  import javasqlSQLException;
  import javautilVector;
  public interface OrderServer extends Remote {
  Vector getUnpaid() throws RemoteException SQLException;
  void shutDown() throws RemoteException;
  // other methods (getOrderNumber getShipped )
  }
  javasql包包含JDBC包每個遠程方法均可被服務器采用實際數據庫的JDBC調用或通過采用其它數據庫訪問機制的本機方法實現上面所示的方法返回一個Order (訂單) 對象的Vector (列表)Order (訂單)就是在您的系統中定義的用來保存客戶訂單的類
  本節將介紹如何使用JDBC實現getUnpaid和如何使用JNI 實施shutDown
  
  JDBC 連接數據庫
  使用JDBC實現getUnpaid的OrderServerImpl如下
  
  import javarmi*;
  import javarmiserver*;
  import javasql*;
  import javautilVector;
  public class OrderServerImpl
  extends UnicastRemoteObject
  implements OrderServer
  {
  Connection db; // connection to the db
  PreparedStatement unpaidQuery; // unpaid order query
  OrderServerImpl() throws RemoteException SQLException {
  db = DriverManagergetConnection(jdbc:odbc:orders);
  unpaidQuery = dbpreparedStatement();
  }
  public Vector getUnpaid() throws SQLException {
  ResultSet results = unpaidQueryexecuteQuery();
  Vector list = new Vector();
  while (resultsnext())
  listaddElement(new Order(results));
  return list;
  }
  public native void shutDown();
  }
  其中大多是JDBC任務除了以Order開始的類型是您的系統的一部分類型以外您所看到的所有類型均為JDBC或 RMI的一部分構造函數初始化OrderServerImpl對象創建與jdbc URL中所規定的數據庫的連接( Connection)有了這個連接我們就可以使用prepareStatement定義一個能找到所有未付款訂單的查詢在此還可為其它方法定義其它查詢OrderServerImpl作為數據庫在同一個系統上運行而且還可能是在同一個進程中(下面將討論shutDown)
  
  當getUnpaid方法在RMI服務器對象OrderServerImpl上被調用後就會執行預先編譯的查詢並返回包含所有匹配元素的JDBC ResultSet對象隨後我們為結果集中的每個項目創建新的Order對象並將其添加到Vector對象中( Java 的動態數組)在結束讀取結果後我們將這個向量返回給客戶機後者可將結果顯示給用戶或者其他相關的人
  
  JNI 本機方法
  RMI服務器和客戶機可利用本機方法與現有的和原有的系統連接您可使用本機方法實現不能直接訪問數據庫的遠程方法或者通過采用現有代碼更簡單地實現您可使用本機接口JNI編寫C和C++程序以實現?Java方法並 Java對象上調用該方法用本機方法實現shutDown的程序如下
  
  JNIEXPORT void JNICALL
  Java_OrderServerImpl_shutDown(JNIEnv *env jobject this)
  {
  jclass cls;
  jfieldID fid;
  DataSet *ds;
  cls = (*env)>GetObjectClass(env this);
  fid = (*env)>GetFieldID(env cls dataSet J);
  ds = (DataSet *) (*env)>GetObjectField(env this fid);
  /* With a DataSet pointer we can use the original API */
  DSshutDown(ds);
  }
  這是假定了現有服務器通過其API定義的DataSet類型得到了引用指向服務器DataSet的指針存儲在dataSet域中當客戶機調用shutDown時服務器的shutDown方法就會被調用因為在服務器實現中聲明了要用本機方法來實現shutDown 方法所以RMI將直接調用這個本機方法這個本機方法找到對象的dataSet域得到其值並用它調用現有API 的函數DSshutDown
  
  Sun公司目前正與ILOG公司合作開發一種稱作TwinPeaks 的產品TwinPeaks將能夠兼容目前的C和C++ API並生成 Java類該Java類包含了到Java類中API的調用這樣您就能從Java調用現有的任何APITwinPeaks面市後將有可能完全使用Java (而非JNI調用)編寫諸如shutDown這樣的方法
  
  體系結構
  RMI系統可為分布式面向對象計算提供簡單而又直接的基礎其體系結構可允許對服務器和引用類型進行擴展從而使RMI能以連續的方式添加功能
  
  當服務程序被輸出後其引用類型就被定義在上面的例子中我們將服務器作為UnicastRemoteObject服務器輸出即點到點非復制服務器對這些對象的引用對於這類服務器非常合適不同類型的服務器有不同的引用句法例如MulticastRemoteObject就有允許復制服務的引用句法
  
  當客戶機收到向服務器的引用後RMI就會下載一個可將該引用上的調用轉換為面向服務器的遠程調用的存根如圖所示存根使用對象序列化法將參數編組到方法中並通過網絡將經過編組的調用送到服務器在服務器端RMI系統接收調用並連接到一個框架上而框架則負責解除參數編組並在服務器上調用該方法的實現當服務器的執行完成後無論返回一個值或拋出一個例外框架通過對結果進行編組並向客戶機的存根發送一個應答存根解除應答編組並根據需要返回一個值或拋出一個例外存根和框架是用服務器的實現生成的通常使用的是程序rmic存根使用引用與框架進行會話這種體系結構使引用能夠定義通信的屬性用於 UnicastRemoteObject服務器的引用與在特定主機和端口上運行的單個服務器對象進行通信憑借存根/引用的分離功能RMI就能添加新的引用類型處理復制服務器的引用可將服務器請求多路發送給一組正確的復制程序匯集響應再根據多種響應返回正確的結果如果服務程序沒有在虛擬機上運行則另一個引用類型可激活該程序客戶機可透明地與所有這些引用類型共同工作
  
  保密與安全
  在執行RMI請求時安全是絕對有保證的RMI可在客戶機與服務器之間提供安全信道並可將下載的執行程序放入安全的沙箱(sandbox)中運行從而保護您的系統免遭不明客戶機可能的攻擊
  
  首先必須定義您的安全需求這非常重要如果您正在安全的企業網內部執行諸如ComputeServer這樣的程序則您只需知道誰在使用計算環路即可這樣您就能對濫用系統的人進行跟蹤如果您需要提供商業計算服務器則您就需要防止多種惡意的破壞這些都會影響接口的設計在企業內部您可能只要求每個Task對象都配備人名和部門編號以便跟蹤而在商業領域中您可能需要更高的安全性包括數字簽名身份識別和某些能幫助您剔除會耗費超過分配於其時間的惡意任務的合同語言
  
  在客戶機和服務器之間您可能需要有一個安全信道 RMI可使您能提供可創建包括加密插口(socket)在內的您所需要的任何類型插口的插口工廠從JDK 開始您將能夠指定服務器插口所提供的服務的要求(通過給出對這些要求的描述)這種新技術可在小應用程序上采用而多數浏覽器都拒絕承諾設置插口工廠插口要求可包括加密和其它要求
  
  下載的類也存在安全問題Java通過SecurityManager對象處理安全問題而該對象可傳遞所有與安全有關操作的判斷如打開文件和網絡連接等RMI通過要求您在輸出任何服務對象或在服務器上調用任何方法之前安裝安全管理器以使用這個標准的Java機制RMI提供與小應用程序(無文件存取只是連接到發出主機等)限制相同的 RMISecurityManager類型這樣可防止下載的執行程序從計算機上讀取或寫入數據或與防火牆後面的其它系統連接您也可編寫和安裝自己的安全管理程序對象以執行不同的安全限制
  
  防火牆
  RMI為防火牆後面的客戶機提供了與遠程服務器進行通信的方法這樣可使您使用RMI在因特網上部署客戶程序如在用於萬維網上的小應用程序中穿越客戶機的防火牆會使通信速度降低所以RMI成功地采用速度最快的技術連接客戶機與服務器當客戶機首次依次嘗試下列三種可能的方法試圖與服務器建立通信時該技術即被UnicastRemoteObject的引用所發現
  
  用插口(socket)直接與服務器的端口通信
  
  如果失敗則建立連接到服務器主機和端口上的URL並在該URL上使用HTTP POST請求將信息作為POST的主體發送給框架如果成功則post的結果就是框架對存根的響應
  
  如果又失敗則用端口 (標准HTTP端口)建立連接到服務器主機的URL並使用能夠將?MI請求發送給服務器的 CGI程序
  
  這三種技術哪一種首先成功將來就會首先被用來與服務器進行通信如果這些技術都不成功則遠程方法調用失敗
  
  這種三步策略使客戶機能夠以盡可能高的效率實現通信並大多使用直接插口連接在沒有安裝
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26656.html
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.