一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Java遠(yuǎn)程方法調(diào)用(RMI)--好

 fanjj 2010-06-12

Java RMI (Remote Method Invocation 遠(yuǎn)程方法調(diào)用)是用Java在JDK1.1中實(shí)現(xiàn)的,它大大增強(qiáng)了Java開發(fā)分布式應(yīng)用的能力。Java作為一種風(fēng)靡一時(shí)的網(wǎng)絡(luò)開發(fā)語言,其巨大的威力就體現(xiàn)在它強(qiáng)大的開發(fā)分布式網(wǎng)絡(luò)應(yīng)用的能力上,而RMI就是開發(fā)百分之百純Java的網(wǎng)絡(luò)分布式應(yīng)用系統(tǒng)的核心解決方案之一。其實(shí)它可以被看作是RPC的Java版本。但是傳統(tǒng)RPC并不能很好地應(yīng)用于分布式對(duì)象系統(tǒng)。而Java RMI 則支持存儲(chǔ)于不同地址空間的程序級(jí)對(duì)象之間彼此進(jìn)行通信,實(shí)現(xiàn)遠(yuǎn)程對(duì)象之間的無縫遠(yuǎn)程調(diào)用。RMI目前使用Java遠(yuǎn)程消息交換協(xié)議JRMP(Java Remote Messaging Protocol)進(jìn)行通信。JRMP是專為Java的遠(yuǎn)程對(duì)象制定的協(xié)議。因此,Java RMI具有Java的"Write Once,Run Anywhere"的優(yōu)點(diǎn),是分布式應(yīng)用系統(tǒng)的百分之百純Java解決方案。用Java RMI開發(fā)的應(yīng)用系統(tǒng)可以部署在任何支持JRE(Java Run Environment Java,運(yùn)行環(huán)境)的平臺(tái)上。但由于JRMP是專為Java對(duì)象制定的,因此,RMI對(duì)于用非Java語言開發(fā)的應(yīng)用系統(tǒng)的支持不足。不能與用非Java語言書寫的對(duì)象進(jìn)行通信。本文擬從程序的角度舉例介紹怎樣利用RMI實(shí)現(xiàn)Java分布式應(yīng)用。 

 
一、RMI系統(tǒng)運(yùn)行機(jī)理

RMI應(yīng)用程序通常包括兩個(gè)獨(dú)立的程序:服務(wù)器程序和客戶機(jī)程序。典型的服務(wù)器應(yīng)用程序?qū)?chuàng)建多個(gè)遠(yuǎn)程對(duì)象,使這些遠(yuǎn)程對(duì)象能夠被引用,然后等待客戶機(jī)調(diào)用這些遠(yuǎn)程對(duì)象的方法。而典型的客戶機(jī)程序則從服務(wù)器中得到一個(gè)或多個(gè)遠(yuǎn)程對(duì)象的引用,然后調(diào)用遠(yuǎn)程對(duì)象的方法。RMI為服務(wù)器和客戶機(jī)進(jìn)行通信和信息傳遞提供了一種機(jī)制。

在與遠(yuǎn)程對(duì)象的通信過程中,RMI使用標(biāo)準(zhǔn)機(jī)制:stub和skeleton。遠(yuǎn)程對(duì)象的stub擔(dān)當(dāng)遠(yuǎn)程對(duì)象的客戶本地代表或代理人角色。調(diào)用程序?qū)⒄{(diào)用本地stub的方法,而本地stub將負(fù)責(zé)執(zhí)行對(duì)遠(yuǎn)程對(duì)象的方法調(diào)用。在RMI中,遠(yuǎn)程對(duì)象的stub與該遠(yuǎn)程對(duì)象所實(shí)現(xiàn)的遠(yuǎn)程接口集相同。調(diào)用stub的方法時(shí)將執(zhí)行下列操作:(1) 初始化與包含遠(yuǎn)程對(duì)象的遠(yuǎn)程虛擬機(jī)的連接;(2) 對(duì)遠(yuǎn)程虛擬機(jī)的參數(shù)進(jìn)行編組(寫入并傳輸);(3) 等待方法調(diào)用結(jié)果;(4) 解編(讀取)返回值或返回的異常;(5) 將值返回給調(diào)用程序。為了向調(diào)用程序展示比較簡(jiǎn)單的調(diào)用機(jī)制,stub將參數(shù)的序列化和網(wǎng)絡(luò)級(jí)通信等細(xì)節(jié)隱藏了起來。在遠(yuǎn)程虛擬機(jī)中,每個(gè)遠(yuǎn)程對(duì)象都可以有相應(yīng)的skeleton(在JDK1.2環(huán)境中無需使用skeleton)。Skeleton負(fù)責(zé)將調(diào)用分配給實(shí)際的遠(yuǎn)程對(duì)象實(shí)現(xiàn)。它在接收方法調(diào)用時(shí)執(zhí)行下列操作:(1) 解編(讀?。┻h(yuǎn)程方法的參數(shù);(2) 調(diào)用實(shí)際遠(yuǎn)程對(duì)象實(shí)現(xiàn)上的方法;(3) 將結(jié)果(返回值或異常)編組(寫入并傳輸)給調(diào)用程序。stub和skeleton由rmic編譯器生成。

利用RMI編寫分布式對(duì)象應(yīng)用程序需要完成以下工作:(1) 定位遠(yuǎn)程對(duì)象。應(yīng)用程序可使用兩種機(jī)制中的一種得到對(duì)遠(yuǎn)程對(duì)象的引用。它既可用RMI的簡(jiǎn)單命名工具rmiregistry來注冊(cè)它的遠(yuǎn)程對(duì)象,也可以將遠(yuǎn)程對(duì)象引用作為常規(guī)操作的一部分來進(jìn)行傳遞和返回。(2)與遠(yuǎn)程對(duì)象通信。遠(yuǎn)程對(duì)象間通信的細(xì)節(jié)由RMI處理,對(duì)于程序員來說,遠(yuǎn)程通信看起來就像標(biāo)準(zhǔn)的Java方法調(diào)用。(3)給作為參數(shù)或返回值傳遞的對(duì)象加載類字節(jié)碼。因?yàn)镽MI允許調(diào)用程序?qū)⒓僇ava對(duì)象傳給遠(yuǎn)程對(duì)象,所以,RMI將提供必要的機(jī)制,既可以加載對(duì)象的代碼又可以傳輸對(duì)象的數(shù)據(jù)。在RMI分布式應(yīng)用程序運(yùn)行時(shí),服務(wù)器調(diào)用注冊(cè)服務(wù)程序以使名字與遠(yuǎn)程對(duì)象相關(guān)聯(lián)??蛻魴C(jī)在服務(wù)器上的注冊(cè)服務(wù)程序中用遠(yuǎn)程對(duì)象的名字查找該遠(yuǎn)程對(duì)象,然后調(diào)用它的方法。

二、對(duì)象序列化

在RMI分布式應(yīng)用系統(tǒng)中,服務(wù)器與客戶機(jī)之間傳遞的Java對(duì)象必須是可序列化的對(duì)象。不可序列化的對(duì)象不能在對(duì)象流中進(jìn)行傳遞。對(duì)象序列化擴(kuò)展了核心Java輸入/輸出類,同時(shí)也支持對(duì)象。對(duì)象序列化支持把對(duì)象編碼以及將通過它們可訪問到的對(duì)象編碼變成字節(jié)流;同時(shí),它也支持流中對(duì)象圖形的互補(bǔ)重構(gòu)造。序列化用于輕型持久性和借助于套接字或遠(yuǎn)程方法調(diào)用(RMI)進(jìn)行的通信。序列化中現(xiàn)在包括一個(gè) API(Application Programming Interface,應(yīng)用程序接口),允許獨(dú)立于類的域指定對(duì)象的序列化數(shù)據(jù),并允許使用現(xiàn)有協(xié)議將序列化數(shù)據(jù)域?qū)懭肓髦谢驈牧髦凶x取,以確保與缺省讀寫機(jī)制的兼容性。

為編寫應(yīng)用程序,除多數(shù)瞬態(tài)應(yīng)用程序外,都必須具備存儲(chǔ)和檢索 Java對(duì)象的能力。以序列化方式存儲(chǔ)和檢索對(duì)象的關(guān)鍵在于提供重新構(gòu)造該對(duì)象所需的足夠?qū)ο鬆顟B(tài)。存儲(chǔ)到流的對(duì)象可能會(huì)支持 Serializable(可序列化)或 Externalizable(可外部化)接口。對(duì)于Java對(duì)象,序列化形式必須能標(biāo)識(shí)和校驗(yàn)存儲(chǔ)其內(nèi)容的對(duì)象所屬的 Java類,并且將該內(nèi)容還原為新的實(shí)例。對(duì)于可序列化對(duì)象,流將提供足夠的信息將流的域還原為類的兼容版本。對(duì)于可外部化對(duì)象,類將全權(quán)負(fù)責(zé)其內(nèi)容的外部格式。序列化 Java 對(duì)象的目的是:提供一種簡(jiǎn)單但可擴(kuò)充的機(jī)制,以序列化方式維護(hù) Java對(duì)象的類型及安全屬性;具有支持編組和解編的擴(kuò)展能力以滿足遠(yuǎn)程對(duì)象的需要;具有可擴(kuò)展性以支持 Java 對(duì)象的簡(jiǎn)單持久性;只有在自定義時(shí),才需對(duì)每個(gè)類提供序列化自實(shí)現(xiàn);允許對(duì)象定義其外部格式。

三、分布式應(yīng)用的實(shí)現(xiàn)和運(yùn)行步驟

編寫Java RMI分布式應(yīng)用程序的步驟主要包括以下幾步:

(1) 將遠(yuǎn)程類的功能定義為Java接口。在Java中,遠(yuǎn)程對(duì)象是實(shí)現(xiàn)遠(yuǎn)程接口的類的實(shí)例。在遠(yuǎn)程接口中聲明每個(gè)要遠(yuǎn)程調(diào)用的方法。遠(yuǎn)程接口具有如下特點(diǎn):1) 遠(yuǎn)程接口必須聲明為public。如果不這樣,則除非客戶端與遠(yuǎn)程接口在同一個(gè)包內(nèi),否則當(dāng)試圖裝入實(shí)現(xiàn)該遠(yuǎn)程接口的遠(yuǎn)程對(duì)象時(shí)會(huì)得到錯(cuò)誤結(jié)果。2) 遠(yuǎn)程對(duì)象擴(kuò)展java.rmi.Remote接口。3) 除了所有應(yīng)用程序特定的例外之外,每個(gè)方法還必須拋出java.rmi.RemoteException例外。4) 任何作為參數(shù)或返回值傳送的遠(yuǎn)程對(duì)象的數(shù)據(jù)類型必須聲明為遠(yuǎn)程接口類型,而不是實(shí)現(xiàn)類。

(2) 編寫和實(shí)現(xiàn)服務(wù)器類。該類是實(shí)現(xiàn)(1)中定義的遠(yuǎn)程接口。所以在該類中至少要聲明實(shí)現(xiàn)一個(gè)遠(yuǎn)程接口,并且必須具有構(gòu)造方法。在該類中還要實(shí)現(xiàn)遠(yuǎn)程接口中所聲明的各個(gè)遠(yuǎn)程方法。

(3) 編寫使用遠(yuǎn)程服務(wù)的客戶機(jī)程序。在該類中使用java.rmi.Naming中的lookup()方法獲得對(duì)遠(yuǎn)程對(duì)象的引用,依據(jù)需要調(diào)用該引用的遠(yuǎn)程方法,其調(diào)用方式和對(duì)本地對(duì)象方法的調(diào)用相同。

實(shí)現(xiàn)了服務(wù)器和客戶機(jī)的程序后,就是編譯和運(yùn)行該RMI系統(tǒng)。其步驟有:
(1) 使用javac編譯遠(yuǎn)程接口類,遠(yuǎn)程接口實(shí)現(xiàn)類和客戶機(jī)程序。
(2) 使用rmic編譯器生成實(shí)現(xiàn)類的stub和skeleton。
(3) 啟動(dòng)RMI注冊(cè)服務(wù)程序rmiregistry。
(4) 啟動(dòng)服務(wù)器端程序。
(5) 啟動(dòng)客戶機(jī)程序。

Java與.NET都提供了遠(yuǎn)程處理功能,但不完全相同.Java遠(yuǎn)程處理是通過一個(gè)“共享接口”實(shí)現(xiàn)的,而.NET可以通過一個(gè)“共享命令集”實(shí)現(xiàn)。下面就這兩種方式來具體說明。
  
   Java 遠(yuǎn)程處理
   Java遠(yuǎn)程方法調(diào)用(RMI)提供了Java程序語言的遠(yuǎn)程通訊功能,這種特性使客戶機(jī)上運(yùn)行的程序可以調(diào)用遠(yuǎn)程服務(wù)器上的對(duì)象,使Java編程人員能夠在網(wǎng)絡(luò)環(huán)境中分布操作。
   創(chuàng)建一個(gè)簡(jiǎn)單的Java分布式遠(yuǎn)程方法調(diào)用程序可以按以下幾個(gè)步驟操作,
  
   一、定義遠(yuǎn)程接口:
   在 Java 中,遠(yuǎn)程對(duì)象是實(shí)現(xiàn)遠(yuǎn)程接口的類的實(shí)例, 遠(yuǎn)程接口聲明每個(gè)要遠(yuǎn)程調(diào)用的方法。在需要?jiǎng)?chuàng)建一個(gè)遠(yuǎn)程對(duì)象的時(shí)候,我們通過傳遞一個(gè)接口來隱藏基層的實(shí)施細(xì)節(jié),客戶通過接口句柄發(fā)送消息即可。
   遠(yuǎn)程接口具有如下特點(diǎn):
   1) 遠(yuǎn)程接口必須為public屬性。如果不這樣,除非客戶端與遠(yuǎn)程接口在同一個(gè)包內(nèi),否則 當(dāng)試圖裝入實(shí)現(xiàn)該遠(yuǎn)程接口的遠(yuǎn)程對(duì)象時(shí),調(diào)用會(huì)得到錯(cuò)誤結(jié)果。
   2) 遠(yuǎn)程接口必須擴(kuò)展接口java.rmi.Remote。
   3) 除與應(yīng)用程序本身特定的例外之外,遠(yuǎn)程接口中的每個(gè)方法都必須在自己的throws從句中 聲明java.rmi.RemoteException。(或 RemoteException 的父類)。
   4) 作為參數(shù)或返回值傳遞的一個(gè)遠(yuǎn)程對(duì)象(不管是直接,還是本地對(duì)象中嵌入)必須聲明為遠(yuǎn) 程接口,而不應(yīng)聲明為實(shí)施類。
   下面是遠(yuǎn)程接口的接口RmiSample的定義

java 代碼
  1. package com.robin.demo.rmi.interf;   
  2.   
  3. import java.rmi.Remote;   
  4. import java.rmi.RemoteException;   
  5.   
  6. public interface RmiSample extends Remote {   
  7.     public int sum(int a, int b) throws RemoteException;   
  8. }   

 二、實(shí)現(xiàn)遠(yuǎn)程接口:
   遠(yuǎn)程對(duì)象實(shí)現(xiàn)類必須擴(kuò)展遠(yuǎn)程對(duì)象java.rmi.UnicastRemoteObject類,并實(shí)現(xiàn)所定義的遠(yuǎn)程接口。遠(yuǎn)程對(duì)象的實(shí)現(xiàn)類中包含實(shí)現(xiàn)每個(gè)遠(yuǎn)程接口所指定的遠(yuǎn)程方法的代碼。這個(gè)類也可以含有附加的方法,但客戶只能使用遠(yuǎn)程接口中的方法。因?yàn)榭蛻羰侵赶蚪涌诘囊粋€(gè)句柄,而不是它的哪個(gè)類。必須為遠(yuǎn)程對(duì)象定義構(gòu)造函數(shù),即使只準(zhǔn)備定義一個(gè)默認(rèn)構(gòu)造函數(shù),用它調(diào)用基礎(chǔ)類構(gòu)造函數(shù)。因?yàn)榛A(chǔ)類構(gòu)造函數(shù)可能會(huì)拋出 java.rmi.RemoteException,所以即使別無它用必須拋出java.rmi.RemoteException例外。
   以下是遠(yuǎn)程對(duì)象實(shí)現(xiàn)類的聲明:

java 代碼
  1. package com.robin.demo.rmi.impl;   
  2.   
  3. import java.rmi.RemoteException;   
  4. import java.rmi.server.UnicastRemoteObject;   
  5.   
  6. import com.robin.demo.rmi.interf.RmiSample;   
  7.   
  8.   
  9. public class RmiSampleImpl extends UnicastRemoteObject implements RmiSample {   
  10.     /**  
  11.      *   
  12.      */  
  13.     private static final long serialVersionUID = 2742977636753958461L;   
  14.   
  15.     public RmiSampleImpl() throws RemoteException {   
  16.         super();   
  17.     }   
  18.   
  19.     public int sum(int a, int b) throws RemoteException {   
  20.         return a + b;   
  21.     }   
  22.   
  23. }   


  
   三、編寫服務(wù)器類:
   包含 main 方法的類可以是實(shí)現(xiàn)類自身,也可以完全是另一個(gè)類。下面通過RmiSampleServer 來創(chuàng)建一個(gè)遠(yuǎn)程對(duì)象的實(shí)例,并通過java.rmi.registry.LocateRegistry類的createRegistry 方法從指定端口號(hào)啟動(dòng)注冊(cè)服務(wù)程序,也可以通過執(zhí)行 rmiregistry 命令啟動(dòng)注冊(cè)服務(wù)程序,注冊(cè)服務(wù)程序的缺省運(yùn)行端口為 1099。必須將遠(yuǎn)程對(duì)象名字綁定到對(duì)遠(yuǎn)程對(duì)象的引用上: Naming.rebind("http://localhost:8808/SAMPLE-SERVER" , Server);
   以下是服務(wù)器類的聲明:

java 代碼
  1. package com.robin.demo.rmi.server;   
  2.   
  3. import java.net.MalformedURLException;   
  4. import java.rmi.Naming;   
  5. import java.rmi.RemoteException;   
  6. import java.rmi.registry.LocateRegistry;   
  7.   
  8. import com.robin.demo.rmi.impl.RmiSampleImpl;   
  9.   
  10.   
  11. public class RmiSampleServer {   
  12.   
  13.     /**  
  14.      * @param args  
  15.      */  
  16.     public static void main(String[] args) {   
  17.         try{   
  18.             LocateRegistry.createRegistry(8808);   
  19.             RmiSampleImpl server= new RmiSampleImpl();   
  20.             Naming.rebind("http://localhost:8808/SAMPLE-SERVER" , server);   
  21.         }catch (MalformedURLException me){   
  22.             System.out.println("Malformed URL: " + me.toString());   
  23.         }catch(RemoteException re){   
  24.             System.out.println("Remote Exception: "+re.toString());   
  25.         }   
  26.     }   
  27.   
  28. }   


  
   四、編寫使用遠(yuǎn)程服務(wù)的客戶機(jī)類:
   客戶機(jī)類的主要功能有兩個(gè),一是通過Naming.lookup方法來構(gòu)造注冊(cè)服務(wù)程序 stub 程序?qū)嵗?,二是調(diào)用服務(wù)器遠(yuǎn)程對(duì)象上的遠(yuǎn)程方法。
   以下是服務(wù)器類的聲明:

java 代碼
  1. package com.robin.demo.rmi.client;   
  2.   
  3. import java.rmi.Naming;   
  4. import java.rmi.RemoteException;   
  5.   
  6. import com.robin.demo.rmi.interf.RmiSample;   
  7.   
  8.   
  9. public class RmiSampleClient {   
  10.   
  11.     /**  
  12.      * @param args  
  13.      */  
  14.     public static void main(String[] args) {   
  15.         try {   
  16.             String url = "http://localhost:8808/SAMPLE-SERVER";   
  17.             RmiSample RmiObject = (RmiSample) Naming.lookup(url);   
  18.             System.out.println(" 1 + 2 = " + RmiObject.sum(1, 2));   
  19.         } catch (RemoteException rex) {   
  20.             System.out.println("Error in lookup: " + rex.toString());   
  21.         } catch (java.net.MalformedURLException me) {   
  22.             System.out.println("Malformed URL: " + me.toString());   
  23.         } catch (java.rmi.NotBoundException ne) {   
  24.             System.out.println("NotBound: " + ne.toString());   
  25.         }   
  26.   
  27.     }   
  28.   
  29. }   

   五、編譯代碼:
   要編譯 Java 源文件,請(qǐng)運(yùn)行 javac 命令:
   javac RmiSample.java RmiSampleImpl.java RmiSampleServer.java RmiSampleClient.java
  
   六、為遠(yuǎn)程對(duì)象實(shí)現(xiàn)創(chuàng)建根和干:
   要?jiǎng)?chuàng)建存根程序和骨架文件,應(yīng)以包含遠(yuǎn)程對(duì)象實(shí)現(xiàn)的已編譯類包全名運(yùn)行 rmic 編譯器。
   存根(Stub)是遠(yuǎn)程對(duì)象在客戶端的代理,它將RMI調(diào)用傳遞給服務(wù)器端的骨架(Skeleton),后者負(fù)責(zé)將該調(diào)用傳遞給實(shí)際的遠(yuǎn)程方法輸入如下:
   D:\RMI>rmic -d D:\RMI RmiSampleImpl 執(zhí)行這個(gè)命令, 若rmic成功運(yùn)行,RMI目錄下就會(huì)多出兩個(gè)新類: RmiSampleImpl_Stub.class RmiSampleImpl_Skel.class 它們分別對(duì)應(yīng)的是存根(stub)和骨架(skeleton).
  
   七、運(yùn)行代碼:
   運(yùn)行服務(wù)端程序:在Windows下,輸入下列命令,在后臺(tái)啟動(dòng)RmiSampleServer程序:
   D:\RMI>java RmiSampleServer
   運(yùn)行客戶端程序:
   D:\RMI>java RmiSampleClient
   客戶端輸出: 1 + 2 = 3 
 
修改上面內(nèi)容:(因?yàn)樯厦娣?wù)端程序和客戶端程序在同一臺(tái)電腦上)
服務(wù)器端程序不變
客戶端修改成  String url = "http://服務(wù)端IP:8808/SAMPLE-SERVER";   
另外特別說明:經(jīng)測(cè)試驗(yàn)證了:客戶端的接口(包括包名)要和服務(wù)端接口和包名相同才能通過
 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    成人精品视频在线观看不卡| 日韩特级黄片免费观看| 欧美日韩国产一级91| 激情综合五月开心久久| 日韩国产精品激情一区| 在线亚洲成人中文字幕高清 | 久久婷婷综合色拍亚洲| 四季精品人妻av一区二区三区| 欧美高潮喷吹一区二区| 91香蕉视频精品在线看| 日本精品最新字幕视频播放| 国产肥女老熟女激情视频一区| 老司机精品视频在线免费看| 欧美性高清一区二区三区视频 | 亚洲三级视频在线观看免费| 日韩精品免费一区二区三区| 伊人欧美一区二区三区| 男女激情视频在线免费观看| 91久久精品在这里色伊人| 国产精品免费精品一区二区| 三级理论午夜福利在线看| 国产视频福利一区二区| 高清国产日韩欧美熟女| 沐浴偷拍一区二区视频| 日本免费一级黄色录像| 在线一区二区免费的视频| 大尺度激情福利视频在线观看 | 国产午夜精品美女露脸视频| 亚洲高清一区二区高清| 日韩精品视频免费观看| 高清国产日韩欧美熟女| 久久99这里只精品热在线| 日韩中文字幕免费在线视频| 中日韩美女黄色一级片| 亚洲天堂一区在线播放| 日本黄色高清视频久久| 日本人妻精品有码字幕| 亚洲伦片免费偷拍一区| 欧美午夜视频免费观看| 成人精品视频在线观看不卡| 国产目拍亚洲精品区一区|