您现在的位置是: 软件 > 开发者网络 > 程序方舟 > Java专栏 > 正文


-Win xp中的多种网络
-试验试验试验试验
-用Freehand实现位图矢量化
-网络电话面面观

探索 CORBA 技术的应用领域
2001-08-20· ·Dave Bartlett ··转自IBM DeveloperWorks 中国网站

上一页  1 2  


  服务器

  现在生成的文件必须在服务器上开始工作,用这个服务器实现我们的接口。所幸的是,大部分探测是适合我们的要求的,但别高兴得太早 -- 还有许多工作要做;就是说,所有这些文件都必须用在正确的地方。

  让我们从 add() 方法的实现开始。(您可以下载完整的 SimpleCalcSvr.java 文件。)

清单 3. SimpleCalcSvr.java -- add() 方法
SimpleCalcServant extends calculatorPOA {
  public int add(int x, int y) {
    return x + y;
  }
}

  请注意,我们的实现类扩展了已生成的类 calculatorPOA。从客户机发来一个请求时,该请求通过 ORB 进入 skeleton,skeleton 最终将调用 SimpleCalcServant,来完成请求并启动响应。我们的接口很简单,所以我们的实现也很简单。

  服务器其余部分的实现,涉及如何围绕这个接口实现来设置 CORBA 体系结构,由于可移植性和灵活性方面的原因,许多这些调用要按 CORBA 规范执行。

  我们需要完成的第一项任务是,详细说明要使用哪一个 ORB,然后予以初始化。下面的代码(文件 SimpleCalcSvr.java 的第 18 行到第 29 行)处理此任务:

清单 4. SimpleCalcSvr.java -- 初始化 ORB
java.util.Properties props = System.getProperties();
props.put("org.omg.CORBA.ORBClass",
"com.ooc.CORBA.ORG");
props.put("org.omg.CORBA.ORBSingletonClass",
"com.ooc.CORBA.ORBSingleton");

org.omg.CORBA.ORB orb = null;
// 初始化 ORB
orb = org.omg.CORBA.ORB.init(args, props);


  初始化 ORB 时,需要准确地告诉它哪一个类将用作 ORBClass,哪一个类将用作 ORBSingleton 类。我们的实现将不考虑这些,但所有相关的探测则都将考虑这些。正如我前面所说的,这种情况下,我使用的是 Object Oriented Concepts, Inc. 的 Orbacus ORB,而 OOC 类在那两个 props.put() 调用中已给出。一旦填入了属性,props 就只作为一个参数传递给 ORB.init() 方法。实际情况可能不是这样;如果我们要把这个服务器移到另一个 ORB,不希望为服务器重新编码。所以,在理想情况下,我们宁愿改变一个配置文件,使之指向另一个 ORB 类,然后直接重新启动。

  现在,ORB 已经到位并已初始化,并且实现也已经到位,只是尚未创建,此时,需要为实现创建一个完善的生存地点,而这可不像听起来那么容易,在一个分布式环境中,各个实现要求的环境可能略有不同。可以赋予实现许多特征。实现既可以是单线程的,也可以是多线程的;既可以是具有高度可伸缩性的对象池,也可以是单元素。这许多不同的服务器特征已产生了可移植对象适配器 (POA)。POA 使我们可以创建完善的环境,供我们的实现在其中驻留。所有符合 2.3 规范的 ORB 都会有一个根 POA,所有其它 POA 都是从根 POA 创建的。在这个简单示例中,我已将实现专用的代码分解为它自己的方法 runcalc()。

  为实现创建一个环境将是我们的第一项任务,所以必须设置一个 POA。本来,CORBA 服务器使用基本对象适配器 (BOA),但是每个供应商的 BOA 都不一样,在最新版本的 CORBA 规范中,POA 已完全取代了 BOA。

  清单 5. SimpleCalcSvr.java -- 设置 POA
// 从始终存在的 rootPOA
// 设置可移植对象适配器
org.omg.PortableServer.POA rootPOA =
    org.omg.PortableServer.POAHelper.narrow(
    orb.resolve_initial_references("RootPOA"));

org.omg.PortableServer.POAManager manager =
    rootPOA.the_POAManager();

  从标题和定义可以看出,这是一个简单的示例。使用根 POA 而不创建新的 POA,将使事情变得简单。POA 管理器是一种封装了 POA 处理状态的对象,所以,我们使用 POA 管理器,将发给 servant 的请求排队。

  还需要实例化实现

清单 6. SimpleCalcSvr.java -- 实例化实现
// 创建计算程序接口的 servant
SimpleCalcServant calcSvt = new SimpleCalcServant();
calculator calc = calcSvt._this(orb);

  按照 CORBA 2.3 规范,所有 skeleton 均提供一个 _this() 方法,该方法使 servant 能得到目标 CORBA 对象的对象引用,servant 正是用目标 CORBA 对象来与这些请求相关联的。

  完成实现的实例化以后,就必须把机制放到适当的位置,以便客户机能够找到它们。有许多不同的方法和服务可用来找到满足接口请求的对象。CORBA Service 定义 Naming Service 和 Trader Services,来专门帮助客户机查找对象,以处理请求。也可以通过方法调用来传递对象。

  在这个示例中,我们将使用所有方法中最直截了当的一种 — 将对象引用写入一个文件,该文件将由客户机选取。对于所有的 ORB 来说,创建一个对象引用的字符串表示,或者反过来,创建由字符串到对象的引用,都是必备的功能。

清单 7. SimpleCalcSvr.java -- 编写对象引用
// 将对象引用写入一个文件
PrintWriter refstr = new PrintWriter(
new FileWriter("calcref.ior"));
refstr.println(orb.object_to_string(calc));
refstr.close();


  最后要做的一件事,就是激活 POA,使客户机请求开始排队,并强制服务器输入其事件循环,以接收这些传入的请求。

清单 8. SimpleCalcSvr.java -- 激活 POA
// 使实现成为可用
manager.activate();
System.out.println("SimpleCalcSvr is running!");
orb.run();


  客户机

  如果您考虑一下正在发生的事件的机制,就会明白客户机和服务器实际上正是互为映像的。客户机将所有的参数打包以创建一个请求,然后以它自己的方式来发送这个请求。服务器只是将请求中的参数解包,执行运算,将返回值和输出参数打包,然后向客户机发回响应。客户机则将返回值和输出参数解包,然后继续处理。这样,客户机打包什么,服务器就解包什么,反之亦然。

  这意味着您将会看到客户机和服务器具有相似的结构。客户机还必须创建并初始化一个 ORB。它可以是我们正在使用的 ORB,也可以是另一个供应商提供的 ORB;但是,不能是任意的 ORB,而应该是支持 IIOP 的 ORB,IIOP 是由对象管理集团 (OMG) 定义的、基于 TCP/IP 的互操作性协议。如果您的 ORB 比较旧,那么请小心,它可能无法与其它 ORB 通话。

  首先,我们以相同的方式创建 ORB,就像创建服务器一样。(您可以下载完整的 SimpleCalcClient.java 文件。)

清单 9. SimpleCalcClient.java -- 初始化 ORB
java.util.Properties props = System.getProperties();
props.put("org.omg.CORBA.ORBClass",
"com.ooc.CORBA.ORG");
props.put("org.omg.CORBA.ORBSingletonClass",
"com.ooc.CORBA.ORBSingleton");

org.omg.CORBA.ORB orb = null;
// 初始化 ORB
orb = ORB.init(args, props);

  看起来眼熟?应该是这样,它看起来与服务器完全一样。现在,客户机已经连接到了一个 ORB 之上,但我们的目标是调用一个服务,而这个服务是在系统中别的地方提供的,需要找到能响应请求的对象。在这个示例中,这意味着要从创建于服务器上的文件中获取一个对象引用。为了找到计算程序服务器,需要取得存储在这个文件中的对象引用的字符串版本,然后把它转换成对象引用,通过这个对象引用就可以进行调用了。

  清单 10. SimpleCalcClient.java -- 获取对象引用
System.out.println("Getting reference from string...");
BufferedReader in = new BufferedReader(
new FileReader("calcref.ior") );
String ior = in.readLine();
in.close();

calculator calc = calculatorHelper.narrow(
orb.string_to_object(ior));

  请注意,这里使用了由 IDL-to-Java 编译器生成的 calculatorHelper 类。calcref.ior 文件含有一个对象引用,而不是含有计算程序引用。calculatorHelper 类有一个 narrow 方法,可用来将抽象类型集中到特定的计算程序类型。

  仔细看一看计算程序 calc,它表示计算机空间中另外某个地方的一个服务器。最后必须做的一件事,就是调用 calc 上的方法 add()。

  清单 11. SimpleCalcClient.java -- 调用 add()
System.out.println( calc.add(2,3) );

  结论

  已经讨论了很多内容,不过请想一想,都学到了什么。我们的客户机与服务器是完全隔离的,客户机不知道服务器在什么样的硬件上运行,使用的是什么操作系统,它是用什么语言编写的,它是不是多线程的,还有,它位于何处 — 是在隔壁,还是距离半个地球之遥。它只知道一点,即如果它调用 calc 中的 add(),就会得到可以指望的响应。

  提供服务的情形全都是这样,电话或电力公司也是如此。当您拿起电话的时候,您所期望的是听到拔号音,然后您的呼叫能畅通连接,您并不在乎电话是通过光缆传输的还是通过卫星转发的,同样的情况在信息产业中也正在成为现实。多亏有了 OMG 和这个基本结构,我们才得以加进这个既简单而又非常有说服力的例子。

  下个月,我们将稍微深入地发掘一下,看一看发生在表面现象之下的 IIOP 的神奇力量。


上一页  1 2  

【责任编辑:方舟】
【发表评论】【关闭窗口】
■ 相关内容
 使用UML编写Java应用程序
 Web 应用程序模型及其Java实现之第一部分
 规则与自由:为何选择CORBA和Java技术
 XP 精华:何使 Java 项目获得更大成功
 JavaBean与EJB有何不同
感谢 访问天极网,如果您觉得该文章涉及版权问题,请看这里!