天天看點

Java&CORBA程式設計執行個體

版權聲明:本文為部落客chszs的原創文章,未經部落客允許不得轉載。 https://blog.csdn.net/chszs/article/details/4353478

Java&CORBA程式設計執行個體

Java IDL技術在Java平台上添加了CORBA(Common Object Request Broker Architecture)功能,提供了基于标準的互操作能力和連接配接性。Java IDL技術使得分布式的Java Web應用能夠通過使用工業标準的IDL和IIOP(Internet Inter-ORB Protocol)來透明地調用遠端網絡服務的操作。運作時元件(Runtime Components)包括了一個用于分布式計算且使用IIOP通信的Java ORB.

可移植對象擴充卡(Portable Object Adapter,POA)

CORBA對象的負責分隔伺服器端遠端調用句柄(handler)到遠端對象和它的服務者(servant)。對象由遠端調用所暴露,而服務者包含實際處理這些請求的方法。每個對象都可以選擇服務者為靜态的(一次)或動态的(每個遠端調用),在這兩種情況下,都允許調用轉移到另一台伺服器。

在伺服器端,POA形成了類似樹狀的結構,每個POA都負責一到多個服務的對象。樹的分支可以是獨立活動的、或鈍化的,服務者調用有不同的代碼和不同的請求處理政策。

API規範

    * org.omg.CORBA 包 - 提供了OMG CORBA APIs到Java程式設計語言的映射

    * org.omg.CosNaming 包 - 為Java IDL提供命名服務

    * org.omg.PortableServer 包 - 為建立伺服器端的可移植的、跨越多ORB的應用程式提供類和接口

    * org.omg.PortableInterceptor 包 - 提供了注冊ORB鈎子的機制,此鈎子通過ORB服務能截取正常的ORB執行流

    * org.omg.DynamicAny 包 - 提供了使得任何值都能被動态解釋(或周遊)和通過DynAny對象構造出來的類和接口

    * org.omg.CORBA.ORB - 為CORBA ORB功能的API

分布式對象之間的關系有兩方面:用戶端和伺服器。

伺服器提供遠端接口,用戶端調用遠端接口。

在用戶端,應用程式包括遠端對象的引用。該對象引用有stub方法,它是獨立的遠端方法。stub方法實際連接配接到ORB,是以調用它實際上轉發調用到伺服器。

在伺服器端,ORB使用skeleton代碼翻譯遠端調用為本地對象的方法調用。Skeleton把調用轉換成指定實作的格式,并在方法中調用。當方法傳回時,Skeleton代碼轉換方法調用的結果或錯誤,經ORB送回用戶端。

Java IDL開發過程

1)定義遠端接口

使用IDL語言為遠端對象定義接口。

【Billing.idl源代碼】如下:

// 聲明CORBA IDL子產品

module BillingApp{

// 聲明接口

interface Billing{

string successBilling();

oneway void shutdown();

};

};

2)編譯遠端接口

使用idlj編譯器生成Java語言的stub和skeleton源檔案。

idlj編譯器預設隻生成用戶端的binding代碼。如果同時需要用戶端的bindings和伺服器端的skeletons,必須加上-fall選項。

使用POA(Portable Object Adaptor)的優點:

· 允許程式設計者建構對象在不同ORB産品之間的可移植實作

· 支援帶持久化辨別的對象

· 對對象的透明活動提供支援

· 允許單個servant支援多種對象同時辨別

注意:确定jdk/bin目錄下有:idlj、java、javac、orbd

指令:

 idlj -fall Billing.idl

在目前目錄下生成BillingApp目錄,包含如下六個檔案:

· Billing.java    ————> 此接口包含IDL接口的Java版本。它繼承自org.omg.CORBA.Object,提供标準的CORBA對象功能。

· BillingHelper.java    ————> 此類提供輔助功能,Helper類負責讀寫資料類型到CORBA流,以及插入和提取資料類型。

· BillingHolder.java    ————> This final class holds a public instance member of type Billing.

· BillingOperations.java    ————> 此接口包含successBilling()和shutdown()方法。

· BillingPOA.java    ————> 此抽象類是基于流的伺服器Skeleton,為伺服器提供基本的CORBA功能。它繼承org.omg.PortableServer.Servant,實作了InvokeHandler接口和BillingOperations接口。伺服器類BillingServant繼承BillingPOA。

· _BillingStub.java    ————> 此類是用戶端stub,為用戶端提供CORBA功能。它繼承org.omg.CORBA.Object,提供标準CORBA對象功能。還擴充了BillingOperations接口和org.omg.CORBA.portable.IDLEntity接口。

3)實作伺服器端

一旦使用idlj編譯器後,就可以使用它産生的Skeleton裝配伺服器應用程式了。另外要實作遠端接口方法,伺服器代碼應包含啟動ORB和等待遠端用戶端調用的機制。

伺服器端由兩個類組成,一個是servant,另一個是Server。

servant是BillingImpl類,是Billing IDL接口的實作,每個Billing執行個體均由BillingImpl執行個體實作。servant是BillingPOA的子類。

servant包含了IDL定義的所有方法,與通常的Java方法類似。

server類含伺服器的main()方法,它:

· 建立和初始化ORB執行個體

· 獲得根POA的引用并激活POAManager

· 建立一個Servant執行個體(CORBA的Billing對象的實作)并通知ORB

· 獲得根命名上下文

· 在命名上下文用“Billing”名注冊新對象

· 等待用戶端調用此新對象

【BillingImpl.java源碼】:

import org.omg.CORBA.ORB;

import BillingApp.*;

class BillingImpl extends BillingPOA{

private ORB orb;

public void setORB(ORB orb_val){

this.orb = orb_val;

}

/**

* 實作successBilling()方法

*/

public String successBilling() {

return "/nBilling success!!/n";

* 實作shutdown()方法

public void shutdown(){

orb.shutdown(false);

}

【BillingServer.java源碼】:

import org.omg.CosNaming.NameComponent;

import org.omg.CosNaming.NamingContextExt;

import org.omg.CosNaming.NamingContextExtHelper;

import org.omg.PortableServer.POA;

public class BillingServer {

public static void main(String args[]){

try{

// 建立和初始化ORB

ORB orb = ORB.init(args, null);

// 獲得根POA的引用并激活POAManager

POA rootpoa = (POA)orb.resolve_initial_references("RootPOA");

rootpoa.the_POAManager().activate();

// 建立servant并注冊到ORB

BillingImpl billingImpl = new BillingImpl();

billingImpl.setORB(orb);

// 從servant獲得對象引用

org.omg.CORBA.Object ref = rootpoa.servant_to_reference(billingImpl);

Billing href = BillingHelper.narrow(ref);

// 得到根命名上下文

org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");

// 使用命名上下文,它是互操作命名服務規範的一部分

NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);

// 在命名中綁定對象引用

String name = "Billing";

NameComponent path[] = ncRef.to_name(name);

ncRef.rebind(path, href);

System.out.println("BillingServer is ready and waiting...");

// 等待用戶端調用

orb.run();

}catch(Exception e){

System.err.println("ERROR:"+e);

e.printStackTrace(System.out);

}

System.out.println("BillingServer Exiting ...");

4)實作用戶端

與第三步類似,可以使用idlj産生的stub作為用戶端應用程式的基礎。用戶端代碼建立于stub之上,啟動ORB,使用伺服器提供的命名服務查詢,獲得遠端對象的引用,調用其方法。

【BillingClient.java源碼】:

public class BillingClient {

static Billing billingImpl;

System.out.println("ORB initialised");

// 獲得根命名上下文

// 使用NamingContextExt代替命名上下文,它是互操作命名服務的一部分

// 在命名中解析對象引用

billingImpl = BillingHelper.narrow(ncRef.resolve_str(name));

System.out.println("Obtained a handle on server object: "+billingImpl);

System.out.println(billingImpl.successBilling());

billingImpl.shutdown();

System.out.println("ERROR: "+e);

5)啟動應用程式

要運作伺服器和用戶端,必須先啟動命名服務,再啟動伺服器,最後運作用戶端。

此例用到命名服務,它使得servant對象的操作對用戶端有效。伺服器需要命名服務的對象引用,命名服務可以釋出對象引用實作各種接口。用戶端使用對象引用來調用方法。

Java SE 1.4以上提供了兩種可選的命名服務:

· tnameserv

一種透明的命名服務

· orbd

包含自啟動服務、透明的命名服務、持久化命名服務和命名管理器的背景處理程序。

本例使用orbd。

5.1)啟動orbd

注意:Solaris系統運作要求root權限并以1024端口開始程序。是以,對所有OS,可以選用大于或等于1024的端口以實作統一。

-ORBInitialPort選項用于指定端口(非預設狀态)。

例如:假定使用1050端口的Java ORB Daemon(orbd),指令如下:

start orbd -ORBInitialPort 1050 -ORBInitialHost localhost

5.2)開始Billing伺服器

start java BillingServer -ORBInitialPort 1050 -ORBInitialHost localhost

注:如在同一台主機上運作,可省略-ORBInitialHost localhost

5.3)運作用戶端應用程式

java BillingClient -ORBInitialPort 1050 -ORBInitialHost localhost