CORBA的簡單介紹及HelloWorld
CORBA概述
CORBA(Common Object Request Broker Architecture,公共物件請求代理體系結構)是由OMG組織制訂的一種標準的面向物件應用程 序體系規範。或者說 CORBA體系結構是OMG為解決分散式處理環境(DCE)中,硬體和軟體系統的互連而提出的一種解決方案。
OMG:Object Management Group,物件管理組織。是一個國際化的、開放成員的、非盈利性的計算機行業標準協會,該協會成立於1989年,其職責是為應用開發提供一個公共框架,制訂工業指南和物件管理規範,加快物件技術的發展。。任何組織都可以加入OMG並且參與標準制定過程。OMG制定了統一建模語言UnifiedModeling Language™ (UML®),模型驅動架構Model Driven Architecture® (MDA®)等建模標準。使強大的視覺設計,執行和維護軟體等工序成為可能。並且,OMG還制定了廣為人知的中介軟體標準Common Object Request Broker Architecture (CORBA®)。
通用物件代理體系結構CORBA(Common Object Request Broker Architecture)是OMG所定義的用來實現現今大量硬體、軟體之間互操作的解決方案,CORBA也是邁向面向物件標準化和互操作的重要一步。
簡單地說,CORBA允許應用之間相互通訊,而不管它們存在於哪裡以及是誰設計的,即跨平臺、跨語言。CORBA1.1於1991年由OMG釋出,其中定義了介面定義語言(IDL)以及在物件請求代理(ORB)中實現客戶物件與伺服器物件之間互動的應用程式設計介面(API)。CORBA2.0於1994年釋出,規定了各個供應商之間的ORB的通訊規則。
CORBA標準主要分為三個部分
IDL是CORBA定義的語言,CORBA還定義了IDL到各種語言的對映,標準對映的有Ada、C、C++、Smalltalk、Java、以及Python。有了這些對映,就可以將IDL翻譯成各種語言,從而實現了跨語言。IDL語言是一種介面定義語言。IDL語言不同於所有已有的程式設計語言,它是一種描述性語言,也就是說,用它描述得到的介面是不能直接被編譯執行。OMG IDL語言採用ISOLatin-1(8859.1)字符集。該字符集可以分為字母、數字、圖形符號、空格符、和格式符號。其中字母包括英文26個字母的大小寫,數字包括10個阿拉伯數字0到9。
ORB是CORBA的核心,是物件之間建立Client/Server關係的中介軟體。使用ORB,客戶可以透明地呼叫一個服務物件上的方法,這個服務物件可以在本地,也可以在通過網路連線的其他機器上。ORB截獲這一呼叫同時負責查詢實現服務的物件並向其傳遞引數、呼叫方法返回最終結果。客戶並不知道服務物件位於什麼地方,它的程式語言和作業系統是什麼,也不知道不屬於物件介面的其他系統部分。這樣,ORB在異構分佈環境下為不同機器上的應用提供了互操作性,並無縫地集成了多種物件系統。
CORBA的基本結構如下:
在client端去呼叫server端的程式碼時,ORB對於client端是不可見的,client感覺好像呼叫了自己物件的方法一樣,但是網路傳輸的過程都被封裝在了ORB中。
CORBA和Java都採用面向物件技術,因此,可以很容易地用Java語言開發CORBA應用,或將Java應用以及JavaBean物件整合到CORBA應用環境中;CORBA和Java都適用於開發分散式應用,所不同的是:CORBA偏重於通用的分散式應用開發,而Java注重於WWW環境中的分散式應用開發。
使用CORBA開發的小例子
如果想開發一個CORBA的Helloworld,基本上有以下幾個步驟:
1.使用idl語言開發idl檔案,這個檔案中描述了介面的定義
-
module helloworld{
-
interface HelloWorld{
-
string sayHello();
-
};
-
};
module:對應了java中的package
interface:對應了java中的interface,HelloWorld即介面名稱
sayHello:對應了java中interface宣告的方法
string:對應了java中方法的返回值
2.使用java中的idlj命令,將idl語言翻譯成java語言,並生成java程式碼
將idl檔案拷貝到%JAVA_HOME%\bin下,然後在命令列下切換到bin目錄下執行:
idlj -fall helloworld.idl
idlj:java自帶的工具
-fall:生成server和client端程式碼,也可以單獨生成server或client
helloworld.idl:之前建立的idl檔案
此時,在bin目錄下就會生成helloworld資料夾,資料夾中會有6個檔案,將這6個拷回eclipse工程中。注意:檔案中的包名就是idl中生命的helloworld。如下圖:
這時_HelloWorldStub.java、HelloWorld.java、HelloWorldHelper.java、HelloWorldHolder.java、HelloWorldOperations.java是client需要的程式碼;HelloWorld.java、HelloWorldOperations.java、HelloWorldPOA.java是server需要的程式碼。
簡單看一下自動生成的這幾個檔案:
HelloWorld.java,與idl中的介面名一模一樣,但是實際上只是一個標識介面沒有任何的實現
-
package helloworld;
-
-
-
/**
-
* helloworld/HelloWorld.java .
-
* Generated by the IDL-to-Java compiler (portable), version "3.2"
-
* from helloworld.idl
-
* Friday, May 16, 2014 2:13:26 PM CST
-
*/
-
-
public
interface HelloWorld extends HelloWorldOperations, org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity
-
{
-
}
// interface HelloWorld
HelloWorldOperations.java,是idl中宣告的介面
-
package helloworld;
-
-
-
/**
-
* helloworld/HelloWorldOperations.java .
-
* Generated by the IDL-to-Java compiler (portable), version "3.2"
-
* from helloworld.idl
-
* Friday, May 16, 2014 2:13:26 PM CST
-
*/
-
-
public
interface HelloWorldOperations
-
{
-
String sayHello ();
-
}
// interface HelloWorldOperations
_HelloWorldStub.java、HelloWorldHelper.java、HelloWorldHolder.java是client的樁和工具類;HelloWorldPOA.java是server的實現介面的類(大概是這個意思吧,不太懂),看著比較暈,就不貼了。
3.開發server端的程式碼
既然開發了介面定義,也翻譯成了java程式碼,那麼就要寫介面的實現了,實現是在server端的,需要繼承自的HelloWorldPOA
-
package server;
-
-
import helloworld.HelloWorldPOA;
-
-
-
/**
-
* 伺服器端的實現程式碼
-
*
-
*/
-
public
class HelloWorldImpl extends HelloWorldPOA {
-
-
@Override
-
public String sayHello() {
-
-
return
"Hello World!";
-
}
-
-
}
server啟動的程式碼,這段程式碼主要功能是將介面實現註冊到ORB中,並啟動監聽,等待client來呼叫
-
package server;
-
-
import helloworld.HelloWorld;
-
import helloworld.HelloWorldHelper;
-
-
import org.omg.CORBA.ORB;
-
import org.omg.CORBA.ORBPackage.InvalidName;
-
import org.omg.CosNaming.NameComponent;
-
import org.omg.CosNaming.NamingContextExt;
-
import org.omg.CosNaming.NamingContextExtHelper;
-
import org.omg.CosNaming.NamingContextPackage.CannotProceed;
-
import org.omg.CosNaming.NamingContextPackage.NotFound;
-
import org.omg.PortableServer.POA;
-
import org.omg.PortableServer.POAHelper;
-
import org.omg.PortableServer.POAManagerPackage.AdapterInactive;
-
import org.omg.PortableServer.POAPackage.ServantNotActive;
-
import org.omg.PortableServer.POAPackage.WrongPolicy;
-
-
-
public
class HelloServer {
-
public static void main(String[] args) throws ServantNotActive, WrongPolicy, InvalidName, AdapterInactive, org.omg.CosNaming.NamingContextPackage.InvalidName, NotFound, CannotProceed {
-
//指定ORB的埠號 -ORBInitialPort 1050
-
args =
new String[
2];
-
args[
0] =
"-ORBInitialPort";
-
args[
1] =
"1050";
-
-
//建立一個ORB例項
-
ORB orb = ORB.init(args,
null);
-
-
//拿到RootPOA的引用,並激活POAManager,相當於啟動了server
-
org.omg.CORBA.Object obj=orb.resolve_initial_references(
"RootPOA");
-
POA rootpoa = POAHelper.narrow(obj);
-
rootpoa.the_POAManager().activate();
-
-
//建立一個HelloWorldImpl例項
-
HelloWorldImpl helloImpl =
new HelloWorldImpl();
-
-
//從服務中得到物件的引用,並註冊到服務中
-
org.omg.CORBA.Object ref = rootpoa.servant_to_reference(helloImpl);
-
HelloWorld href = HelloWorldHelper.narrow(ref);
-
-
//得到一個根名稱的上下文
-
org.omg.CORBA.Object objRef = orb.resolve_initial_references(
"NameService");
-
NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
-
-
//在命名上下文中繫結這個物件
-
String name =
"Hello";
-
NameComponent path[] = ncRef.to_name(name);
-
ncRef.rebind(path, href);
-
-
//啟動執行緒服務,等待客戶端呼叫
-
orb.run();
-
-
System.out.println(
"server startup...");
-
}
-
}
4.開發client端的程式碼
server端的實現與服務監聽都已經做完,現在需要寫一個client來呼叫server的方法
-
package client;
-
-
import helloworld.HelloWorld;
-
import helloworld.HelloWorldHelper;
-
-
import org.omg.CORBA.ORB;
-
import org.omg.CORBA.ORBPackage.InvalidName;
-
import org.omg.CosNaming.NamingContextExt;
-
import org.omg.CosNaming.NamingContextExtHelper;
-
import org.omg.CosNaming.NamingContextPackage.CannotProceed;
-
import org.omg.CosNaming.NamingContextPackage.NotFound;
-
-
-
public
class HelloClient {
-
static HelloWorld helloWorldImpl;
-
-
static {
-
System.out.println(
"client開始連線server.......");
-
-
//初始化ip和埠號,-ORBInitialHost 127.0.0.1 -ORBInitialPort 1050
-
String args[] =
new String[
4];
-
args[
0] =
"-ORBInitialHost";
-
//server端的IP地址,在HelloServer中定義的
-
args[
1] =
"127.0.0.1";
-
args[
2] =
"-ORBInitialPort";
-
//server端的埠,在HelloServer中定義的
-
args[
3] =
"1050";
-
-
//建立一個ORB例項
-
ORB orb = ORB.init(args,
null);
-
-
// 獲取根名稱上下文
-
org.omg.CORBA.Object objRef =
null;
-
try {
-
objRef = orb.resolve_initial_references(
"NameService");
-
}
catch (InvalidName e) {
-
e.printStackTrace();
-
}
-
NamingContextExt neRef = NamingContextExtHelper.narrow(objRef);
-
-
String name =
"Hello";
-
try {
-
-
//通過ORB拿到了server例項化好的實現類
-
helloWorldImpl = HelloWorldHelper.narrow(neRef.resolve_str(name));
-
}
catch (NotFound e) {
-
e.printStackTrace();
-
}
catch (CannotProceed e) {
-
e.printStackTrace();
-
}
catch (org.omg.CosNaming.NamingContextPackage.InvalidName e) {
-
e.printStackTrace();
-
}
-
-
System.out.println(
"client connected server.......");
-
}
-
-
public static void main(String args[]) throws Exception {
-
sayHello();
-
}
-
-
//呼叫實現類的方法
-
public static void sayHello() {
-
String str = helloWorldImpl.sayHello();
-
System.out.println(str);
-
}
-
}
我們可以看到在server和client個建立了一個ORB的例項,這時因為在server和client都需要有支援通訊(見上面的CORBA基本結構圖)。
5.啟動orbd服務
僅僅建立了server和client的程式碼還不足以跑起來一個HelloWorld,還需要啟動一個orbd服務,這個服務在%JAVA_HOME%\jre\bin下。orbd包含自啟動服務、透明的命名服務、持久化命名服務和命名管理器的後臺處理程序。應該是上面的HelloWorld用到了nameService所以才會需要這個服務,使用其他方式拿server的例項是不是就不需要這個服務了,又或者是所有的CORBA都要與這個服務通訊,不太明白?
在命令列下輸入啟動orbd:
- cd /d %JAVA_HOME%\bin
- orbd -ORBInitialPort 1050 -ORBInitialHost 127.0.0.1
6.啟動server服務
7.啟動client
可以看到輸出結果:
-
client開始連線
server.......
-
client connected
server.......
-
Hello World!
現在CORBA用的已經很少了,基本上只有一些大的電信專案還在用,現在同類的解決方案中WebService是比較流行的。
<script>
(function(){
function setArticleH(btnReadmore,posi){
var winH = $(window).height();
var articleBox = $("div.article_content");
var artH = articleBox.height();
if(artH > winH*posi){
articleBox.css({
'height':winH*posi+'px',
'overflow':'hidden'
})
btnReadmore.click(function(){
articleBox.removeAttr("style");
$(this).parent().remove();
})
}else{
btnReadmore.parent().remove();
}
}
var btnReadmore = $("#btn-readmore");
if(btnReadmore.length>0){
if(currentUserName){
setArticleH(btnReadmore,3);
}else{
setArticleH(btnReadmore,1.2);
}
}
})()
</script>
</article>