zt http://blog.163.com/try_boy/blog/static/17868656220122941155802/?latestBloghtml
分佈式對象技術主要是在分佈式異構環境下創建應用系統框架和對象構件。在應用系統框架的支撐下,開發者能夠將軟件功能封裝爲更易管理和使用的對象,這些對象能夠跨越不一樣的軟、硬件平臺進行互操做。目前,分佈式互操做標準主要有Microsoft的COM/DCOM標準、Sun公司的Java RMI標準和OMG組織的CORBA標準。
Java RMI簡介
遠程方法調用(RMI,Remote Method Invocation)是jdk1.1中引入的分佈式對象軟件包,它的出現大大簡化了分佈異構環境中Java應用之間的通訊。
要使用RMI,必須構建四個主要的類:遠程對象的本地接口、遠程對象實現、RMI客戶機和RMI服務器。RMI服務器生成遠程對象實現的一個實例,並用一個專有的URL註冊。RMI客戶機在遠程RMI服務器上查找服務對象,並將它轉換成本地接口類型,而後像對待一個本地對象同樣使用它。
下面是一個簡單的RMI實例,RMI客戶機經過RMI服務器提供的方法輸出一個語句。例子雖然很簡單,但掌握了Java RMI調用的基本原理和方法,在實現複雜應用時,咱們須要作的也只是完善遠程對象的實現類而已。
RMI實例分析
1.遠程對象的本地接口聲明(RMIOperate.java)
· 該類僅僅是一個接口聲明,RMI客戶機能夠直接使用它,RMI服務器必須經過一個遠程對象來實現它,並用某個專有的URL註冊它的一個實例。
· 遠程接口擴展
java.rmi.Remote
接口。
· 除了全部應用程序特定的例外以外,每一個方法還必須在 throws 子句中聲明
java.rmi.RemoteException
(或
RemoteException
的父類)。java
Hello.java |
|
2.遠程對象實現類
這個類應實現RMI客戶機調用的遠程服務對象的本地接口,它必須從UnicastRemoteObject繼承,構造函數應拋出RemoteException異常。 安全
HelloImpl.java服務器 |
/* * @author javamxj (CSDN Blog) 建立日期 2004-12-27 */ import java.rmi.*; import javax.rmi.PortableRemoteObject; public class HelloImpl extends PortableRemoteObject implements Hello { /* 構造函數 */ public HelloImpl() throws RemoteException { super(); } /* 實現本地接口中聲明的'sayHello()'方法 */ public String sayHello(String message) throws RemoteException { System.out.println("我在RMI的服務器端,客戶端正在調用'sayHello'方法。 "); System.out.println("Hello " + message); return message; } } |
3.RMI服務器類
該類建立遠程對象實現類HelloImpl的一個實例,而後經過一個專有的URL來註冊它。所謂註冊就是經過Java.rmi.Naming.bind()方法或Java.rmi.Naming.rebind()方法,將HelloImpl實例綁定到指定的URL上。框架
HelloServer.java分佈式 |
/* * @author javamxj (CSDN Blog) 建立日期 2004-12-27 */ import java.rmi.*; public class HelloServer { public static void main(String[] args) { // 在服務器端設置安全機制 /* if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } */ try { System.out.println("開始 RMI Server ..."); /* 建立遠程對象的實現實例 */ HelloImpl hImpl = new HelloImpl(); System.out.println("將實例註冊到專有的URL "); Naming.rebind("HelloService", hImpl); System.out.println("等待RMI客戶端調用..."); System.out.println(""); } catch (Exception e) { System.out.println("錯誤: " + e); } } } |
請注意有關
rebind
方法調用的下列參數: 函數
第一個參數是 URL 格式的
java.lang.String
,表示遠程對象的位置和名字。
須要將
myhost
的值更改成服務器名或 IP 地址。不然,若是在 URL 中省略,則主機缺省值爲當前主機,並且在 URL 中無需指定協議(例如「
HelloServer
」)。
在 URL 中,能夠選擇提供端口號:例如「/
/myhost:1234/HelloServer」。
端口缺省值爲 1099。除非服務器在缺省 1099 端口上建立註冊服務程序,不然須要指定端口號。
第二個參數爲從中調用遠程方法的對象實現引用。
RMI 運行時將用對遠程對象 stub 程序的引用代替由
hImpl
參數指定的實際遠程對象引用。遠程實現對象(如
HelloImpl
實例)將始終不離開建立它們的虛擬機。所以,當客戶機在服務器的遠程對象註冊服務程序中執行查找時,將返回包含該實現的 stub 程序的對象。
4.RMI客戶機類
· RMI客戶使用java.rmi.Naming.lookup()方法,在指定的遠程主機上查找RMI服務對象,若找到就把它轉換成本地接口RMIOperate類型。它與CORBA不一樣之處在於RMI客戶機必須知道提供RMI服務主機的URL,這個URL能夠經過rmi://host/path或rmi://host:port/path來指定,若是省略端口號,就默認使用1099。
· Java.rmi.Naming.lookup()方法可能產生三個異常:Java.rmi.RemoteException、Java.rmi.NotBoundException、java.net. MalformedURLException,三個異常都須要捕獲。spa
HelloClient.java.net |
/* * @author javamxj (CSDN Blog) 建立日期 2004-12-27 */ import java.rmi.*; public class HelloClient { public static void main(String[] args) { // 在服務器端設置安全機制 /* if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } */ /* 默認爲本地主機和默認端口 */ String host = "localhost:1099"; /* 帶輸入參數時,將host設置爲指定主機 */ if (args.length > 0) host = args[0]; try { /* 根據指定的URL定位遠程實現對象 */ /* 「h」是一個標識符,咱們將用它指向實現「Hello」接口的遠程對象 */ Hello h = (Hello) Naming.lookup("rmi://" + host + "/HelloService"); System.out.println("實現「Hello」接口的遠程對象: " + h); System.out.println("我在客戶端,開始調用RMI服務器端的'sayHello'方法"); System.out.println("歡迎, " + h.sayHello("javamxj blog")); } catch (Exception ex) { System.out.println("錯誤 " + ex); } } } |
5. 編譯代碼與運行系統:
在MS-DOS環境下,建立一個D:\RMISample目錄,把上面4個文件複製到這個目錄下,而後在此目錄下新建兩個文件夾:client和server(把它們分別看做是客戶端與服務端)。
(1).編譯全部的源代碼
D:\RMISample> javac *.java
(2).生成客戶端存根和服務器框架
D:\RMISample> rmic HelloImpl
這將生成HelloImpl_Stub.class和HelloImpl_Skel.class。
( 注:若是須要查看這兩個類的源代碼,可使用「 rmic -keep HelloImpl」語句)
(3).把Hello.class、HelloClient.class、HelloImpl_Stub.class複製到client目錄;
把Hello.class、HelloServer.class、HelloImpl_Skel.class、HelloImpl_Stub.class 複製到server目錄。
(4).啓動RMI註冊
D:\RMISample\server>rmiregistry
(注: 我是在命令控制檯下運行這個系統的,必須開啓三個控制檯窗口,一個運行RMIRegistry,一個運行服務器,還有一個運行客戶端。)
(5).運行和調用
● 在服務器上執行HelloServer
D:\RMISample\server>java HelloServer
● 在本地客戶機上運行HelloClient
D:\RMISample\client>java HelloClient
● 在遠程客戶機上運行HelloClient(須指明RMI服務器主機名或IP地址)
java HelloClient 222.222.34.34
運行rmiregistry和server後的結果:orm
再運行Client後的結果:
還有一點要注意,在上面的例子中我註釋了安全管理的代碼,若是把註釋去掉,那麼須要創建一個安全策略文件,好比其文件名爲 policy.txt,內容以下:
grant {
permission java.security.AllPermission "", "";
};
這是一條簡單的安全策略,它容許任何人作任何事,對於你的更加關鍵性的應用,你必須指定更加詳細安全策略。把這個文件複製到Client和Server目錄,而後以下運行:
D:\RMISample\server>java -Djava.security.policy=policy.txt HelloServer
D:\RMISample\client>java -Djava.security.policy=policy.txt HelloClient