1 / 38

第三章 简单 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 构架(服务方代理).

lois-duke
Download Presentation

第三章 简单 Corba 程序设计

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第三章简单Corba程序设计

  2. 1 CORBA应用开发过程 • CORBA规范并没有限制ORB的具体实现方法,所以不同厂商对ORB的具体实现方法可能差别很大,这就导致不同厂商提供的ORB上操作可能有很大的差异。但基本过程都是类似的。

  3. 1.1 开发环境 • Inprise VisiBroker 4.5 + JDK 1.3 + UltraEdit • Inprise Visibroker 5 + JDK 1.4 ( + Jbuilder / SunOne Studio EE)

  4. 1.2 静态工作方式 客户方 对象实现方 IDL构架(服务方代理) IDL桩 (客户方代理) ORB内核

  5. 对象实现 IDL编译器 Java C++ … IDL桩 Java C++ … IDL构架 Java C++ … 设计一个静态方式的程序 IDL文件 客户方调用 服务方主程序

  6. 用IDL编写对象规格说明 编译IDL生成桩和框架 编写客户程序代码 编写对象实现和服务程序代码 编译客户程序 编译服务程序 运行客户程序 运行服务程序 启动对象请求代理(ORB)内核 1.4典型的CORBA应用实现过程 一个典型CORBA应用的实现过程

  7. 对象接口 • 对象接口实际上是分布式对象向外提供服务的规格说明 • 是客户程序与对象实现之间的一种合约,双方必须严格遵守对象接口定义中的约定,包括操作名字,参数表,返回表,异常表,上下文等 • 对象接口定义存放在一个或多个IDL文本文件中,指明每一对象对外提供的服务,以及客户程序如何使用这些服务或处理服务的返回结果

  8. 1.3 IDL语言 • 说明性语言,定义组件接口,不定义实现。 • 语法上可以看成C++的一个子集,规定组件的属性、所继承的父类、产生的异常、事件和各类数据类型。 • 编译器作用:将IDL映射到具体程序设计语言,产生桩代码和框架代码 • 调用请求经客户端桩传递给ORB,然后转发到服务端框架,最后到达真正要执行请求的对象实现实例

  9. 编写对象实现和服务程序 • IDL文件只定义了对象的语法规格说明,必须编写这些对象的具体实现代码 • 对象实现可用各种语言实现,且与客户程序的语言无关 • IDL到编程语言的映射规则 • 生成IDL框架代码和各种辅助性的java接口或类 • 编写对象实现代码时必须继承或使用其中的某些接口或类 • 服务程序 • 利用POA激活伺服对象供客户对象使用 • 通常是一个循环执行的进程,不断监听客户程序请求并为之服务

  10. 编写客户程序 • 初始化ORB • 是应用程序进入CORBA的起点 • 作用 • 让ORB了解有新的成员加入 • 获取ORB伪对象的引用,以备调用ORB内核提供的操作时使用 • 伪对象(pseudo object):在CORBA基础设施中的一个对象 • 获取分布式对象引用,利用其调用对象实现提供的服务

  11. 创建并部署应用程序 • 客户端:客户程序代码与IDL编译器自动生成的IDL桩代码一起编译 • 服务端:对象实现代码与服务程序代码与IDL框架代码一起编译

  12. 1.5 例子背景 • 银行账户管理 • 服务端管理大量银行顾客的账户,提供基本的开户、存款、取款、查询余额的功能。

  13. manage 1.5.1 对象认定 • 一个银行帐户的实体模型。 • balance:表示当前的余额。 • deposit:存款 • withdraw:取款 • getBalance:查询余额 • 银行中的储蓄员的实体模型。 • accountList :记录当前已开设的所有帐户。 • open:根据帐户标识查找某一帐户,如果该标识的帐户不存在则创建一个新帐户。

  14. 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

  15. 1.5.3 生成Stub与Skeleton • IDL编译器作用是将IDL映射到具体程序设计语言,产生桩代码和框架代码 • Visibroker for java提供的编译器idl2java将IDL映射到java语言,生成java语言的桩和框架语言 • 每个对象实例都有一个用于唯一标识自身的对象引用。客户程序利用对象引用指明调用的方向 • 表面上看,客户程序调用的是远程对象实现上的操作,实际被调用的代码是作为其代理的IDL桩

  16. 生成Stub与Skeleton • prompt> idl2java Bank.idl Stub Bank.idl Skeleton 输入 idl2java 输出 其它辅助 文件

  17. 1.5.4 生成7个文件 • VisiBroker for Java的IDL编译器idl2java为每个接口自动生成7个文件: • AccountOperations.java • Account.java • _AccountStub.java • AccountPOA.java • AccountPOATie.java • AccountHelper.java • AccountHolder.java

  18. 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(); }

  19. 生成的接口定义 • 客户程序代码中,程序员通常使用的是操作接口的派生接口Account(位于Account.java) package Bank; public interface Account extends com.inprise.vbroker.CORBA.Object, Bank.AccountOperations, org.omg.CORBA.portable.IDLEntity {}

  20. 1.5.4.2 生成的Stub • _AccountStub.java是Account对象在客户端的桩代码,它实现了Account接口。 • 程序员编写的客户程序代码通常不直接调用这个类中的方法。 • VisiBroker for Java生成了另外的辅助类AccountHelper。

  21. 生成的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

  22. 1.5.4.3 生成的Skeleton • AccountPOA.java是Account对象的服务端框架代码,该类的功能: • 解包in类型的参数并将参数传递给对象实现。 • 打包返回值与所有out类型的参数。 • 打包(marshal):指将特定程序设计语言描述的数据类型转换为CORBA的IIOP流格式。 • 解包(unmarshal):从IIOP流格式转换为依赖于具体程序设计语言的数据结构。 • 编写对象实现的最简单途径是继承这些POA类,即把它们作为对象实现的基类。

  23. 生成的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

  24. 1.5.4.4 生成的辅助工具类 • IDL编译器为每一个用户自定义类型还生成一个辅助工具类。AccountHelper.java声明了AccountHelper类,该类为Account接口定义了许多实用功能和支持功能的静态方法(又称类方法)。 • 从Any对象提取或向Any对象插入对象(extract和insert方法); • 从输入/输出流读写对象(read和write方法); • 获取对象的库标识和类型码(id和type方法); • 绑定对象与类型转换操作(bind和narrow方法)等等。 • 编程时会用到该类中提供的方法。

  25. 生成的辅助工具类 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

  26. 1.5.4.5 生成的对象传递支撑类 • AccountHolder.java声明的AccountHolder类为传递对象提供支持。 • IDL有三种参数传递方式:in、out和inout。 • in类型的参数以及返回结果与Java的参数传递方式与结果返回方式完全相同。 • out和inout两种类型的参数允许参数具有返回结果的能力,无法直接映射到Java语言的参数传递机制,这时AccountHolder类为传递out和inout参数提供了一个托架(holder)。

  27. In表明实际参数从客户程序传向对象实现 • Out表明数据从实现对象传递给客户程序,并且对象实现无需从客户程序获取参数的初始值 • Inout表明数据从客户程序传给对象实现,然后经对象实现加工后再返回给客户程序

  28. 生成的对象传递支撑类 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

  29. 1.5.5 编写对象实现 • 对象实现代码所在的类名字可由程序员自由掌握,只要不与IDL编译器自动产生的Java类产生名字冲突即可。客户程序也无须了解对象实现是由哪一个Java类完成的。 • CORBA应用程序的对象实现最常用、最简单的实现方式是使用继承,即直接继承由IDL编译器生成的xxxPOA类。 • 当对象实现需要利用继承机制达到其他目的时,就必须改用CORBA对象实现的另一种实现方式 ── 纽带机制(tie mechanism)。 • 我们的例子程序采用简单的继承方式编写对象实现。

  30. 账户的对象实现 • 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

  31. 账户管理员的对象实现 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

  32. 1.5.6 编写服务程序 • 通常程序员都会编写一个名为Server.java的服务程序,服务程序创建伺服对象供客户端使用。

  33. 编写服务程序 初始化ORB 创建一个POA 创建提供服务的伺服对象 激活伺服对象 激活POA管理器 等待客户程序发来请求 服务程序的处理流程

  34. 初始化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

  35. 初始化ORB 绑定到服务对象 调用服务对象提供的服务 1.5.7 编写客户程序 客户程序操作流程

  36. 初始化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

  37. 1.5.8 编译应用程序 • 利用VisiBroker for Java提供的编译器vbjc完成这一工作: • prompt> vbjc Server.java • prompt> vbjc Client.java • vbjc实际上封装了JDK提供的Java编译器。 • Holder类和POATie类需要指定额外的参数才会生成。

  38. 1.5.9 运行应用程序 • 按一定的顺序启动应用程序 • 1. 启动智能代理 • 运行CORBA应用程序之前,网络中必须至少有一台主机上启动了智能代理osagent。这是VisiBroker特有的分布式位置服务(location service)守护进程,网络中多个智能代理可协作以查找合适的对象实现。 • prompt> osagent • 2.启动服务程序 • prompt> start vbj Server • 3.启动客户程序 • prompt> vbj Client

More Related