| 導購 | 订阅 | 在线投稿
分享
 
 
 

J2EE中用RMI和CORBA進行分布式Java編程

來源:互聯網  2008-06-05 05:35:52  評論

Java遠程方法調用(RMI)機制和公用對象請求代理體系(CORBA)是最重要和使用最廣泛的兩種分布式對象系統。每個系統都有其特點和短處。它們在行 業中被用于從電子交易到保健醫療的各個領域。一個項目如果要從這兩種分布式 機制中選用一個,往往難以抉擇。本文概括地介紹了RMI和CORBA,更重要的是, 它將介紹如何開發一個有用的應用程序,用于從遠程主機下載文件。然後它將:

簡要介紹分布式對象系統

簡要介紹RMI和CORBA

讓你對在RMI和CORBA中開發應用程序所涉及的工作有個初步印象

演示如何使用RMI和CORBA,從遠程主機傳送文件

對RMI和CORBA進行簡單比較

客戶機/服務器模型

客戶機/服務器模型是分布式計算的一種形式,在這種形式中,一個程序(客 戶機)與另一個程序(服務器)通訊以便交換信息。在這種模型中,客戶機和服 務器通常都說同樣的語言--也就是說客戶機和服務器能理解同一個協議--這 樣它們才能通訊。

雖然客戶機/服務器模型的實現方式多種多樣,但典型做法是使用底層套接字。 使用套接字開發客戶機/服務器系統意味著,我們必須設計一個協議,也就是客戶 機和服務器都認識的一組命令集,通過這些命令它們就能通訊了。舉例來說, HTTP協議中提供了一個名爲GET的方法,所有Web服務器都必須實現這個方法,所 有Web客戶機(浏覽器)都必須使用這個方法,才能獲取文檔。

分布式對象模型

基于分布式對象的系統是一組對象的集合,這些對象以一種明確定義封裝的接 口把服務的請求者(客戶機)和服務的提供者(服務器)分隔開。換言之,客戶 機從服務的實現中分離出來,變成數據的呈現和可執行代碼。這就是基于分布式 對象的模型與純粹的客戶機/服務器模型的主要區別之一。

在基于分布式對象的模型中,客戶機向對象發送消息,然後對象解釋該消息以 便決定要執行什麽服務。這項服務,也就是方法,可以選擇是讓對象還是讓代理 來執行。Java遠程方法調用(RMI)和公用對象請求代理體系(CORBA)就是這種 模型的例子。

RMI

RMI是一個分布式對象系統,它使你能夠輕松地開發出分布式Java應用程序。 在RMI中開發分布式應用程序比用套接字開發要簡單,因爲不需要做設計協議這種 很容易出錯的工作。在RMI中,開發者會有一種錯覺,似乎是從本地類文件調用的 本地方法,其實參數傳送給了遠程目標,目標解釋參數後再把結果發回給調用方。

RMI應用程序初步

使用RMI開發分布式應用程序包括以下步驟:

定義一個遠程接口

實現這個遠程接口

開發服務器

開發客戶機

生成存根和基幹,啓動RMI注冊表、服務器和客戶機

下面我們將通過開發一個文件傳輸程序來實踐這些步驟。

範例: 文件傳輸程序

這個應用程序允許客戶機從遠程主機上傳送(即下載)任何類型的文件(純 文本或二進制文件)。第一步是定義一個遠程接口,這個接口規定了服務器所提 供方法的信號,客戶機將調用這些方法。

定義一個遠程接口

用于文件下載應用程序的遠程接口如代碼範例1所示。接口 FileInterface提供了一個方法downloadFile,這個 方法接受String參數(文件名),將文件的數據以字節數組的形式 返回。

代碼範例1 1: FileInterface.java

import java.rmi.Remote;

import java.rmi.RemoteException;

public interface FileInterface extends Remote {

public byte[] downloadFile(String fileName) throws

RemoteException;

}

請注意FileInterface的以下特征:

它必須聲明爲public,這樣客戶機才能加載實現遠程接口 的遠程對象。

它必須擴展爲Remote接口,以滿足使該對象成爲遠程對象的 要求。

這個接口中的每種方法都必須投出一個java.rmi.RemoteException。

實現遠程接口

下一步是實現接口FileInterface。實現的範例見代碼範例2。 請注意,除了實現FileInterface之外,還把FileImpl 類擴展爲UnicastRemoteObject。這表示FileImpl類 將用于創建一個單獨的、不可複制的遠程對象,它使用RMI缺省的基于TCP的傳送 通道進行通訊。

代碼範例2: FileImpl.java

import java.io.*;

import java.rmi.*;

import java.rmi.server.UnicastRemoteObject;

public class FileImpl extends UnicastRemoteObject

implements FileInterface {

private String name;

public FileImpl(String s) throws RemoteException{

super();

name = s;

}

public byte[] downloadFile(String fileName){

try {

File file = new File(fileName);

byte buffer[] = new byte[(int)file.length()];

BufferedInputStream input = new

BufferedInputStream(new FileInputStream(fileName));

input.read(buffer,0,buffer.length);

input.close();

return(buffer);

} catch(Exception e){

System.out.println("FileImpl: "+e.getMessage());

e.printStackTrace();

return(null);

}

}

}

開發服務器

第三個步驟是開發服務器。服務器需要做三件事:

創建RMISecurityManager的一個實例並安裝它

創建遠程對象(在本例中是FileImpl)的一個實例

在RMI注冊表中登記這個創建的對象。實現的範例見代碼範例3。

代碼範例 3: FileServer.java

import java.io.*;

import java.rmi.*;

public class FileServer {

public static void main(String argv[]) {

if(System.getSecurityManager() == null) {

System.setSecurityManager(new RMISecurityManager());

}

try {

FileInterface fi = new FileImpl("FileServer");

Naming.rebind("//127.0.0.1/FileServer", fi);

} catch(Exception e) {

System.out.println("FileServer: "+e.getMessage());

e.printStackTrace();

}

}

}

語句Naming.rebind("//127.0.0.1/FileServer", fi)假定RMI 注冊表在缺省的端口號1099上運行。但是,如果RMI注冊表在其他端口號上運行, 就必須在這一句中指定端口號。例如,如果RMI注冊表在端口4500上運行,那麽 這一句就變成:

Naming.rebind("//127.0.0.1:4500/FileServer", fi)

另外,在這裏要著重指出,我們假定rmi注冊表和服務器是在同一台電腦上運 行。如果不是這樣,只需修改rebind方法中的地址即可。

開發客戶機

下一步是開發客戶機。客戶機可以遠程調用遠程接口 (FileInterface)中指定的任何方法。但是爲了能這麽做,客戶 機首先必須從RMI注冊表中獲得指向該遠程對象的引用。獲得引用之後就可以調 用downloadFile方法了。客戶機的實現請見代碼範例4。在這個實 現中,客戶機從命令行接收兩個參數:

第一個參數是要下載文件的名稱,第二個參數是要下載的文件所在主機的地 址,也就是運行文件服務器的那台電腦的地址。

代碼範例4: FileClient.java

import java.io.*;

import java.rmi.*;

public class FileClient{

public static void main(String argv[]) {

if(argv.length != 2) {

System.out.println("Usage: java FileClient fileName machineName");

System.exit(0);

}

try {

String name = "//" + argv[1] + "/FileServer";

FileInterface fi = (FileInterface) Naming.lookup(name);

byte[] filedata = fi.downloadFile(argv[0]);

File file = new File(argv[0]);

BufferedOutputStream output = new

BufferedOutputStream(new FileOutputStream(file.getName()));

output.write(filedata,0,filedata.length);

output.flush();

output.close();

} catch(Exception e) {

System.err.println("FileServer exception: "+ e.getMessage());

e.printStackTrace();

}

}

}

運行應用程序

爲了運行應用程序,我們需要生成存根和基幹,編譯服務器和客戶機,啓動 RMI注冊表,最後是啓動服務器和客戶機。

爲了生成存根和基幹,請使用rmic編譯器:

prompt> rmic FileImpl

這將生成兩個文件:FileImpl_Stub.class和 FileImpl_Skel.class。存根是一個客戶機代理,基幹是一個服 務器基幹。

下一步是編譯服務器和客戶機。用javac編譯器來做這件事。但是請注意:如 果服務器和客戶機是在兩台不同的機器上開發的,爲了編譯客戶機,需要把接口 (FileInterface)複制一份。

最後,啓動RMI注冊表並運行服務器和客戶機。爲了在缺省的端口號上啓動 RMI注冊表,請在Windows中使用命令rmiregistry或 start rmiregistry。爲了在其他端口號上啓動RMI注冊表,可以 提供該端口號作爲RMI注冊表的一個參數:

prompt> rmiregistry portNumber

運行RMI注冊表之後,就可以啓動服務器FileServer了。但是, 因爲在服務器應用程序中正在使用RMI安全管理員,所以需要一個安全方針來與之 相配。下面是一個安全方針範例:

grant {

permission java.security.AllPermission "", "";

};

注意: 這只是一個方針的例子。它允許任何人做任何事情。對于關鍵 性事務應用程序,你需要指定更嚴格的安全方針。

現在,爲了啓動服務器,需要把除了客戶機類 (FileClient.class)之外的所有類(包括存根和基幹)複制一 份。請使用以下命令啓動服務器,假定安全方針位于文件policy.txt中:

prompt> java -Djava.security.policy=policy.txt FileServer

爲了在另一台機器上啓動客戶機,需要複制遠程接口 (FileInterface.class)和存根 (FileImpl_Stub.class)。請使用以下命令啓動客戶機:

prompt> java FileClient fileName machineName

其中fileNamefileName是要下載的文件,machineName 是該文件所在的機器(運行文件服務器的那台機器)。如果一切順利,那麽客戶 機就存在了,下載完的文件保存在本地的機器上。

Java遠程方法調用(RMI)機制和公用對象請求代理體系(CORBA)是最重要和使用最廣泛的兩種分布式對象系統。每個系統都有其特點和短處。它們在行 業中被用于從電子交易到保健醫療的各個領域。一個項目如果要從這兩種分布式 機制中選用一個,往往難以抉擇。本文概括地介紹了RMI和CORBA,更重要的是, 它將介紹如何開發一個有用的應用程序,用于從遠程主機下載文件。然後它將: 簡要介紹分布式對象系統 簡要介紹RMI和CORBA 讓你對在RMI和CORBA中開發應用程序所涉及的工作有個初步印象 演示如何使用RMI和CORBA,從遠程主機傳送文件 對RMI和CORBA進行簡單比較 客戶機/服務器模型 客戶機/服務器模型是分布式計算的一種形式,在這種形式中,一個程序(客 戶機)與另一個程序(服務器)通訊以便交換信息。在這種模型中,客戶機和服 務器通常都說同樣的語言--也就是說客戶機和服務器能理解同一個協議--這 樣它們才能通訊。 雖然客戶機/服務器模型的實現方式多種多樣,但典型做法是使用底層套接字。 使用套接字開發客戶機/服務器系統意味著,我們必須設計一個協議,也就是客戶 機和服務器都認識的一組命令集,通過這些命令它們就能通訊了。舉例來說, HTTP協議中提供了一個名爲GET的方法,所有Web服務器都必須實現這個方法,所 有Web客戶機(浏覽器)都必須使用這個方法,才能獲取文檔。 分布式對象模型 基于分布式對象的系統是一組對象的集合,這些對象以一種明確定義封裝的接 口把服務的請求者(客戶機)和服務的提供者(服務器)分隔開。換言之,客戶 機從服務的實現中分離出來,變成數據的呈現和可執行代碼。這就是基于分布式 對象的模型與純粹的客戶機/服務器模型的主要區別之一。 在基于分布式對象的模型中,客戶機向對象發送消息,然後對象解釋該消息以 便決定要執行什麽服務。這項服務,也就是方法,可以選擇是讓對象還是讓代理 來執行。Java遠程方法調用(RMI)和公用對象請求代理體系(CORBA)就是這種 模型的例子。 RMI RMI是一個分布式對象系統,它使你能夠輕松地開發出分布式Java應用程序。 在RMI中開發分布式應用程序比用套接字開發要簡單,因爲不需要做設計協議這種 很容易出錯的工作。在RMI中,開發者會有一種錯覺,似乎是從本地類文件調用的 本地方法,其實參數傳送給了遠程目標,目標解釋參數後再把結果發回給調用方。 RMI應用程序初步 使用RMI開發分布式應用程序包括以下步驟: 定義一個遠程接口 實現這個遠程接口 開發服務器 開發客戶機 生成存根和基幹,啓動RMI注冊表、服務器和客戶機 下面我們將通過開發一個文件傳輸程序來實踐這些步驟。 範例: 文件傳輸程序 這個應用程序允許客戶機從遠程主機上傳送(即下載)任何類型的文件(純 文本或二進制文件)。第一步是定義一個遠程接口,這個接口規定了服務器所提 供方法的信號,客戶機將調用這些方法。 定義一個遠程接口 用于文件下載應用程序的遠程接口如代碼範例1所示。接口 FileInterface提供了一個方法downloadFile,這個 方法接受String參數(文件名),將文件的數據以字節數組的形式 返回。 代碼範例1 1: FileInterface.java import java.rmi.Remote; import java.rmi.RemoteException; public interface FileInterface extends Remote { public byte[] downloadFile(String fileName) throws RemoteException; } 請注意FileInterface的以下特征: 它必須聲明爲public,這樣客戶機才能加載實現遠程接口 的遠程對象。 它必須擴展爲Remote接口,以滿足使該對象成爲遠程對象的 要求。 這個接口中的每種方法都必須投出一個java.rmi.RemoteException。 實現遠程接口 下一步是實現接口FileInterface。實現的範例見代碼範例2。 請注意,除了實現FileInterface之外,還把FileImpl 類擴展爲UnicastRemoteObject。這表示FileImpl類 將用于創建一個單獨的、不可複制的遠程對象,它使用RMI缺省的基于TCP的傳送 通道進行通訊。 代碼範例2: FileImpl.java import java.io.*; import java.rmi.*; import java.rmi.server.UnicastRemoteObject; public class FileImpl extends UnicastRemoteObject implements FileInterface { private String name; public FileImpl(String s) throws RemoteException{ super(); name = s; } public byte[] downloadFile(String fileName){ try { File file = new File(fileName); byte buffer[] = new byte[(int)file.length()]; BufferedInputStream input = new BufferedInputStream(new FileInputStream(fileName)); input.read(buffer,0,buffer.length); input.close(); return(buffer); } catch(Exception e){ System.out.println("FileImpl: "+e.getMessage()); e.printStackTrace(); return(null); } } } 開發服務器 第三個步驟是開發服務器。服務器需要做三件事: 創建RMISecurityManager的一個實例並安裝它 創建遠程對象(在本例中是FileImpl)的一個實例 在RMI注冊表中登記這個創建的對象。實現的範例見代碼範例3。 代碼範例 3: FileServer.java import java.io.*; import java.rmi.*; public class FileServer { public static void main(String argv[]) { if(System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } try { FileInterface fi = new FileImpl("FileServer"); Naming.rebind("//127.0.0.1/FileServer", fi); } catch(Exception e) { System.out.println("FileServer: "+e.getMessage()); e.printStackTrace(); } } } 語句Naming.rebind("//127.0.0.1/FileServer", fi)假定RMI 注冊表在缺省的端口號1099上運行。但是,如果RMI注冊表在其他端口號上運行, 就必須在這一句中指定端口號。例如,如果RMI注冊表在端口4500上運行,那麽 這一句就變成: Naming.rebind("//127.0.0.1:4500/FileServer", fi) 另外,在這裏要著重指出,我們假定rmi注冊表和服務器是在同一台電腦上運 行。如果不是這樣,只需修改rebind方法中的地址即可。 開發客戶機 下一步是開發客戶機。客戶機可以遠程調用遠程接口 (FileInterface)中指定的任何方法。但是爲了能這麽做,客戶 機首先必須從RMI注冊表中獲得指向該遠程對象的引用。獲得引用之後就可以調 用downloadFile方法了。客戶機的實現請見代碼範例4。在這個實 現中,客戶機從命令行接收兩個參數: 第一個參數是要下載文件的名稱,第二個參數是要下載的文件所在主機的地 址,也就是運行文件服務器的那台電腦的地址。 代碼範例4: FileClient.java import java.io.*; import java.rmi.*; public class FileClient{ public static void main(String argv[]) { if(argv.length != 2) { System.out.println("Usage: java FileClient fileName machineName"); System.exit(0); } try { String name = "//" + argv[1] + "/FileServer"; FileInterface fi = (FileInterface) Naming.lookup(name); byte[] filedata = fi.downloadFile(argv[0]); File file = new File(argv[0]); BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(file.getName())); output.write(filedata,0,filedata.length); output.flush(); output.close(); } catch(Exception e) { System.err.println("FileServer exception: "+ e.getMessage()); e.printStackTrace(); } } } 運行應用程序 爲了運行應用程序,我們需要生成存根和基幹,編譯服務器和客戶機,啓動 RMI注冊表,最後是啓動服務器和客戶機。 爲了生成存根和基幹,請使用rmic編譯器: prompt> rmic FileImpl 這將生成兩個文件:FileImpl_Stub.class和 FileImpl_Skel.class。存根是一個客戶機代理,基幹是一個服 務器基幹。 下一步是編譯服務器和客戶機。用javac編譯器來做這件事。但是請注意:如 果服務器和客戶機是在兩台不同的機器上開發的,爲了編譯客戶機,需要把接口 (FileInterface)複制一份。 最後,啓動RMI注冊表並運行服務器和客戶機。爲了在缺省的端口號上啓動 RMI注冊表,請在Windows中使用命令rmiregistry或 start rmiregistry。爲了在其他端口號上啓動RMI注冊表,可以 提供該端口號作爲RMI注冊表的一個參數: prompt> rmiregistry portNumber 運行RMI注冊表之後,就可以啓動服務器FileServer了。但是, 因爲在服務器應用程序中正在使用RMI安全管理員,所以需要一個安全方針來與之 相配。下面是一個安全方針範例: grant { permission java.security.AllPermission "", ""; }; 注意: 這只是一個方針的例子。它允許任何人做任何事情。對于關鍵 性事務應用程序,你需要指定更嚴格的安全方針。 現在,爲了啓動服務器,需要把除了客戶機類 (FileClient.class)之外的所有類(包括存根和基幹)複制一 份。請使用以下命令啓動服務器,假定安全方針位于文件policy.txt中: prompt> java -Djava.security.policy=policy.txt FileServer 爲了在另一台機器上啓動客戶機,需要複制遠程接口 (FileInterface.class)和存根 (FileImpl_Stub.class)。請使用以下命令啓動客戶機: prompt> java FileClient fileName machineName 其中fileNamefileName是要下載的文件,machineName 是該文件所在的機器(運行文件服務器的那台機器)。如果一切順利,那麽客戶 機就存在了,下載完的文件保存在本地的機器上。
󰈣󰈤
王朝萬家燈火計劃
期待原創作者加盟
 
 
 
>>返回首頁<<
 
 
 
 
 熱帖排行
 
 
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有