企業中的 RMI-IIOP
RMI?和?CORBA?常被視為相互競爭的技術,因為兩者都提供對遠程分布式對象的透明訪問。但這兩種技術實際上是相互補充的,一者的長處正好可以彌補另一者的短處。RMI?和?CORBA?的結合產生了?RMI-IIOP,RMI-IIOP?是企業服務器端?Java?開發的基礎。在本文中,Java?開發者?Damian?Hagge?簡要介紹了?RMI-IIOP,然后為您展示如何構建和運行一個簡單的、基于?Java?的?RMI-IIOP?客戶機/服務器應用程序。請親自看看?RMI?能在?IIOP?上工作得多么好。請單擊本文頂部或底部的?討論,在?討論論壇與作者及其他讀者交流關于本文的心得。?1997?年,IBM?和?Sun?Microsystems?啟動了一項旨在促進?Java?作為企業開發技術的發展的合作計劃。兩家公司特別著力于如何將?Java?用作服務器端語言,生成可以結合進現有體系結構的企業級代碼。所需要的就是一種遠程傳輸技術,它兼有?Java?的?RMI(Remote?Method?Invocation,遠程方法調用)較少的資源占用量和更成熟的?CORBA(Common?Object?Request?Broker?Architecture,公共對象請求代理體系結構)技術的健壯性。出于這一需要,RMI-IIOP?問世了,它幫助將?Java?語言推向了目前服務器端企業開發的主流語言的領先地位。
在本文中,我將簡要介紹?RMI-IIOP,目標是使您能開始在企業開發解決方案中使用這一技術。要解釋?RMI-IIOP?究竟是什么,我認為提供一些關于?CORBA?和?RMI?的信息是重要的,這些信息您在各個技術的典型介紹中可能找不到。如果您對?CORBA?或?RMI?的基礎知識不熟悉,我建議您在往下讀之前先閱讀一些介紹性信息。請參閱?參考資料,那里挑選了一些文章和教程。?
在我具體討論?RMI-IIOP?之前,我們將先看一下?CORBA?和?RMI?用來對請求進行數據編入的機制。CORBA?將是我們的主要示例,因為?RMI-IIOP?數據編入是建立在?CORBA?傳輸協議(IIOP)的基礎上的。我們將回顧一下該傳輸協議和?ORB(object?request?broker,對象請求代理)在網絡上發送請求、定位遠程對象和傳輸對象方面的基本功能。
遠程對象傳輸
對?CORBA?請求進行數據編入是通過使用?IIOP?協議做到的。簡言之,IIOP?將以標準化格式構造的任何?IDL(Interface?Definition?Language,接口定義語言)的元素表示為一系列字節。那就假設有一個?Java?客戶機正在將一個?CORBA?請求分派到?C++?服務器吧。客戶機應用程序以?Java?接口的形式擁有遠程對象的引用,并調用該接口的一個操作。本質上是,接口調用它對該操作的相應實現,這個實現將位于存根(stub)(存根是您將已經用?idlj?從?IDL?生成了的)。?
存根把方法調用分派到?ORB?中,ORB?由兩部分組成:客戶機?ORB?和服務器?ORB。客戶機?ORB?的職責是對請求進行數據編入,放到網絡上,傳往特定位置。服務器?ORB?的職責是偵聽從網絡上傳下來的請求,并將這些請求轉換成語言實現能夠理解的方法調用。要了解對?CORBA?ORB?的角色的更深入討論,請參閱?參考資料部分。?
存根分派了方法調用之后,客戶機?ORB?將請求和所有參數轉換成標準化字節格式,在這種情況中是?IIOP。接著,請求通過導線被發送到服務器?ORB,服務器?ORB?應該正在偵聽傳入請求。服務器端?ORB?將讀進數據的字節并將請求轉換成對?C++?服務器實現有意義的東西。C++?服務器方法將執行它的功能(即調用所請求的方法)并使用相同的機制通過?IIOP?將結果返回給客戶機。
RMI?以類似的方式處理請求,但是它使用?JRMP(Java?Remote?Messaging?Protocol,Java?遠程消息傳遞協議)作為其傳輸協議。當然,RMI?傳輸還涉及?Java?對象的序列化。
?CORBA?和?RMI?的差異
CORBA?運行在?IIOP?協議之上;RMI?使用?JRMP。?
CORBA?是獨立于語言的;RMI?是純粹?Java?到?Java?的。?
RMI?使用?JNDI?定位遠程對象;CORBA?使用?CosNaming。?
RMI?會將對象序列化;CORBA?則不然。?
?遠程對象定位
CORBA?使用?CosNaming?命名服務定位遠程對象。CosNaming?為名稱服務器保存對?CORBA?服務器進程的綁定(或引用)提供了一個框架。當?CORBA?客戶機向名稱服務發送?CosNaming?請求,請求給定名稱的服務器進程時,名稱服務返回該進程的?可互操作對象引用(interoperable?object?reference(IOR))。接著,客戶機使用該?IOR?直接與服務器進程通信。?
IOR?包含關于服務器進程的信息,例如服務器進程的位置。CosNaming?服務的缺點之一是,IOR?對人類而言是難以看懂的?—?至少對我們這些沒有電子大腦的人來說是這樣。相反地,RMI?對用戶則要友好一些。它使用運行在?JNDI?之上的?注冊中心(與命名服務極為相似)來定位遠程對象。RMI?注冊中心使用?Java?Reference?對象(它由若干個?RefAddr?對象組成)來識別和定位遠程對象。這些?Java?對象比?IOR?對用戶更加友好。?
不久前,COBRA?將可互操作命名服務(Interoperable?Naming?Service(INS))結合進了它的對象-定位(object-location)模式。INS?在?CosNaming?上運行,使用人類可以閱讀的?URL?作它的對象位置。INS?不使用命名服務;相反地,它將調用直接發送到指定的?URL。請參閱?參考資料了解關于?INS?的更多信息。?
RMI?對?CORBA
那么,哪一個更好呢:是?CORBA?還是?RMI?答案取決于您想做什么。CORBA?是一個運行在業界標準的第三或第四代協議上的、經過試驗和測試的大體系結構。如果考慮到?CORBA?提供的所有附件(例如:事務處理、安全攔截器、事件通道,還有更多)的話,則?CORBA?看來是企業應用程序的解決方案。CORBA?的最大缺點是它很復雜。要熟練使用?CORBA,開發者通常要經歷陡峭的培訓曲線。
相反地,RMI?相當容易學習。創建一個客戶機/服務器實現,綁定到注冊中心和遠程對象,使用?RMI?調用和/或接收請求都相當簡單。RMI?的資源占用量也比?CORBA?小得多,因為?JRMP?是開銷比?IIOP?小得多的協議。但是,RMI?缺乏?CORBA?的工業級的附件,而且是純基于?Java?的機制。那么,我們真正需要的就是?RMI?的靈活性和易用性以及?CORBA?的企業就緒性,對嗎?那就開始討論?RMI-IIOP?吧。
?為什么是?RMI-IIOP?
RMI-IIOP?兼有?CORBA?的強度和?RMI?的靈活性。?
開發者很容易就可以使用?RMI-IIOP,RMI-IIOP?也易于集成到多數企業基礎架構中。?
?
RMI-IIOP?概覽
RMI-IIOP?讓您僅需極少修改就可以在?IIOP?上運行?RMI?調用。借助于?RMI-IIOP,您可以編寫簡單易懂的?Java?代碼,同時使用?CORBA?提供的豐富的企業功能套件。而且,代碼的靈活性足夠大,可以運行在?RMI?或IIOP?上。這意味著,您的代碼可以在純?Java?環境中運行(當小的資源占用量和靈活性很關鍵時),或者對代碼作少量修改后集成到現有的?CORBA?基礎架構中。?
RMI-IIOP?很強大的功能之一是,它讓您編寫純?Java?客戶機/服務器實現而不喪失?RMI?類序列化的靈活性。RMI-IIOP?通過覆蓋?Java?序列化并在導線上將?Java?類轉換成?IIOP?做到這一點。在另一端,Java?類被作為?IIOP?從導線上讀下來,接著創建這個類的一個新實例(使用反射),類的所有成員的值都完整無缺?—?瞧:這就是?IIOP?上的?Java?序列化!?
為了讓?RMI-IIOP?實現透明的對象定位,ORB?供應商歷史上曾經使用?Java?CosNaming?服務提供者(或用外行人的話說,是?插件)。該插件在?JNDI?API?之下工作,訪問?CORBA?命名服務。盡管我沒有在這里花篇幅來說明原因,但這種命名解決方案并不理想。其結果是,許多供應商?—?尤其是應用服務器供應商?—?為?RMI-IIOP?開發了專門的對象定位機制。?
RMI-IIOP?也支持作為?Java?CosNaming?服務的一個擴展的?INS。因為我相信?INS?將確定對象定位的未來方向,所以我們在本文將討論的代碼示例使用?INS。
注:因為?Sun?尚未完全遵循?OMG?INS?標準,也尚未公開?org.omg.CORBA.ORB?接口的?register_initial_reference?,所以本文提供的源代碼將不能與?Sun?JDK?一起工作。您將需要?IBM?Developer?Kit?for?Java?technology,版本?1.3.1?或更高版本。不過,我已經創建了一個使用命名服務的與?Sun?兼容的示例,您可以從?參考資料部分下載它?
自己動手構建?RMI-IIOP
說得夠多了,讓我們來編寫代碼吧!在以下幾部分中,我們將構建一個簡單的、基于?Java?的客戶機/服務器?RMI-IIOP?應用程序。這個應用程序由三個部分組成:RMI?接口、服務器應用程序和客戶機應用程序。示例以在?IIOP?之上的?Java?序列化為特色,所以您可以看到?Java?類如何被客戶機實例化,如何傳遞到服務器,由服務器更改,然后將所有修改完整地回傳到客戶機。
第?1?部分:定義接口
在?RMI-IIOP?下,我們可以選擇使用?RMI?或?IDL?來定義接口。因為我們想看看?RMI?如何運行在?IIOP?上,所以我們將使用?RMI?定義示例接口。清單?1?是我們的簡單示例的?RMI?接口:
清單?1.?RMIInterface.java
/*
?*?Remote?interface
?*/
public?interface?RMIInterface?extends?java.rmi.Remote?{
????public?String?hello()?throws?java.rmi.RemoteException;
????public?SerClass?alterClass(SerClass?classObject)?
???????throws?java.rmi.RemoteException;
}
?
RMIInterface?定義一個?hello()?方法和一個?alterClass(SerClass)?方法。后一個方法用?SerClass?作參數,?SerClass?是一個實現?Serializable?的?Java?類,?alterClass(SerClass)?方法返回一個類型與其參數的類型相同的類。?SerClass?是一個有幾個成員的簡單的類,每個成員有相應的?getter?方法。這些方法如清單?2?所示:?
清單?2.?SerClass.java
/**
?*??This?class?is?intended?to?be?serialized?over?RMI-IIOP.
?*/
public?class?SerClass?implements?java.io.Serializable?{
????//?members
????private?int?x;
????private?String?myString;
????//?constructor
????public?SerClass(int?x,?String?myString)?
???????throws?java.rmi.RemoteException?{
????????this.x=x;
????????this.myString=myString;
????}?
????
????//?some?accessor?methods
????public?int?getX()?{??return?x;}
????public?void?setX(int?x)?{?this.x=x;?}
????public?String?getString()?{??return?myString;??}
????public?void?setString(String?str)?{?myString=str;?}
}
?
這就是我們簡單的接口的全部。現在我們來研究一下服務器類。
第?2?部分:構建服務器
我們將使用一個既充當?RMIInterface?實現類又包含?main?方法(以啟動我們的服務)的服務器類(?Server.java?)。?Server.java?繼承?javax.rmi.PortableRemoteObject?。這樣,它就包含了將自己作為?Remote?接口綁定到?ORB?和開始偵聽請求所需要的全部功能。清單?3?是該服務器的代碼:?
清單?3.?Server.java
/*
?*?Simple?server
?*/
import?java.util.*;
import?java.rmi.Remote;
import?java.rmi.RemoteException;
import?javax.rmi.PortableRemoteObject;
import?javax.rmi.CORBA.Tie;
import?javax.rmi.CORBA.Util;
import?org.omg.PortableServer.POA;
import?org.omg.PortableServer.*;
import?org.omg.PortableServer.Servant;
import?org.omg.CORBA.ORB;
public?class?Server?extends?PortableRemoteObject?
????implements?RMIInterface?{
????//?must?explicitly?create?default?constructor?
????//?to?throw?RemoteException
????public?Server()?throws?RemoteException?{
????}
????//?implementation?of?RMIInterface?methods
????public?String?hello()?throws?RemoteException?{
????????return?"Hello?there!";
????}
????public?SerClass?alterClass(SerClass?classObject)?
????????throws?RemoteException?{
????????//?change?the?values?of?SerClass?and?return?it.
????//?add?5?to?X
????????classObject.setX(?
???????????classObject.getX()?+?5?);?
????//?alter?the?string
????????classObject.setString(?
???????????classObject.getString()?+?"?:?I've?altered?you"?);?
????????return?classObject;
????}???
????public?static?void?main(String[]?args)?{
????????try?{
????????????//?create?the?ORB?passing?in?the?port?to?listen?on
????????????Properties?props?=?new?Properties();
????????????props.put("com.ibm.CORBA.ListenerPort","8080");
????????????ORB?orb?=?ORB.init(args,?props);
????
????????????//?instantiate?the?Server
????????????//?this?will?automatically?call?exportObject(this)
????????????Server?s?=?new?Server();
????????????
????????????//?now?get?the?Stub?for?our?server?object?-?
?????????//?this?will?be?both
????????????//?a?remote?interface?and?an?org.omg.CORBA.Object
????????????Remote?r=PortableRemoteObject.toStub(s);????????????????
????
????????????//?register?the?process?under?the?name?
?????????//?by?which?it?can?be?found????
????????????((com.ibm.CORBA.iiop.ORB)orb).
????????????register_initial_reference("OurLittleClient",
????????????(org.omg.CORBA.Object)r);
????
????????????System.out.println("Hello?Server?waiting...");
????????????//?it's?that?easy?-?
????????//?we're?registered?and?listening?for?incoming?requests
????????????orb.run();
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????}
????}
}
?
呃,這里發生著什么呢?
服務器應用程序的代碼很長,那我們就分開來講吧。首先,如前面提到過的,?Server?類實現?RMIInterface?并為它的所有方法提供實現。您可以在代碼的前面部分看到?RMIInterface?的?hello()?方法和?alterClass(SerClass)?方法的實現。?hello()?方法只是返回字符串“Hello?there!”。?alterClass(SerClass)?方法用?SerClass?對象作參數,修改成員的值,然后返回新的對象?—?全都通過?RMI-IIOP。?
Server.java?的?main?方法初始化一個?ORB。這個?ORB?將設置為?8080?的?com.ibm.CORBA.ListenerPort?屬性作為參數傳入。這將使得?ORB?在端口?8080?上偵聽傳入請求。請注意,?com.ibm.CORBA.ListenerPort?是一個專有的?IBM?屬性。如果您想在另一供應商的?ORB?上運行這些代碼,那您應該參閱該供應商的文檔,找到適當的屬性。(Sun?使用?com.sun.CORBA.POA.ORBPersistentServerPort?,但它只在您使用?POA(portable?object?adapter,可移植對象適配器)伺服器(servant)時才能夠工作。)?
初始化?ORB?后,main?方法接著對?Server?對象進行實例化。因為這個?server?對象也是一個?PortableRemoteObject?,所以缺省構造函數會自動調用?exportObject(this)?。這個對象現在已經就緒于接收遠程調用。?
接著,我們需要通過調用?ORB.register_initial_reference(String,orb.omg.CORBA.Object)?注冊這個對象。為此,我們需要把我們的?server?對象作為?org.omg.CORBA.Object?的引用。調用?PortableRemoteObject.toStub(s)?實現了這一點,因為所返回的對象都實現了?java.rmi.Remote?和?org.omg.CORBA.Object?。?
然后,返回的?org.omg.CORBA.Object?對象向服務器端?ORB?注冊為“OurLittleClient”。為了確保?INS?請求能夠定位對象,我們使用注冊調用?register_initial_reference?。當?INS?調用進入?ORB?時,ORB?將查找已經以正在被請求的名稱注冊的對象。由于我們將對象注冊為“OurLittleClient”,所以,當一個?INS?調用進入我們的服務器?ORB?要求“OurLittleClient”時,我們將知道客戶機正在查找的是哪個對象。?
最后,我確信您已經注意到我們將?ORB?強制轉型成?com.ibm.CORBA.iiop.ORB?。因為?Sun?尚未公開?org.omg.CORBA.ORB?接口的?register_initial_reference?,所以?IBM?SDK?也不能將它公開。因此,我們必須將我們的?ORB?強制轉型成?IBM?ORB。隨著?Sun?越來越遵循?OMG,JDK?的未來版本(1.4.0?后)將可能不需要這種強制轉型。?
就是這樣!?很簡單吧—?嗯,是有點。我們的服務器現在正在等待傳入客戶機?INS?請求。但客戶機怎么樣呢??
第?3?部分:構建客戶機
客戶機應用程序的代碼如清單?4?所示:
清單?4.?Client.java
/*
?*?Client?application
?*/
import?javax.rmi.PortableRemoteObject;
import?org.omg.CORBA.ORB;
public?class?Client?{
??public?static?void?main(String[]?args)?{
????try?{
??????ORB?orb?=?ORB.init(args,?null);
????
?????????//?here's?the?URL?for?the?local?host
?????????String?INSUrl?=?
????????"corbaloc:iiop:1.2@localhost:8080/OurLittleClient";??
???????
?????????//?get?the?reference?to?the?remote?process
?????????org.omg.CORBA.Object?objRef=orb.string_to_object(INSUrl);
?????????//?narrow?it?into?our?RMIInterface
?????????RMIInterface?ri?=?
??(RMIInterface)PortableRemoteObject.narrow(objRef,?RMIInterface.class);
????????
??????//?call?the?hello?method
?????????System.out.println("received?from?server:?"+ri.hello()+"\n");??
????
??????//?try?RMI?serialization
?????????SerClass?se?=?new?SerClass(5,?"Client?string!?");
?????????//?pass?the?class?to?be?altered?on?the?server
?????????//?of?course?behind?the?scenes?this?class?is?being?
??????//?serialized?over?IIOP
?????????se?=?ri.alterClass(se);
?????????//?now?let's?see?the?result
?????????System.out.println("Serialization?results?:\n"+
????????????"Integer?was?5?now?is?"+se.getX()+"\n"+
????????????"String?was?\"Client?String!?\"?
?????????now?is?\""+se.getString()+"\"");???
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????}
????}
}
?
如何分解客戶機代碼
客戶機代碼比服務器代碼要簡單一些。我們初始化一個?ORB,然后調用?string_to_object(String)?,其中的?string?是我們的?INS?URL。構造?INS?URL?相當簡單:首先,我們指定我們使用?corbaloc?URL(請參閱?參考資料)和?IIOP?協議版本?1.2。接著,我們將主機名(www.whatever.com)和要連接的端口添加進去。最后,我們指定我們要查找的服務的名稱。結果?INS?URL?是?corbaloc:iiop:1.2@localhost:8080/OurLittleClient。?
當我們將這個?URL?傳遞到?ORB.string_to_object(String)?時,ORB?將分派一個請求到所指定的服務器,以請求所請求的服務。假設一切運轉正常,則?ORB?將接收回該服務的一個對象引用(實際上是一個?IOR)。然后,我們將該對象引用強制轉型(narrow)成我們能夠使用的東西,即?RMIInterface?,這樣,我們就為開始調用方法做好了準備。?
在調用了簡單的?hello?方法(它應該不需要任何解釋吧)之后,我們可以開始探討?RMI-IIOP?的序列化功能了。首先,我們創建一個?SerClass?,一個可序列化的?Java?類,并初始化它的成員變量。接著,我們將這個類傳入到我們的方法,方法通過?IIOP?將類寫出到服務器。服務器讀入類并將它重創建為服務器端?Java?對象,修改它的成員值,然后返回它(使用?IIOP)作為方法的返回值。當接收到在遠程方法調用之后重創建的對象時,我們看到它的成員確實已被服務器修改了。就是這么簡單:在?IIOP?上進行?Java?序列化。?
?
第?4?部分:運行示例
請注意,我們這里所創建的示例必須在?IBM?Developer?Kit?for?Java?technology,版本?1.3.1?或更高版本中運行。如果您寧愿使用?Sun?JDK,請下載?特定于?Sun?的源代碼,您應該在?Sun?1.4.0?JDK?或更高版本中運行它。這個源代碼包括一個解釋?IBM?SDK?版本和?Sun?JDK?版本之間的差異的?readme.txt?文件。如果您沒有?IBM?Developer?Kit?for?Java?technology(而您又想要一個),請?現在就下載一個;它們是免費的。?
這里是運行示例的步驟:
下載?源文件。?
輸入?javac?*.java?,javac?所有文件。?
對?server?類運行?rmic?(帶?IIOP?標志):?rmic?-iiop?Server?。?
啟動服務器:在?Windows?中,請輸入?start?java?Server?。?
啟動客戶機:在?Windows?中,請輸入?start?java?Client?。
?
關于?RMI-IIOP?和?EJB?組件的一點注釋
EJB?2.0?規范指出,EJB?組件必須能在?RMI?和?RMI-IIOP?上運行。添加?RMI-IIOP?作為針對?EJB?組件的在線協議,已經給將?J2EE?環境集成到現有的企業基礎設施(多數是?CORBA?相當密集的)帶來了很大幫助。但它也引起了一些問題。
簡單地說,就是將定制構建的組件和?EJB?組件集成起來要求您(開發者)處理管道(plumbing),否則在?EJB?體系結構中它們對您來說將很抽象。到目前為止,還沒有解決這個問題的簡單方案,可能永遠也不會有。隨著諸如?Web?服務這樣的技術的發展,或許會出現解決方案,但目前尚未可知。
?
結束語:此后該做什么
我希望本文已經向您展示了構建和運行?RMI-IIOP?客戶機/服務器應用程序是多么容易。您可以修改一下我們使用的示例,用純?CORBA?替代客戶機或服務器,不過這樣做將除去您應用程序中的?Java?序列化。
如果您想在?CORBA?環境中使用?RMI-IIOP,那么看看?IDL?如何映射成?Java?以及?Java?如何映射成?IDL?是值得的。如果您想在不安全的環境(即不是您自己的?PC)中部署?RMI-IIOP,那么研究一下?CORBA?安全功能(如攔截器和?CORBA?安全模型)以及其它?CORBA?企業功能(如事務處理)是個不錯的主意。CORBA?所有的豐富功能在您運行?RMI-IIOP?時都可以使用。
您可以隨意提出對本文的意見?—?或者直接提給?我,或者提到?討論論壇。我對您的想法很感興趣。?
?
?
參考資料?
您可以參閱本文在?developerWorks?全球站點上的?英文原文.?
請單擊本文頂部或底部的?討論參加本文的?討論論壇。?
下載?本文與?IBM?兼容的源代碼。?
下載?本文與?Sun?兼容的源代碼。?
IIOP?協議是由?對象管理組織(Object?Management?Group(OMG))制定的,這個組織還制定并維護著?CORBA?規范。?
要更多了解?CORBA,請訪問?OMG?的?CORBA?Web?站點。?
要更多了解?RMI,請訪問?RMI?主頁。?
“The?Java?Developer?Connection”提供了一篇?INS?教程,它也對命名服務、CosNaming?服務和?corbaloc?URL?格式做了一般介紹。?
想探索一下您有哪些?Java?技術選擇嗎?請參閱?IBM?Developer?Kit?for?Java?technology的完整清單。?
要更多了解?IBM?Developer?Kit?for?Java?technology,版本?1.3?和?RMI-IIOP,請參閱?javax.rmi.CORBA?類層次結構。?
要獲得對用?RMI?和?CORBA?編程的更進一步介紹,請學習教程“?RMI,?CORBA,?and?Distributed?Objects”(?developerWorks,2000?年?10?月)。?
如果您是用?EJB?組件編程的新手,您可能需要學習教程“?EnterpriseJavaBeans?fundamentals”(?developerWorks,2001?年?3?月)。?
要更多了解?EJB?技術和?CORBA?之間的關系,請參閱?Ken?Nordby?的“?Deployingand?using?Enterprise?JavaBeans?components”—?對?EJB?技術的分為三個部分的介紹的第?3?部分(?developerWorks,2000?年?6?月)。?
RMI-IIOP?的主要設計師在?JavaWorld上的文章“?RMIover?IIOP”講述了他對此項技術的看法(?JavaWorld,1999?年?12?月)。?
要全方位了解?RMI-IIOP,請參閱?theServerSide.com?上的文章“?RMI/IIOP,?nice?idea?but?the?reality?is?turning?out?to?be?different”,它著重講述?RMI-IIOP?不提供的東西(TheServerside.com)。?
關于作者
?Damian?Hagge?在?IBM?的?Hursley?開發實驗室工作。雖然他目前住在英國,但他的出生地比他目前的居住地晚五個時區,四十九緯度線偏上一點(對那些地理不達標的人,就是加拿大)。除了作為開發者在?IBM?Java?ORB?小組工作和寫一些關于不易理解的主題的長篇大論之外,Damian?還是一個知曉各種雞毛蒜皮小事的人;比如說,您知道冰島支持自立的不斷發展的香蕉產業嗎?Damian?還做一些常規運動,例如舉重(power?lifting)(如果您認為舉重是常規運動的話!)。您可以通過?Hagge@uk.ibm.com與他聯系。
posted on 2006-04-04 13:50 劉軍偉 閱讀(487) 評論(0) 編輯 收藏 所屬分類: 其它JAVA技術