CORBA基本介紹
CORBA(公用對象請求代理體系)是OMG(對象管理組織)于1991年提出的基于對象技術的分布計算應用軟件體系結構。CORBA標準主要分為三個部分:接口定義語言(IDL)、對象請求代理(ORB),以及ORB之間的互操作協議IIOP,核心是對象請求代理。CORBA可以抽象系統平臺、網絡通訊及編程語言的差異。通過在CORBA技術規范中定義多種類型的服務,如名字服務(Naming Service)、事務服務(Transaction Service)、對象生命期服務(LifeCycle Service)、并發控制服務(Concurrency Control Service)、時間服務(Time Service)等功能,為應用軟件開發者提供一個全面、健壯、可擴展的分布對象計算平臺,使面向對象的應用軟件在分布異構環境下方便地實現可重用、易移植和互操作。
與RMI比較
與RMI 不同,CORBA 不屬于Java 平臺本身。OMG(Object Management Group,對象管理組織)發明了CORBA 規范,CORBA 被設計成與平臺和語言無關。因此,CORBA對象可以運行于任何平臺之上,位于網絡的任何位置,還可以用任何語言(包括 Java、C、C++和Smalltalk 等)編寫,只要該語言具有IDL(Interface Definition Language,接口定義語言)的映射。
與RMI 相比,CORBA 是為更大、可伸縮更強的系統準備的,在這些系統中可能有數千個對象;CORBA 的編程和部署比RMI 更復雜,但允程序員開發需要事務、安全性等支持的企業級系統;CORBA 的命名服務也比RMI 命名注冊功能更強大和靈活。
CORBA 的實現稱為ORB(Object Request Broker,對象請求代理)。Java IDL 即是CORBA 的一個實現,它是JDK1.3 或更高版本的核心軟件包之一,定義在org.omg.CORBA及其子包中。在Java IDL 的支持下,開發人員可以使用如下兩種方法將Java 和CORBA 集成在一起:
· ??創建Java 對象并使之可在CORBA ORB 中展開,
· ??創建Java 類并作為和其它ORB 一起展開的CORBA 對象的客戶。這種方法提供了另外一種途徑,通過它Java 可以被用于將你的新的應用和以前遺留的系統相集。
采用Java創建CORBA應用
CORBA對象服務的實現方式分為兩種:對象的命名引用方式和字符串化對象引用方式。不論采用何種高級語言,創建CORBA應用程序的過程大體如下:
● 編寫IDL接口定義文件;
● 將接口定義文件編譯為相應高級語言源代碼,產生服務器框架與客戶端存根;
● 基于服務器框架,編寫服務對象實現程序;
● 基于客戶端存根,編寫客戶對象調用程序;
● 分別編譯客戶對象和服務對象程序;
● 運行服務對象和客戶對象程序;
CORBA對象服務的實現方式分為兩種:對象的命名引用方式和字符串化對象引用方式。不論采用何種高級語言,創建CORBA應用程序的過程大體如下:
● 編寫IDL接口定義文件;
● 將接口定義文件編譯為相應高級語言源代碼,產生服務器框架與客戶端存根;
● 基于服務器框架,編寫服務對象實現程序;
● 基于客戶端存根,編寫客戶對象調用程序;
● 分別編譯客戶對象和服務對象程序;
● 運行服務對象和客戶對象程序;
CORBA實例分析
下面通過一個實例,描述如何通過Java創建CORBA應用程序。
下面通過一個實例,描述如何通過Java創建CORBA應用程序。
1. 接口定義 (Hello.idl)
Hello.idl
|
module HelloApp { interface Hello { string sayHello(in string message); }; }; |
通過Sun提供的將IDL文件編譯成Java源代碼的工具idlj(jdk1.3.0_01以上版本),為接口定義文件生成客戶端存根和服務器框架。具體操作如下:
idlj -oldImplBase -fall Hello.idl
編譯后將在 HelloApp 子目錄中形成以下六個文件:
n
_HelloImplBase.java
該抽象類是一個服務器 skeleton,它可為服務器提供基本的 CORBA 功能。它實現 Hello.java 接口。服務器類 HelloServant 擴展 _HelloImplBase。
該抽象類是一個服務器 skeleton,它可為服務器提供基本的 CORBA 功能。它實現 Hello.java 接口。服務器類 HelloServant 擴展 _HelloImplBase。
n
_HelloStub.java
該類是客戶機 stub,可為客戶機提供 CORBA 功能。它實現 Hello.java 接口。
該類是客戶機 stub,可為客戶機提供 CORBA 功能。它實現 Hello.java 接口。
n Hello.java
該接口含有 IDL 接口的 Java 版本。Hello.java 接口擴展 org.omg.CORBA.Object 并提供標準的 CORBA 對象功能。
n HelloHelper.java
這是一個終態類,可以提供輔助功能,特別是提供將 CORBA 對象引用轉換為適當類型所需的 narrow() 方法。
n HelloHolder.java
這是一個終態類,其中含有 Hello 類型的公有實例成員。它可為“out” 和 “inout” 變量提供操作。CORBA 有這些變量,但不容易映射為 Java 的語義。
n
HelloOperations.java
這是一個接口類,其中含有方法 sayHello()。
要完成該應用程序,只需在文件 HelloServer.java 和 HelloClient.java 中提供服務器和客戶機的實現即可。
2. 接口實現
HelloImpl.java是Hello IDL 接口的實現;每個Hello實例都由一個HelloImpl實例來實現。HelloImpl是_HelloImplBase的子類,_HelloImplBase是由 idlj編譯器從示例 IDL 中生成的。
HelloImpl.java
|
/* * @author javamxj (CSDN Blog) 創建日期 2004-12-27 */ import HelloApp . * ; public class HelloImpl extends _HelloImplBase { /* 構造函數 */ public HelloImpl() { super (); } /* 實現接口聲明方法sayHello */ public String sayHello( String message) { System .out.println( "我在CORBA的服務器端,客戶端正在調用'sayHello'方法。 " ); System .out.println( "Hello " + message); return message; } } |
3. 服務器
服務器類含有服務器的main()方法,可完成以下任務:
·
創建一個 ORB 實例
·
創建一個HelloImpl實例(CORBA Hello對象的實現)并通知 ORB
·
獲取一個命名上下文的 CORBA 對象引用,在該命名上下文中注冊新 CORBA 對象
·
在命名上下文中將新對象注冊在“Hello”名下
·
等待對新對象的調用
HelloSever.java
|
/* * @author javamxj (CSDN Blog) 創建日期 2004-12-27 */ import org . omg . CosNaming . * ; import org . omg . CORBA . * ; public class HelloServer { public static void main( String args[]) { try { /* 創建和初始化 ORB */ ORB orb = ORB.init(args, null ); System .out.println( "開始 ORB Server ..." ); /* 創建一個實例并將其向 ORB 注冊 */ HelloImpl helloImpl = new HelloImpl(); orb.connect(helloImpl); System .out.println( "將實例注冊到ORB " ); /* 獲取根命名上下文 */ org.omg.CORBA. Object objRef =orb.resolve_initial_references( "NameService" ); NamingContext ncRef = NamingContextHelper.narrow(objRef); /* 綁定命名中的對象引用 */ NameComponent nc = new NameComponent( "Hello" , "" ); NameComponent path[] = { nc }; ncRef.rebind(path, helloImpl); /* 等待來自客戶機的調用 */ java.lang. Object sync = new java.lang. Object (); synchronized (sync) { sync.wait(); } System .out.println( "等待CORBA客戶端調用..." ); } catch ( Exception e) { System .err.println( "錯誤: " + e); e.printStackTrace( System .out); } } } |
4. 客戶端
下面的應用程序客戶機將完成以下任務:
·
創建一個 ORB
·
獲取一個指向命名上下文的引用
·
在命名上下文中查找 "Hello" 并獲得指向該 CORBA 對象的引用
·
調用對象的 sayHello() 操作并打印結果
HelloClient.java
|
|
CORBA Server/Client的編譯與運行
·
把上面4個文件復制到D:\CorbaSample目錄下,在此目錄下建立Client和Server目錄,假設它們分別為客戶端和服務端。
· 編譯Hello.idl
D:\CorbaSample>idlj -oldImplBase -fall Hello.idl
這會生成一個HelloApp的目錄
·
編譯所有java文件:
D:\CorbaSample>javac *.java HelloApp/*.java
·
分別在Client和Server目錄下建立HelloApp子目錄,將D:\CorbaSample\HelloApp目錄中的
_HelloStub.class
Hello.class
HelloHelper.class
HelloHolder.class
HelloOperations.class
復制到D:\CorbaSample\Client\HelloApp目錄下,再將D:\CorbaSample目錄中的HelloClient.class復制到D:\CorbaSample\Client目錄下。
將D:\CorbaSample\HelloApp目錄中的
_HelloImplBase.class
Hello.class
HelloOperations.class
復制到D:\CorbaSample\Server\HelloApp目錄下, 再將D:\CorbaSample目錄中的HelloServer.class和 HelloImpl.class 復制到D:\CorbaSample\Server目錄中
(
注意:
當然,你可以不必建立Server和Client目錄及以上復制文件的操作,可以直接在D:\CorbaSample目錄中進行操作,我這樣做的目的主要是為了區分客戶端和服務端
)
·
確保名字服務器處于運行狀態:
D:\CorbaSample\Server>tnameserv -ORBInitialPort 1050
·
啟動 Hello 服務器:
D:\CorbaSample\Server>java HelloServer -ORBInitialPort 1050
·
CORBA客戶端調用CORBA服務:
D:\CorbaSample\Client>java HelloClient -ORBInitialPort 1050
(本地調用,不需要用-ORBInitialHost參數來指定遠程的IP地址)
D:\CorbaSample\Server>java HelloClient -ORBInitialHost localhost -ORBInitialPort 1050
(遠程調用CORBA服務,可以將localhost替換成遠程的IP地址)
圖1. 客戶端沒有調用CORBA服務之前
圖2. 客戶端調用CORBA服務之后
一點補充:
不知道大家注意到沒有,在JDK1.4編譯idl文件時使用的idlj -oldImplBase -fall Hello.idl
這個命令帶有“-oldImplBase”參數,表示這是一個老版本的實現。而JDK1.4版本下,可以直接使用
idlj-fall Hello.idl命令,這樣
idlj
編譯器對服務器端生成的是輕便對象適配器(
POA
)。
(直接再命令行敲入idlj可以得到其使用說明)
這里我就不作詳細說明了,操作基本上與上一個例子相似。
首先在 D:\CorbaSample2 目錄下編寫下面4個文件,然后依次進行如下操作:
D:\CorbaSample2>idlj -fall Hello.idl
D:\CorbaSample2>javac *.java HelloApp/*.java
D:\CorbaSample2>tnameserv -ORBInitialPort 1050
D:\CorbaSample2>java HelloServer -ORBInitialPort 1050
D:\CorbaSample2>java HelloClient -ORBInitialPort 1050
(
注意
:這里為了方便.我沒有再劃分客戶端和服務端。進行對比,你可以發現這次idlj編譯器生成的文件與上例中生成的文件有和不同。)
Hello.idl
|
module HelloApp { interface Hello { string sayHello(in string message); }; }; |
HelloImpl.java
|
/* * @author javamxj (CSDN Blog) 創建日期 2004-12-27 */ import org . omg . CORBA . * ; import HelloApp . HelloPOA ; public class HelloImpl extends HelloPOA { private ORB orb; public void setORB(ORB orb_val) { orb = orb_val; } /* 實現接口聲明方法sayHello */ public String sayHello( String message) { System .out.println( "我在CORBA的服務器端,客戶端正在調用'sayHello'方法。 " ); System .out.println( "Hello " + message); return message; } } |
HelloServer.java
|
/* * @author javamxj (CSDN Blog) 創建日期 2004-12-27 */ import HelloApp . * ; import org . omg . CosNaming . * ; import org . omg . CORBA . * ; import org . omg . PortableServer . * ; import org . omg . PortableServer . POA ; public class HelloServer { public static void main( String args[]) { try { /* 創建和初始化 ORB */ ORB orb = ORB.init(args, null ); /* 獲取對RootPOA的引用,啟動POAManager */ POA rootpoa = POAHelper.narrow(orb .resolve_initial_references( "RootPOA" )); rootpoa.the_POAManager().activate(); /* 創建一個實例并將其向 ORB 注冊 */ HelloImpl h = new HelloImpl(); h.setORB(orb); System .out.println( "將實例注冊到ORB " ); /* 獲取對服務端的對象引用 */ org.omg.CORBA. Object ref = rootpoa.servant_to_reference(h); Hello href = HelloHelper.narrow(ref); /* 從名稱服務中獲取根元素名稱上下文 */ org.omg.CORBA. Object objRef = orb .resolve_initial_references( "NameService" ); NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef); /* 在Hello名稱下注冊新對象 */ String name = "Hello" ; NameComponent path[] = ncRef.to_name(name); ncRef.rebind(path, href); /* 等待客戶端的調用。 */ orb.run(); System .out.println( "等待CORBA客戶端調用..." ); } catch ( Exception e) { System .err.println( "ERROR: " + e); e.printStackTrace( System .out); } System .out.println( "HelloServer Exiting ..." ); } } |
HelloClient.java
|
/* * @author javamxj (CSDN Blog) 創建日期 2004-12-27 */ import HelloApp . * ; import org . omg . CosNaming . * ; import org . omg . CORBA . * ; public class HelloClient { public static void main( String args[]) { try { /* 創建和初始化 ORB */ ORB orb = ORB.init(args, null ); /* 獲取根命名上下文 */ org.omg.CORBA. Object objRef = orb .resolve_initial_references( "NameService" ); NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef); /* 在名稱上下文中查找Hello對象,獲取對它的引用。 */ String name = "Hello" ; Hello h = HelloHelper.narrow(ncRef.resolve_str(name)); System .out.println( "我在客戶端,開始調用CORBA服務器端的'sayHello'方法" ); System .out.println( "歡迎, " + h.sayHello( "javamxj blog" )); } catch ( Exception e) { System .out.println( "錯誤 : " + e); e.printStackTrace( System .out); } } } |
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
