第三章 简单 Corba 程序设计
description
Transcript of 第三章 简单 Corba 程序设计
山东大学计算机科学与技术学院基础技术教学部
第三章简单 Corba程序设计
山东大学计算机科学与技术学院
1 CORBA应用开发过程
CORBA规范并没有限制 ORB的具体实现方法,所以不同厂商对 ORB的具体实现方法可能差别很大,这就导致不同厂商提供的 ORB上操作可能有很大的差异。但基本过程都是类似的。
山东大学计算机科学与技术学院
1.1 开发环境
Inprise VisiBroker 4.5 + JDK 1.3 + UltraEdit
Inprise Visibroker 5 + JDK 1.4 ( + Jbuilder / SunOne
Studio EE)
山东大学计算机科学与技术学院
1.2 静态工作方式
客户方 对象实现方
IDL 桩(客户方代
理)
IDL 构架(服务方
代理)
ORB 内核
山东大学计算机科学与技术学院
设计一个静态方式的程序
IDL 文件对象实现
IDL 编译器JavaC++…
IDL 桩JavaC++…
IDL 构架JavaC++…
客户方调用
服务方主程序
山东大学计算机科学与技术学院
1.4典型的 CORBA应用实现过程
用 IDL编写对象规格说明
编译 IDL生成桩和框架
编写客户程序代码 编写对象实现和服务程序代码
编译客户程序 编译服务程序
运行客户程序 运行服务程序
启动对象请求代理( ORB)内核
一个典型 CORBA 应用的实现过程
山东大学计算机科学与技术学院
对象接口
对象接口实际上是分布式对象向外提供服务的规格说明
是客户程序与对象实现之间的一种合约,双方必须严格遵守对象接口定义中的约定,包括操作名字,参数表,返回表,异常表,上下文等
对象接口定义存放在一个或多个 IDL文本文件中,指明每一对象对外提供的服务,以及客户程序如何使用这些服务或处理服务的返回结果
山东大学计算机科学与技术学院
1.3 IDL语言
说明性语言,定义组件接口,不定义实现。 语法上可以看成 C++的一个子集,规定组件的属性、所继承的父类、产生的异常、事件和各类数据类型。
编译器作用:将 IDL映射到具体程序设计语言,产生桩代码和框架代码
调用请求经客户端桩传递给 ORB,然后转发到服务端框架,最后到达真正要执行请求的对象实现实例
山东大学计算机科学与技术学院
编写对象实现和服务程序
IDL文件只定义了对象的语法规格说明,必须编写这些对象的具体实现代码
对象实现可用各种语言实现,且与客户程序的语言无关 IDL到编程语言的映射规则
– 生成 IDL框架代码和各种辅助性的 java接口或类– 编写对象实现代码时必须继承或使用其中的某些接口或类
服务程序– 利用 POA激活伺服对象供客户对象使用– 通常是一个循环执行的进程,不断监听客户程序请求并为之服务
山东大学计算机科学与技术学院
编写客户程序
初始化 ORB
– 是应用程序进入 CORBA的起点– 作用
让 ORB 了解有新的成员加入获取 ORB 伪对象的引用,以备调用 ORB 内核提供的操作时使用
– 伪对象 (pseudo object):在 CORBA基础设施中的一个对象
获取分布式对象引用,利用其调用对象实现提供的服务
山东大学计算机科学与技术学院
创建并部署应用程序
客户端:客户程序代码与 IDL编译器自动生成的 ID
L桩代码一起编译 服务端:对象实现代码与服务程序代码与 IDL框架代码一起编译
山东大学计算机科学与技术学院
1.5 例子背景
银行账户管理– 服务端管理大量银行顾客的账户,提供基本的开户、存款、取款、查询余额的功能。
山东大学计算机科学与技术学院
1.5.1 对象认定
一个银行帐户的实体模型。 balance :表示当前的余额。 deposit:存款 withdraw:取款 getBalance:查询余额
AccountManager
accountList : HashTable
open(name : String) : Account
manage 银行中的储蓄员的实体模型。 accountList :记录当前已开设的
所有帐户。 open :根据帐户标识查找某一帐
户,如果该标识的帐户不存在则创建一个新帐户。
Account
balance : float
deposit(amount : float) : voidwithdraw(amount : float) : booleangetBalance() : float
山东大学计算机科学与技术学院
1.5.2 定义对象接口
// 银行帐户管理系统的对象接口定义module Bank { // 帐户 interface Account { // 存款 void deposit(in float amount); // 取款 boolean withdraw(in float amount); // 查询余额 float getBalance(); }; // 帐户管理员 interface AccountManager { // 查询指定名字的帐户,查无则新开帐户 Account open(in string name); };};
Bank.idl
山东大学计算机科学与技术学院
1.5.3 生成 Stub与 Skeleton
IDL编译器作用是将 IDL映射到具体程序设计语言,产生桩代码和框架代码
Visibroker for java提供的编译器 idl2java将 IDL映射到 jav
a语言,生成 java语言的桩和框架语言 每个对象实例都有一个用于唯一标识自身的对象引用。客户程序利用对象引用指明调用的方向
表面上看,客户程序调用的是远程对象实现上的操作,实际被调用的代码是作为其代理的 IDL桩
山东大学计算机科学与技术学院
生成 Stub与 Skeleton
prompt> idl2java Bank.idl
idl2javaBank.idl
Stub
Skeleton输入
输出
其它辅助文件
山东大学计算机科学与技术学院
1.5.4 生成 7个文件
VisiBroker for Java的 IDL编译器 idl2java为每个接口自动生成 7个文件:– AccountOperations.java– Account.java– _AccountStub.java– AccountPOA.java– AccountPOATie.java– AccountHelper.java– AccountHolder.java
山东大学计算机科学与技术学院
1.5.4.1 生成的接口定义
Account.java和 AccountOperations.java定义了 IDL
接口 Account的完整基调。– AccountOperations.java(操作基调 )定义了 Account接口中定义的所有常量和方法。
package Bank; public interface AccountOperations//操作接口{ public void deposit(float amount); public boolean withdraw(float amount); public float getBalance();}
山东大学计算机科学与技术学院
生成的接口定义
– 客户程序代码中,程序员通常使用的是操作接口的派生接口 Ac
count( 位于 Account.java)
package Bank; public interface Account extends com.inprise.vbroker.CORBA.Object, Bank.AccountOperations, org.omg.CORBA.portable.IDLEntity{}
山东大学计算机科学与技术学院
1.5.4.2 生成的 Stub
_AccountStub.java是 Account对象在客户端的桩代码,它实现了 Account接口。– 程序员编写的客户程序代码通常不直接调用这个类中的方法。– VisiBroker for Java生成了另外的辅助类 AccountHelper。
山东大学计算机科学与技术学院
生成的 Stub
package Bank; public class _AccountStub extends com.inprise.vbroker.CORBA.portable.ObjectImpl implements Account{ final public static java.lang.Class _opsClass =
Bank.AccountOperations.class; private static java.lang.String[] __ids =
{"IDL:Bank/Account:1.0"}; public java.lang.String[] _ids(){ return __ids; } public void deposit(float amount){ //与 ORB交互,完成真正的 deposit方法调用 } public boolean withdraw(float amount){ //与 ORB交互,完成真正的 withdraw方法调用 } public float getBalance(){ //与 ORB交互,完成真正的 getBalance方法调用 }}
_AccountStub.java
山东大学计算机科学与技术学院
1.5.4.3 生成的 Skeleton
AccountPOA.java是 Account对象的服务端框架代码,该类的功能:– 解包 in类型的参数并将参数传递给对象实现。– 打包返回值与所有 out类型的参数。
打包( marshal ):指将特定程序设计语言描述的数据类型转换为 CORBA 的 IIOP 流格式。
解包( unmarshal ):从 IIOP 流格式转换为依赖于具体程序设计语言的数据结构。
编写对象实现的最简单途径是继承这些 POA类,即把它们作为对象实现的基类。
山东大学计算机科学与技术学院
生成的 Skeleton
package Bank; public abstract class AccountPOA extends org.omg.PortableServer.Servant implements org.omg.CORBA.portable.InvokeHandler,
Bank.AccountOperations{ public static org.omg.CORBA.portable.OutputStream _invoke( ...) { org.omg.CORBA.portable.OutputStream _output = null; { switch (_method_id) { case 0: { float amount; amount = _input.read_float(); _self.deposit(amount); _output = _handler.createReply(); return _output; } case 1: {//...
} case 2: {//...
} }}}}
AccountPOA.java
山东大学计算机科学与技术学院
1.5.4.4 生成的辅助工具类
IDL编译器为每一个用户自定义类型还生成一个辅助工具类。AccountHelper.java 声明了 AccountHelper类,该类为 Account接口定义了许多实用功能和支持功能的静态方法(又称类方法)。– 从 Any对象提取或向 Any对象插入对象( extract和 insert方法);– 从输入/输出流读写对象( read和 write方法);– 获取对象的库标识和类型码( id和 type方法);– 绑定对象与类型转换操作( bind 和 narrow 方法)等等。
编程时会用到该类中提供的方法。
山东大学计算机科学与技术学院
生成的辅助工具类
package Bank; public final class AccountHelper{ public static Bank.Account narrow
(final org.omg.CORBA.Object obj) { //... } public static Bank.Account bind(org.omg.CORBA.ORB orb,
java.lang.String name) { //... } //...}
AccountHelper.java
山东大学计算机科学与技术学院
1.5.4.5 生成的对象传递支撑类
AccountHolder.java 声明的 AccountHolder类为传递对象提供支持。– IDL有三种参数传递方式: in、 out和 inout。– in类型的参数以及返回结果与 Java的参数传递方式与结果返回方式完全相同。
– out和 inout 两种类型的参数允许参数具有返回结果的能力,无法直接映射到 Java语言的参数传递机制,这时 AccountHolder
类为传递 out和 inout参数提供了一个托架( holder)。
山东大学计算机科学与技术学院
In表明实际参数从客户程序传向对象实现 Out表明数据从实现对象传递给客户程序,并且对象实现无需从客户程序获取参数的初始值
Inout表明数据从客户程序传给对象实现,然后经对象实现加工后再返回给客户程序
山东大学计算机科学与技术学院
生成的对象传递支撑类
package Bank; public final class AccountHolder implements org.omg.CORBA.portable.Streamable{ public Bank.Account value; public AccountHolder() {} public AccountHolder(final Bank.Account _vis_value){ this.value = _vis_value; } public void _read(
final org.omg.CORBA.portable.InputStream input){ value = Bank.AccountHelper.read(input); } public void _write(final
org.omg.CORBA.portable.OutputStream output){ Bank.AccountHelper.write(output, value); } public org.omg.CORBA.TypeCode _type() { return Bank.AccountHelper.type(); }}
AccountHolder.java
山东大学计算机科学与技术学院
1.5.5 编写对象实现
对象实现代码所在的类名字可由程序员自由掌握,只要不与IDL编译器自动产生的 Java类产生名字冲突即可。客户程序也无须了解对象实现是由哪一个 Java类完成的。
CORBA应用程序的对象实现最常用、最简单的实现方式是使用继承,即直接继承由 IDL编译器生成的 xxxPOA类。– 当对象实现需要利用继承机制达到其他目的时,就必须改用 CORBA对象实现的另一种实现方式 ── 纽带机制( tie mechanism)。
我们的例子程序采用简单的继承方式编写对象实现。
山东大学计算机科学与技术学院
账户的对象实现
public class AccountImpl extends Bank.AccountPOA{ // 属性定义 protected float balance; // 构造方法,按指定余额创建新的帐户 public AccountImpl(float bal){ balance = bal; } // 往帐户中存款 public void deposit(float amount){ balance += amount; } // 从帐户中取款,不足余额则返回 false public boolean withdraw(float amount){ if (balance < amount) return false;
else { balance -= amount; return true;}
}// 查询帐户余额public float getBalance(){
return balance}
}
AccountImpl.java
山东大学计算机科学与技术学院
账户管理员的对象实现
public class AccountManagerImpl extends Bank.AccountManagerPOA{ protected Hashtable accountList; // 该帐户管理员所负责的帐户清单 public AccountManagerImpl(){ accountList = new Hashtable(); } public synchronized Bank.Account open(String name){ Bank.Account account=(Bank.Account)accountList.get(name); if (account == null) { Random random = new Random(); float balance = Math.abs(random.nextInt())%100000/100f; AccountImpl accountServant = new AccountImpl(balance); try {
org.omg.CORBA.Object obj = _default_POA().servant_to_reference(accountServant);
account = Bank.AccountHelper.narrow(obj); } catch(Exception exc) { exc.printStackTrace(); } accountList.put(name, account); System.out.println("新开帐户: " + name); } return account; }}
AccountManagerImpl.java
山东大学计算机科学与技术学院
1.5.6 编写服务程序
通常程序员都会编写一个名为 Server.java的服务程序,服务程序创建伺服对象供客户端使用。
山东大学计算机科学与技术学院
编写服务程序
初始化 ORB
创建一个 POA
创建提供服务的伺服对象
激活伺服对象
激活 POA管理器
等待客户程序发来请求
服务程序的处理流程
山东大学计算机科学与技术学院
编写服务程序
public class Server{ public static void main(String[] args) { try { org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null); POA rootPOA = POAHelper.narrow( orb.resolve_initial_references("RootPOA")); org.omg.CORBA.Policy[] policies = { rootPOA.create_lifespan_policy(
LifespanPolicyValue.PERSISTENT) }; POA myPOA = rootPOA.create_POA("BankPOA", rootPOA.the_POAManager(), policies); AccountManagerImpl managerServant =
new AccountManagerImpl(); myPOA.activate_object_with_id( "BankManager".getBytes(), managerServant); rootPOA.the_POAManager().activate(); System.out.println("帐户管理员 BankManager已就绪 ...\n"); orb.run(); } catch(Exception exc) { exc.printStackTrace(); } }}
服务程序 Server.java
初始化 ORB
创建一个 POA
创建提供服务的伺服对象
激活伺服对象
激活 POA管理器
等待客户程序发来请求
山东大学计算机科学与技术学院
1.5.7 编写客户程序
初始化 ORB
绑定到服务对象
调用服务对象提供的服务
客户程序操作流程
山东大学计算机科学与技术学院
编写客户程序
public class Client{ public static void main(String[] args) { org.omg.CORBA.ORB orb=org.omg.CORBA.ORB.init(args, null); // 利用 POA全称与对象标识 "BankManager"查找帐户管理员 Bank.AccountManager manager =
Bank.AccountManagerHelper.bind( orb, "/BankPOA", "BankManager".getBytes()); String name = args.length > 0 ? args[0] : "David Zeng"; // 请求帐户管理员找出一个指定名字的帐户,无此帐户则新开一个 Bank.Account account = manager.open(name); System.out.println(name + “的帐户余额为” +
account.getBalance() + "元 "); account.deposit(200); System.out.println(“存款 200元后,余额为” +
account.getBalance() + “元” ); if (account.withdraw(600)) { System.out.println(“取款 600元后,余额为” +
account.getBalance() + "元 "); } else { System.out.println("余额不足 600元,取款失败,余额保持不变 "); } }}
客户程序 Client.java
初始化 ORB
绑定到服务对象
调用服务对象提供的服务
山东大学计算机科学与技术学院
1.5.8 编译应用程序
利用 VisiBroker for Java提供的编译器 vbjc 完成这一工作:– prompt> vbjc Server.java
– prompt> vbjc Client.java
vbjc实际上封装了 JDK提供的 Java编译器。 Holder类和 POATie类需要指定额外的参数才会生成。
山东大学计算机科学与技术学院
1.5.9 运行应用程序
按一定的顺序启动应用程序– 1. 启动智能代理
运行 CORBA 应用程序之前,网络中必须至少有一台主机上启动了智能代理 osagent 。这是 VisiBroker 特有的分布式位置服务( location service )守护进程,网络中多个智能代理可协作以查找合适的对象实现。
prompt> osagent
– 2.启动服务程序 prompt> start vbj Server
– 3.启动客户程序 prompt> vbj Client