《Java網絡程序設計》課件-第9章_第1頁
《Java網絡程序設計》課件-第9章_第2頁
《Java網絡程序設計》課件-第9章_第3頁
《Java網絡程序設計》課件-第9章_第4頁
《Java網絡程序設計》課件-第9章_第5頁
已閱讀5頁,還剩44頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第9章遠程方法調用

9.1RMI9.2RMI工作機制9.3RMI實現技術

9.1RMI

9.1.1RMI的概念

分布式計算的實質是“要求運行在不同地址空間不同主機上的對象互相調用。”各種分布式系統都有自己的調用協議,著名的解決方案有:

●?公共對象請求代理體系結構(CommonObjectRequestBrokerArchitecture,CORBA)的IIOP(InternetInterORBProtocol,互聯網內部對象請求代理協議)。CORBA體系結構是對象管理組織(ObjectManagermentGroup,OMG)為解決分布式處理環境(DistributedComputingEnviornment,DCE)中,硬件和軟件系統的互連而提出的一種解決方案。●?微軟事務服務器(MicrosoftTransactionServer,MTS)中的分布式組件對象模型(DistributedComponentObjectModel,DCOM)。DCOM是一系列微軟的概念和程序接口,利用這個接口,客戶端程序對象能夠請求來自網絡中另一臺計算機上的服務器程序對象。

●?RMI。RMI是Java的一組開發分布式應用程序的API。RMI使用Java語言接口定義了遠程對象,它集合了Java序列化和Java遠程方法協議(JavaRemoteMethodProtocol)。它是一種機制,能夠讓在某個Java虛擬機上的對象調用另一個Java虛擬機中對象上的方法,可以調用任何實現該遠程接口的對象。

Java語言之所以被稱為網絡開發語言,因為它一開始就與Web開發聯系在一起,并擁有“強大開發分布式網絡應用”的能力,RMI就是開發百分之百純Java的網絡分布式應用系統的核心解決方案之一。

RMI是Java在JDK1.1中實現的,是非常重要的底層技術,它大大增強了Java開發分布式應用的能力。EJB(EnterpriseJavaBean)就是建立在RMI基礎之上的,現在還有一些開源的遠程調用組件,其底層技術也采用了RMI。

RMI使用Java語言接口定義了遠程對象,它集合了Java序列化和Java遠程方法協議(JavaRemoteMethodProtocol)。簡單地說,這樣使原先的程序由在同一操作系統的方法調用,變成了在不同操作系統之間程序的方法調用。由于J2EE是分布式程序平臺,因而RMI機制可實現程序組件在不同操作系統之間的通信。比如,一個EJB可以通過RMI調用Web上另一臺機器上的EJB遠程方法,即跨平臺操作,如圖9-1所示。圖9-1RMI工作原理

RMI以Java為核心,它將Java的安全性和可移植性等強大功能帶給了分布式計算,所以可將代理和業務邏輯等屬性移動到網絡中最合適的地方,例如遠程的服務器。RMI可以被看做是遠程過程控制(RemoteProcessControl,RPC)的Java版本,但是傳統的RPC并不能很好地應用于分布式對象系統。而RMI則支持存儲于不同地址空間的程序級對象之間彼此進行通信,實現遠程對象之間的無縫遠程調用。

在Java的RMI規范中提供的功能有:

●?支持對存在于不同虛擬機上的對象進行無縫的遠程調用;●?支持服務器對客戶的回調;

●?把分布式對象模型自然地集成到Java語言里,盡可能從語義上保留Java的面向對象的特征;

●?使分布式對象模型和本地Java對象模型間的差異明朗;

●?使編寫可靠的分布式應用程序盡可能簡單;

●?保留Javarun-time環境所提供的安全性;

●?多樣化的遠程調用機制;

●?支持多點傳輸的能力;

●?支持分布式的垃圾回收。9.1.2RMI的優點

RMI為采用Java對象的分布式計算提供了簡單而直接的途徑,通過RMI技術充分體現了“編寫一次就能在任何地方運行的模式”。RMI可利用標準Java本機方法接口JNI與現有的和原有的系統相連接。RMI還可利用標準JDBC類庫與關系型數據庫連接,即RMI/JNI和RMI/JDBC相結合,并且可利用RMI與目前使用非Java語言的現有服務器進行通信。

RMI的主要優點如下:

(1)面向對象。RMI可將完整的對象作為參數和返回值進行傳遞,而不僅僅是預定義的數據類型。也就是說,您可以將類似Java哈希表這樣的復雜類型作為一個參數進行傳遞。而在目前的RPC系統中,您只能依靠客戶機將此類對象分解成基本數據類型,然后傳遞這些數據類型,最后在服務器端重新創建哈希表。RMI則不需額外的客戶程序代碼(將對象分解成基本數據類型),直接跨網傳遞對象。

(2)可移動屬性。RMI可將屬性(類實現程序)從客戶機移動到服務器,或者從服務器移到客戶機。例如,可以定義一個檢查雇員開支報告的接口,以便察看雇員是否遵守了公司目前實行的政策。在開支報告創建后,客戶機就會從服務器端獲得實現該接口的對象。如果政策發生變化,服務器端就會開始返回使用了新政策的該接口的另一個實現程序。不必在用戶系統上安裝任何新的軟件就能在客戶端檢查限制條件,從而向用戶提供快速的反饋,并降低服務器的工作量。這樣程序就能具備最大的靈活性,因為政策改變時您只需要編寫一個新的Java類,并將其在服務器主機上安裝一次即可。

(3)設計方式。對象傳遞功能使您可以在分布式計算中充分利用面向對象技術的強大功能,如二層和三層結構系統。如果對象能夠傳遞屬性,那么就可以在解決方案中使用面向對象的設計方式。所有面向對象的設計方式無不依靠不同的屬性來發揮功能,如果不能傳遞完整的對象(包括實現和類型),就會失去設計方式上所提供的優點。

(4)安全性。RMI使用Java內置的安全機制保證下載執行程序時用戶系統的安全。RMI使用專門為保護系統免遭惡意小應用程序侵害而設計的安全管理程序,可保護您的系統和網絡免遭潛在的惡意下載程序的破壞。在情況嚴重時,服務器可拒絕下載任何執行程序。

(5)便于編寫和使用。RMI使得Java遠程服務程序和訪問這些服務程序的Java客戶程序的編寫工作變得輕松、簡單。遠程接口實際上就是Java接口。服務程序大約用三行指令聲明其本身是服務程序,其他方面則與Java對象類似。這種方法便于快速編寫完整的分布式對象系統的服務程序,并快速地制做軟件的原型和早期版本,以便于進行測試和評估。RMI程序編寫簡單,維護簡便。

(6)可連接現有/原有的系統。RMI可通過Java的本機方法接口JNI與現有系統進行進行交互。利用RMI和JNI,您就能用Java語言編寫客戶端程序,還能使用現有的服務器端程序。在使用RMI/JNI與現有服務器連接時,您可以有選擇地用Java重新編寫服務程序的任何部分,并使新的程序充分發揮Java的功能。類似地,RMI可利用JDBC、在不修改使用數據庫的現有非Java源代碼的前提下與現有關系數據庫進行交互。

(7)編寫一次,到處運行。RMI是Java“編寫一次,到處運行”方法的一部分。任何基于RMI的系統均可100%地移植到任何Java虛擬機上,RMI/JDBC系統也不例外。如果使用RMI/JNI與現有系統進行交互工作,則采用JNI編寫的代碼可在任何Java虛擬機進行編譯、運行。

(8)分布式垃圾收集。RMI采用分布式垃圾收集功能收集不再被網絡中任何客戶程序所引用的遠程服務對象。與Java虛擬機內部的垃圾收集類似,分布式垃圾收集功能允許用戶根據自己的需要定義服務器對象,并且明確這些對象在不被客戶機引用時會刪除。

(9)并行計算。RMI采用多線程處理方法,可使服務器利用這些Java線程更好地并行處理客戶端的請求。Java分布式計算解決方案:RMI從JDK1.1開始就是Java平臺的核心部分,因此,它存在于任何一臺1.1Java虛擬機中。所有RMI系統均采用相同的公開協議,所以,所有Java系統均可直接相互對話,而不必事先對協議進行轉換。

9.2RMI工作機制

RMI應用程序通常包括兩個獨立的程序,即服務器端程序和客戶機端程序。典型的服務器應用程序將創建多個遠程對象,使這些遠程對象能夠被引用,然后等待客戶機調用這些遠程對象的方法。而典型的客戶機程序則從服務器中得到一個或多個遠程對象的引用,然后調用遠程對象的方法。RMI為服務器和客戶機進行通信和信息傳遞提供了一種機制。

RMI為服務器和客戶機進行遠程通信和信息傳遞提供了一種標準機制,即樁(stub)和構架(skeleton)。其中,遠程對象的stub擔當遠程對象的客戶本地代表或代理人角色。調用程序將調用本地stub的方法,而本地stub將負責執行對遠程對象的方法調用。stub通常負責初始化遠程調用、序列化、遠程方法調用、反序列化、遠程方法調用完成處理等。遠程對象的stub與該遠程對象所實現的遠程接口集相同。調用stub的方法時將執行下列操作:

●?初始化與包含遠程對象的遠程虛擬機的連接;

●?對遠程虛擬機的參數進行編組(寫入并傳輸);●?等待方法調用結果;

●?解編(讀取)返回值或返回的異常;

●?將值返回給調用程序。

為了向調用程序展示比較簡單的調用機制,stub將參數的序列化和網絡級通信等細節隱藏了起來。

在遠程虛擬機中,每個遠程對象都可以有相應的架構(在JDK1.2環境中無需使用架構)。架構負責將調用分配給實際的遠程對象實現(反序列化)、反序列化客戶端參數、調用實際遠程對象、序列化返回客戶端參數。它在接收方法調用時執行下列操作:

●?解編(讀取)遠程方法的參數;●?調用實際遠程對象實現上的方法;

●?將結果(返回值或異常)編組(寫入并傳輸)給調用程序。

樁和架構是應用程序與系統其他部分的接口,通常使用RMI的rmic編譯器產生。

RMI系統結構由以下三個部分組成:

●?樁/構架層:應用程序與系統其他部分的接口;

●?遠程引用層:負責獨立于客戶樁和服務器構架,提供多種形式的遠程引用和調用協議;

●?傳輸層:低級層,在不同的地址空間內傳輸序列化的流。

RMI工作機制為:調用通過樁/構架層傳遞,它們作為應用程序與RMI系統其他部分的一個接口來提供服務,其唯一目的是通過序列化流,傳輸數據到遠程引用層;一旦數據通過樁/構架層傳遞,它將通過遠程引用層實現調用,并且使用面向連接的流,將數據傳遞到傳輸層;當數據到達,傳輸層負責建立連接并管理這些連接。RMI系統的結構如圖9-2所示。圖9-2RMI系統結構遠程方法調用的流向為:從客戶對象經樁程序、遠程引用層(RemoteReferenceLayer)和傳輸層(TransportLayer)向下,傳遞給主機,然后再次經傳輸層,向上穿過遠程調用層和骨干網(Skeleton),到達服務器對象,如圖9-2中虛線流向。

在RMI系統結構中,樁程序扮演著遠程服務器對象的代理的角色,使該對象可被客戶激活。遠程引用層處理語義,管理單一或多重對象的通信,決定調用是發往一個服務器還是多個。傳輸層管理實際的連接,并且追蹤可以接受方法調用的遠程對象。服務器端的骨干網完成對服務器對象實際的方法調用,并獲取返回值。返回值向下經遠程引用層、服務器端的傳輸層傳遞回客戶端,再向上經傳輸層和遠程調用層返回。最后,樁程序獲得返回值。典型的服務器應用程序將創建多個遠程對象,并使這些遠程對象能夠被引用,然后等待客戶機調用這些遠程對象提供的方法。典型的客戶機程序則從服務器中得到一個或多個遠程對象的引用,然后調用遠程對象的方法。

9.3RMI實現技術

9.3.1RMI類和工具

利用RMI編寫分布式對象應用程序需要五個類庫包和三個應用軟件工具。其中,五個類庫包分別是:

java.rmi,提供客戶端的RMI類、接口和異常類;

java.rmi.server,提供服務器端的RMI類,接口和異常類;

java.rmi.registry,用于管理RMI命名服務的類;

java.rmi.dgc,用于管理分布式垃圾收集(Distributional

GarbageCollection)的類;

java.rmi.activation,用于按需激活的RMI服務的類。三個應用軟件工具均包含在JSDK安裝路徑的bin目錄下,分別是:

rmic.exe,它是RMI編譯器,在使用javac編譯java源程序后,還需要使用rmic編譯服務器端的class文件,用于生成stub和skeleton;

rmiregistry.exe,一個為RMI提供命名服務的服務器,這項服務把名字和對象關聯在一起,即將RMI服務注冊為一個遠程對象以便客戶端的調用;

rmi.exe,一個支持RMI激活框架的服務器。9.3.2RMI實現流程

因為RMI允許調用程序將純Java對象傳給遠程對象,所以RMI將提供必要的機制,既可以加載對象的代碼又可以傳輸對象的數據。在RMI分布式應用程序運行時,服務器調用注冊服務程序以使名字與遠程對象相關聯。客戶機在服務器上的注冊服務程序中用遠程對象的名字查找該遠程對象,然后調用它的方法。利用RMI編寫分布式對象應用程序需要完成以下工作:

●?定位遠程對象。應用程序可使用兩種機制中的一種得到對遠程對象的引用。它既可用RMI的簡單命名工具rmiregistry來注冊它的遠程對象,也可以將遠程對象引用作為常規操作的一部分來進行傳遞和返回。●?與遠程對象通信。遠程對象間通信的細節由RMI處理,對于程序員來說,遠程通信看起來就像標準的Java方法調用。

●?給作為參數或返回值傳遞的對象加載類字節碼。

為了實現以上工作,RMI實現的步驟如下:

(1)定義遠程服務接口,該接口必須聲明為public,必須繼承java.rmi.Remote接口。在接口定義中說明服務器提供的方法特性,包含了方法的名字和參數,這個服務方法必須拋出異常java.rmi.RemoteException;

(2)實現遠程服務接口所定義的方法;

(3)利用rmic生成樁和框架文件;

(4)一個運行遠程服務的服務器;

(5)一個RMI命名服務,它允許客戶端去發現這個遠程服務;

(6)注冊遠程對象;

(7)類文件的提供者(一個HTTP或者FTP服務器);

(8)一個需要這個遠程服務的客戶端程序。

【例9-1】定義遠程服務接口,一個用于數組相加的遠程服務接口。

1.importjava.rmi.*;

2.publicinterfaceArithextendsjava.rmi.Remote{

3.int[]add(inta[],intb[])throwsjava.rmi.RemoteException;

}

代碼注釋如下:

①第1行引用了重要的RMI類庫包;

②第2行定義了自定義的遠程接口Arith,該接口必須具有公開(public)屬性,而且繼承了java.rmi.Remote接口;

③第3行申明一個沒有方法體的add(),并且該方法拋出了java.rmi.RemoteException異常。

代碼注釋如下:

①第1~2行引用重要類庫包和類;

②第3行定義遠程服務類ArithImp1,它實現了事先定義遠程服務接口Arith,并且繼承了UnicastRemoteObject類,用于遠程單播傳輸對象;

③第4行定義成員屬性,用于存儲該遠程服務的名稱;

④第5~8行定義構造方法,通過super()指定本遠程服務的名稱;

⑤第9~14行覆蓋了Arith接口的add()方法,實現了數組相加功能;⑥第16~17行定義RMI安全管理器實例,并加入到系統的安全管理器中;

⑦第18~24行創建遠程對象的對象實例名稱為obj,通過rebind()注冊了遠程服務名稱ArithServer,將該服務綁定在“//localhost:3000/ArithServer”,使本地環回測試用戶可用。

該程序僅說明遠程服務的內容,運行該服務還需要特殊的指令。

客戶端是調用服務的,它提供用于服務的數據和獲得服務結果,如例9-3提供了兩個準備相加的數組。

代碼注釋如下:

①第1~2行引用重要的類庫包;

②第5~7行給出了用于服務的兩個數組a[]?和b[]?以及用于存儲結果的數組result[];

③第9行查找在遠程服務器localhost端口3000上開放的注冊服務ArithServer,并生成遠程引用對象obj;

④第10行調用遠程方法調用和傳遞參數;

⑤第14~17行輸出結果。

在第4章中,曾經提到使用多線程實現累加計數器,現在將它修改為采用RMI完成數值的累加。其不同之處在于,原程序在一臺計算機上啟動多個線程共同完成累加任務,現在變更為由多臺計算機同時完成累加任務。為了使觀察效果更好,將累加范圍改為1~10?000,并設置了計時器,通過計算所消耗時間來判斷是否得到優化。

【例9-4】數字累加累計接口。

1.

importjava.rmi.*;

2.publicinterfaceSumextendsjava.rmi.Remote{

3.intadd(intstart,intend)throwsjava.rmi.RemoteException;

4.}

代碼注釋如下:

①第2行定義遠程服務接口Arith,其繼承了java.rmi.Remote接口;

②第3行申明了遠程服務方法,其參數是用于累加數值的區間。

【例9-5】實現遠程服務,實現累加服務,注意運行在兩臺不同的服務器上,供客戶端調用。

代碼注釋如下:

①第1~2行引用重要類庫包和類;

②第3行定義遠程服務類SumImp,它實現了事先定義遠程服務接口Sum,并且繼承了UnicastRemoteObject類,用于遠程單播傳輸對象;

③第4行定義成員屬性,用于存儲該遠程服務的名稱;

④第5~8行定義構造方法,通過super()?指定本遠程服務的名稱;

⑤第9~14行覆蓋了Sum接口的add()?方法,實現了數組相加功能;⑥第16~17行定義RMI安全管理器實例,并加入到系統的安全管理器中;

⑦第18~24行創建遠程對象的對象實例名稱為obj,通過rebind()注冊了遠程服務名稱SumServer,將該服務綁定在“//服務運行的地址:3000/SumServer”,該服務運行的地址需要根據運行環境獲得。

【例9-6】客戶端將一個1~10000的累加工作分配到兩個遠程服務器上。

代碼注釋如下:

①第1~2行引用重要的類庫;

②第3行定義客戶端類,其實現了Runnable接口;

③第4~11行定義了累加數值的區間start和end,累加和sum和遠程服務名稱server;

④第12~19行實現線程運行入口,在指定的服務器上查找服務Naming.loop(server),如找到,則調用遠程方法obj.add(start,end);

⑤第24~25行自定義兩個線程對象,帶入參數,指定數值累加區間和遠程服務名稱;

⑥第28~29,31行啟動線程;

⑦第28、31、33行用于記錄累加所用的時間;

⑧第30行將這兩個子線程添加到主線程中,保證子線程先于主線程結束。9.3.3RMI運行步驟

由于RMI程序的運行依賴于網絡的遠程調用,它涉及安全問題,因而不同于普通的JavaApplication程序,其運行一共分為五步:

(1)使用javac*.java分別編譯接口程序、服務端程序和客戶端程序。

(2)使用rmic服務端的?.class文件,產生一個服務端的_Stub.class的產生樁和框架文件。樁和框架在服務器端運行時確定,根據需要動態裝載,采用rmic編譯器生成stub和skeleton。例如:rmicrmiExampl,在JDK1.5下,該命令執行后將生成一個樁文件,文件名為rmiExampl_Stub.class。

(3)使用startrmiregistry,在服務端啟動一個RMI注冊表,便于對服務端提供的遠程服務進行注冊;RMI注冊表是一個名字服務,允許客戶程序獲得對遠程對象的引用,在服務器/客戶程序之前,必須啟動RMI注冊表。啟動方式:

startrmiregistry

默認情況下,啟動的端口為1099。如果要改變端口則使用

startrmiregistry3000

(4)執行服務端和客戶端程序,應首先在服務端按安全策略文件運行服務器,輸入

java-Djava.security.policy=policyNameserverName

(5)在客戶端按安全策略文件運行客戶端,輸入

java-Djava.security.policy=policyNameclientName

注意,有的時候要在后面加上參數localhost。

在運行時,有可能出現如圖9-3所示的提示。圖9-3RMI服務端運行提示該提示中提到程序運行中出現了訪問控制異常(AccessControlException),對地址3000端口的連接和解析服務訪問被拒絕。出現該異常則說明程序運行還缺少策略文件。9.3.4策略文件

RMI程序是一個調用分布式資源的網絡程序,運行客戶端通過服務端的指定的端口訪問資源,需要控制的安全機制來保護服務端。在RMI中利用策略文件,對計算機端口的訪問進行某些設置。

策略文件是一個文本文件,里面記錄了一些對計算機資源訪問的方式,比如對本地文件的訪問控制,對端口的訪問控制等。其文件后綴名為“*.policy”。在Windows系

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論