?? 探索 corba 技術(shù)的應(yīng)用領(lǐng)域.htm
字號:
<BODY bgColor=#ffffff text=#000000>
<table>
<TBODY>
<TR>
<TD height=21>
<DIV align=center><B><FONT size=3>探索 CORBA 技術(shù)的應(yīng)用領(lǐng)域 <BR><FONT
size=2> </FONT></FONT></FONT>
<HR align=center color=#cccccc noShade SIZE=1>
</DIV></TD></TR>
<TR>
<TD class=line><FONT
color=#333300>6 月份,我們談過您為什么要使用 CORBA 和 Java 技術(shù)。本月,我要通過一個可用的簡單示例,讓您開始探索 CORBA 技術(shù)的許多領(lǐng)域。不過,別忘了我們的目標(biāo)是,創(chuàng)建這樣一種分布式應(yīng)用程序:使駐留在一臺計算機(jī)上的客戶機(jī)能向運(yùn)行于另一臺計算機(jī)上的服務(wù)發(fā)出請求。我們不想為諸如硬件或操作系統(tǒng)軟件等細(xì)節(jié)問題操心,而只是想讓這種服務(wù)能響應(yīng)客戶機(jī)的請求。<BR><BR> IDL 接口 <BR><BR> 全部 CORBA 結(jié)構(gòu)是從一個接口開始的,理解接口的最佳方法就是想像我的汽車,對,我的汽車。雖然您不熟悉它,但如果我對您說:“開上我的車,帶些三明治回來當(dāng)午餐”,恐怕您就不會懷疑自己能不能駕駛我的汽車。您可能想知道它停在哪里,以及開它是否安全,但是您會確信開我的車與開您的車差別不大。這是因?yàn)椋诟鞣N汽車當(dāng)中,人與汽車之間的接口已高度標(biāo)準(zhǔn)化了。我的轎車和您的跑車之間可能會有一些差異,但汽車的油門踏板、剎車和方向盤的安裝都是標(biāo)準(zhǔn)的,您一定能輕松快速上路。<BR><BR> 因?yàn)?amp;nbsp;CORBA 與語言無關(guān),所以它依靠一種接口定義語言 (IDL),來表達(dá)客戶機(jī)如何向?qū)崿F(xiàn)接口的服務(wù)發(fā)出請求。我們的接口就是一個方法:add()。這個方法將取兩個數(shù)(兩個 IDL 的 long 型數(shù))并返回這兩個數(shù)之和。下面是我們的接口計算程序:<BR><BR>清單 1. calcsimpl.idl <BR>module corbasem {<BR> module gen {<BR> module calcsimpl {<BR> interface calculator {<BR> long add(in long x, in long y);<BR> };<BR> };<BR> };<BR>};<BR> <BR><BR> 這個接口中的 IDL 關(guān)鍵字有:module、interface、long 和 in。IDL 使用關(guān)鍵字 module 來創(chuàng)建名稱空間,并且此關(guān)鍵字準(zhǔn)確地映射為 Java 關(guān)鍵字 package。運(yùn)行 IDL-to-Java 編譯器時,生成的 Java 文件將會存到名為 calcsimpl 的子目錄中。IDL 關(guān)鍵字 interface 完美地映射為 Java 接口,并代表一種抽象類型,因?yàn)閮烧叨贾欢x您與對象通訊的方式,而不涉及對象的實(shí)現(xiàn)。IDL 關(guān)鍵字 long 是一種基本的整數(shù)類型,它至少映射為一個 4 字節(jié)的類型,這種類型在 Java 代碼中就是 int。<BR><BR> 想一想執(zhí)行遠(yuǎn)程方法調(diào)用的機(jī)制,您就會發(fā)現(xiàn)定義參數(shù)傳遞的方向(客戶機(jī)到服務(wù)器、服務(wù)器到客戶機(jī)或者雙向傳遞)是多么的有意義。在 IDL 操作中,這些方向用 in、out 和 inout 關(guān)鍵字來聲明,每個參數(shù)都必須聲明方向,以便使對象請求代理程序 (ORB) 知道該參數(shù)的去向。這會影響到為發(fā)送而進(jìn)行的參數(shù)打包、參數(shù)解包以及內(nèi)存管理。ORB 對參數(shù)了解得越多,它的效率就越高。關(guān)鍵字 in 表明 long x 和 long y 是從客戶機(jī)傳遞到服務(wù)器。<BR><BR>圖 1. 參與 CORBA 請求的各個部分<BR><BR><IMG
src="1418520011012232jt.gif"></IMG> <BR><BR>IDL 編譯器 需要 IDL 編譯器嗎? <BR><BR> 您可能已經(jīng)有了 ORB 供應(yīng)商和 IDL-to-Java 編譯器。但如果還沒有,您從哪里獲取呢?這里有好多,而且有些還可以免費(fèi)下載。我推薦 Object Oriented Concepts, Inc. 的 Orbacus ORB。如果不將其用于商業(yè)目的,它還可以免費(fèi)下載,而且完全符合 CORBA 2.3 規(guī)范。另外一個可試用 60 天的編譯器是 Inprise 的 Visibroker,也完全符合 CORBA 2.3 規(guī)范并且可下載。如想獲得這兩種產(chǎn)品,請參閱參考資料。<BR><BR> 接口定義以后,必須在 ORB 供應(yīng)商提供的 IDL-to-Java 編譯器上運(yùn)行。IDL 編譯器是一種精巧的實(shí)用程序,它生成 IDL 的 stub 和 skeleton 以及其它支持文件。生成的這些源文件,大部分將增強(qiáng) CORBA 標(biāo)準(zhǔn)中定義的特定 IDL 類型的打包功能。編譯器將生成大部分網(wǎng)絡(luò)探測 (plumbing),這在分布式系統(tǒng)中非常重要。在最基本的級別中,IDL-to-Java 編譯器只是一個按 CORBA 2.3 規(guī)范的定義來實(shí)現(xiàn)從 IDL 到 Java 語言映射的程序。手動生成這些代碼既枯燥又費(fèi)時,還容易出錯;IDL-to-Java 編譯器會處理這一切,所以您就不用操心啦;同時,它會用一定的規(guī)則約束您,并強(qiáng)制您執(zhí)行封裝。IDL-to-Java 編譯器將把 CORBA-land 規(guī)則強(qiáng)加給您的系統(tǒng)。<BR><BR> 輸入下面的命令,從 Orbacus 執(zhí)行 IDL-to-Java 編譯器,把所有生成的文件都放在 CLASSPATH 的輸出目錄下。<BR><BR>清單 2. 調(diào)用 IDL-to-Java 編譯器<BR>jidl --output-dir c:\_work\corbasem calculator.idl <BR><BR> 生成了什么呢?這個命令生成了構(gòu)建實(shí)現(xiàn)所需要的全部 Java 源文件。IDL-to-Java 編譯器可確保所定義的接口遵守 CORBA 規(guī)范的規(guī)則。<BR><BR>圖 2. IDL-to-Java 編譯器文件生成<BR><BR><IMG
src="1798820011012232jt2.gif"></IMG><BR>下面是這些文件: <BR><BR> calculator.java - 這個文件叫標(biāo)記接口文件。CORBA 規(guī)范指出這個文件必須擴(kuò)展 IDLEntity,并且與 IDL 接口同名。這個文件提供類型標(biāo)記,從而使這個接口能用于其它接口的方法聲明。 <BR><BR> calculatorOperations.java - 這個文件內(nèi)含 Java 公共接口 -- calculatorOperations。規(guī)范指出,這個文件應(yīng)該與具有 Operations 后綴的 IDL 接口同名,并且這個文件內(nèi)含此接口映射的操作標(biāo)記。上面定義的標(biāo)記接口 (calculator.java) 可擴(kuò)展這個接口。 <BR><BR> calculatorHelper.java - 設(shè)計 helper 類的目的是,讓所需要的許多內(nèi)務(wù)處理功能脫離我們的接口,但又隨時可用到實(shí)現(xiàn)過程中。幫助程序文件含有重要的靜態(tài) narrow 方法,這種方法使 org.omg.CORBA.Object 收縮為一種更具體的類型的對象引用;在這種情況下,將是一個計算程序類型。 <BR><BR> calculatorHolder.java - holder 類是一個專門化類,是為了需要通過引用來傳遞參數(shù)的任意數(shù)據(jù)類型而生成的。這個示例中將不使用 holder 類,但我們將會在以后的欄目中經(jīng)常見到它。 <BR><BR> calculatorPOA.java - skeleton 類為 CORBA 功能提供了請求-響應(yīng)探測的一大部分。生成 calculatorPOA.java,是因?yàn)槿笔》绞较碌膶?shí)現(xiàn)是基于繼承的,如果我們選擇基于委托的實(shí)現(xiàn)方式,輸出就會不一樣。這些主題將在以后的欄目中詳細(xì)介紹。 <BR><BR> _calculatorStub.java - 顧名思義,這是一個 stub 類。您的客戶機(jī)將需要這個類來進(jìn)行工作。<BR><BR><BR>服務(wù)器 <BR><BR> 現(xiàn)在生成的文件必須在服務(wù)器上開始工作,用這個服務(wù)器實(shí)現(xiàn)我們的接口。所幸的是,大部分探測是適合我們的要求的,但別高興得太早 -- 還有許多工作要做;就是說,所有這些文件都必須用在正確的地方。<BR><BR> 讓我們從 add() 方法的實(shí)現(xiàn)開始。(您可以下載完整的 SimpleCalcSvr.java 文件。)<BR><BR>清單 3. SimpleCalcSvr.java -- add() 方法 <BR>SimpleCalcServant extends calculatorPOA {<BR> public int add(int x, int y) {<BR> return x + y;<BR> }<BR>}<BR> <BR><BR> 請注意,我們的實(shí)現(xiàn)類擴(kuò)展了已生成的類 calculatorPOA。從客戶機(jī)發(fā)來一個請求時,該請求通過 ORB 進(jìn)入 skeleton,skeleton 最終將調(diào)用 SimpleCalcServant,來完成請求并啟動響應(yīng)。我們的接口很簡單,所以我們的實(shí)現(xiàn)也很簡單。<BR><BR> 服務(wù)器其余部分的實(shí)現(xiàn),涉及如何圍繞這個接口實(shí)現(xiàn)來設(shè)置 CORBA 體系結(jié)構(gòu),由于可移植性和靈活性方面的原因,許多這些調(diào)用要按 CORBA 規(guī)范執(zhí)行。<BR><BR> 我們需要完成的第一項任務(wù)是,詳細(xì)說明要使用哪一個 ORB,然后予以初始化。下面的代碼(文件 SimpleCalcSvr.java 的第 18 行到第 29 行)處理此任務(wù):<BR><BR>清單 4. SimpleCalcSvr.java -- 初始化 ORB <BR>java.util.Properties props = System.getProperties();<BR>props.put("org.omg.CORBA.ORBClass",<BR>"com.ooc.CORBA.ORG");<BR>props.put("org.omg.CORBA.ORBSingletonClass",<BR>"com.ooc.CORBA.ORBSingleton");<BR><BR>org.omg.CORBA.ORB orb = null;<BR>// 初始化 ORB<BR>orb = org.omg.CORBA.ORB.init(args, props); <BR><BR> <BR><BR> 初始化 ORB 時,需要準(zhǔn)確地告訴它哪一個類將用作 ORBClass,哪一個類將用作 ORBSingleton 類。我們的實(shí)現(xiàn)將不考慮這些,但所有相關(guān)的探測則都將考慮這些。正如我前面所說的,這種情況下,我使用的是 Object Oriented Concepts, Inc. 的 Orbacus ORB,而 OOC 類在那兩個 props.put() 調(diào)用中已給出。一旦填入了屬性,props 就只作為一個參數(shù)傳遞給 ORB.init() 方法。實(shí)際情況可能不是這樣;如果我們要把這個服務(wù)器移到另一個 ORB,不希望為服務(wù)器重新編碼。所以,在理想情況下,我們寧愿改變一個配置文件,使之指向另一個 ORB 類,然后直接重新啟動。<BR><BR> 現(xiàn)在,ORB 已經(jīng)到位并已初始化,并且實(shí)現(xiàn)也已經(jīng)到位,只是尚未創(chuàng)建,此時,需要為實(shí)現(xiàn)創(chuàng)建一個完善的生存地點(diǎn),而這可不像聽起來那么容易,在一個分布式環(huán)境中,各個實(shí)現(xiàn)要求的環(huán)境可能略有不同。可以賦予實(shí)現(xiàn)許多特征。實(shí)現(xiàn)既可以是單線程的,也可以是多線程的;既可以是具有高度可伸縮性的對象池,也可以是單元素。這許多不同的服務(wù)器特征已產(chǎn)生了可移植對象適配器 (POA)。POA 使我們可以創(chuàng)建完善的環(huán)境,供我們的實(shí)現(xiàn)在其中駐留。所有符合 2.3 規(guī)范的 ORB 都會有一個根 POA,所有其它 POA 都是從根 POA 創(chuàng)建的。在這個簡單示例中,我已將實(shí)現(xiàn)專用的代碼分解為它自己的方法 runcalc()。<BR><BR> 為實(shí)現(xiàn)創(chuàng)建一個環(huán)境將是我們的第一項任務(wù),所以必須設(shè)置一個 POA。本來,CORBA 服務(wù)器使用基本對象適配器 (BOA),但是每個供應(yīng)商的 BOA 都不一樣,在最新版本的 CORBA 規(guī)范中,POA 已完全取代了 BOA。<BR><BR> 清單 5. SimpleCalcSvr.java -- 設(shè)置 POA <BR>// 從始終存在的 rootPOA<BR>// 設(shè)置可移植對象適配器<BR>org.omg.PortableServer.POA rootPOA = <BR> org.omg.PortableServer.POAHelper.narrow(<BR> orb.resolve_initial_references("RootPOA"));<BR><BR>org.omg.PortableServer.POAManager manager =<BR> rootPOA.the_POAManager();<BR> <BR><BR> 從標(biāo)題和定義可以看出,這是一個簡單的示例。使用根 POA 而不創(chuàng)建新的 POA,將使事情變得簡單。POA 管理器是一種封裝了 POA 處理狀態(tài)的對象,所以,我們使用 POA 管理器,將發(fā)給 servant 的請求排隊。<BR><BR> 還需要實(shí)例化實(shí)現(xiàn):<BR><BR>清單 6. SimpleCalcSvr.java -- 實(shí)例化實(shí)現(xiàn) <BR>// 創(chuàng)建計算程序接口的 servant<BR>SimpleCalcServant calcSvt = new SimpleCalcServant();<BR>calculator calc = calcSvt._this(orb);<BR> <BR><BR> 按照 CORBA 2.3 規(guī)范,所有 skeleton 均提供一個 _this() 方法,該方法使 servant 能得到目標(biāo) CORBA 對象的對象引用,servant 正是用目標(biāo) CORBA 對象來與這些請求相關(guān)聯(lián)的。<BR><BR> 完成實(shí)現(xiàn)的實(shí)例化以后,就必須把機(jī)制放到適當(dāng)?shù)奈恢茫员憧蛻魴C(jī)能夠找到它們。有許多不同的方法和服務(wù)可用來找到滿足接口請求的對象。CORBA Service 定義 Naming Service 和 Trader Services,來專門幫助客戶機(jī)查找對象,以處理請求。也可以通過方法調(diào)用來傳遞對象。<BR><BR> 在這個示例中,我們將使用所有方法中最直截了當(dāng)?shù)囊环N — 將對象引用寫入一個文件,該文件將由客戶機(jī)選取。對于所有的 ORB 來說,創(chuàng)建一個對象引用的字符串表示,或者反過來,創(chuàng)建由字符串到對象的引用,都是必備的功能。<BR><BR>清單 7. SimpleCalcSvr.java -- 編寫對象引用 <BR>// 將對象引用寫入一個文件<BR>PrintWriter refstr = new PrintWriter(<BR>new FileWriter("calcref.ior"));<BR>refstr.println(orb.object_to_string(calc));<BR>refstr.close();<BR><BR> <BR><BR> 最后要做的一件事,就是激活 POA,使客戶機(jī)請求開始排隊,并強(qiáng)制服務(wù)器輸入其事件循環(huán),以接收這些傳入的請求。<BR><BR>清單 8. SimpleCalcSvr.java -- 激活 POA <BR>// 使實(shí)現(xiàn)成為可用<BR>manager.activate();<BR>System.out.println("SimpleCalcSvr is running!");<BR>orb.run();<BR><BR> <BR><BR> 客戶機(jī) <BR><BR> 如果您考慮一下正在發(fā)生的事件的機(jī)制,就會明白客戶機(jī)和服務(wù)器實(shí)際上正是互為映像的。客戶機(jī)將所有的參數(shù)打包以創(chuàng)建一個請求,然后以它自己的方式來發(fā)送這個請求。服務(wù)器只是將請求中的參數(shù)解包,執(zhí)行運(yùn)算,將返回值和輸出參數(shù)打包,然后向客戶機(jī)發(fā)回響應(yīng)。客戶機(jī)則將返回值和輸出參數(shù)解包,然后繼續(xù)處理。這樣,客戶機(jī)打包什么,服務(wù)器就解包什么,反之亦然。<BR><BR> 這意味著您將會看到客戶機(jī)和服務(wù)器具有相似的結(jié)構(gòu)。客戶機(jī)還必須創(chuàng)建并初始化一個 ORB。它可以是我們正在使用的 ORB,也可以是另一個供應(yīng)商提供的 ORB;但是,不能是任意的 ORB,而應(yīng)該是支持 IIOP 的 ORB,IIOP 是由對象管理集團(tuán) (OMG) 定義的、基于 TCP/IP 的互操作性協(xié)議。如果您的 ORB 比較舊,那么請小心,它可能無法與其它 ORB 通話。<BR><BR> 首先,我們以相同的方式創(chuàng)建 ORB,就像創(chuàng)建服務(wù)器一樣。(您可以下載完整的 SimpleCalcClient.java 文件。)<BR><BR>清單 9. SimpleCalcClient.java -- 初始化 ORB <BR>java.util.Properties props = System.getProperties();<BR>props.put("org.omg.CORBA.ORBClass",<BR>"com.ooc.CORBA.ORG");<BR>props.put("org.omg.CORBA.ORBSingletonClass",<BR>"com.ooc.CORBA.ORBSingleton");<BR><BR>org.omg.CORBA.ORB orb = null;<BR>// 初始化 ORB<BR>orb = ORB.init(args, props); <BR> <BR><BR> 看起來眼熟?應(yīng)該是這樣,它看起來與服務(wù)器完全一樣。現(xiàn)在,客戶機(jī)已經(jīng)連接到了一個 ORB 之上,但我們的目標(biāo)是調(diào)用一個服務(wù),而這個服務(wù)是在系統(tǒng)中別的地方提供的,需要找到能響應(yīng)請求的對象。在這個示例中,這意味著要從創(chuàng)建于服務(wù)器上的文件中獲取一個對象引用。為了找到計算程序服務(wù)器,需要取得存儲在這個文件中的對象引用的字符串版本,然后把它轉(zhuǎn)換成對象引用,通過這個對象引用就可以進(jìn)行調(diào)用了。<BR><BR> 清單 10. SimpleCalcClient.java -- 獲取對象引用 <BR>System.out.println("Getting reference from string...");<BR>BufferedReader in = new BufferedReader(<BR>new FileReader("calcref.ior") );<BR>String ior = in.readLine();<BR>in.close();<BR><BR>calculator calc = calculatorHelper.narrow(<BR>orb.string_to_object(ior));<BR> <BR><BR> 請注意,這里使用了由 IDL-to-Java 編譯器生成的 calculatorHelper 類。calcref.ior 文件含有一個對象引用,而不是含有計算程序引用。calculatorHelper 類有一個 narrow 方法,可用來將抽象類型集中到特定的計算程序類型。<BR><BR> 仔細(xì)看一看計算程序 calc,它表示計算機(jī)空間中另外某個地方的一個服務(wù)器。最后必須做的一件事,就是調(diào)用 calc 上的方法 add()。<BR><BR> 清單 11. SimpleCalcClient.java -- 調(diào)用 add()<BR>System.out.println( calc.add(2,3) );<BR> <BR><BR> 結(jié)論 <BR><BR> 已經(jīng)討論了很多內(nèi)容,不過請想一想,都學(xué)到了什么。我們的客戶機(jī)與服務(wù)器是完全隔離的,客戶機(jī)不知道服務(wù)器在什么樣的硬件上運(yùn)行,使用的是什么操作系統(tǒng),它是用什么語言編寫的,它是不是多線程的,還有,它位于何處 — 是在隔壁,還是距離半個地球之遙。它只知道一點(diǎn),即如果它調(diào)用 calc 中的 add(),就會得到可以指望的響應(yīng)。<BR><BR> 提供服務(wù)的情形全都是這樣,電話或電力公司也是如此。當(dāng)您拿起電話的時候,您所期望的是聽到拔號音,然后您的呼叫能暢通連接,您并不在乎電話是通過光纜傳輸?shù)倪€是通過衛(wèi)星轉(zhuǎn)發(fā)的,同樣的情況在信息產(chǎn)業(yè)中也正在成為現(xiàn)實(shí)。多虧有了 OMG 和這個基本結(jié)構(gòu),我們才得以加進(jìn)這個既簡單而又非常有說服力的例子。<BR><BR> 下個月,我們將稍微深入地發(fā)掘一下,看一看發(fā)生在表面現(xiàn)象之下的 IIOP 的神奇力量。<BR><BR><BR> <BR><BR></FONT></TD></TR>
<TR>
<TD height=5>
<HR align=center color=#cccccc noShade SIZE=1>
</TD></TR></TBODY></BODY></HTML>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -