跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

弥补和 COM 的缝隙

发现 Bridge2Java 如何帮助扩展 Java 代码的范围

William F. Phillips 为位于纽约的 Endicott 的 IBM 工作,是从事类似 Bridge2Java 和 DirectDOM 这样的项目。请通过 billphil@us.ibm.com 和 William 取得联系。

简介: Java 平台的有力特征之一就是它面向对象的本质;面向对象语言的好处之一就是它们有助于代码重用。但如果您是一个 Java 程序员想重用不是用 Java 语言写的代码,那怎么办?有了 Bridge2Java ― IBM 的一种 alphaWorks 技术,Java 开发者可以将 COM 对象集成到他们的应用程序。William Phillips 解释它如何做到这一点。请到 讨论论坛和其他读者和作者分享您关于这篇文章的想法。

发布日期: 2001 年 10 月 10 日
级别: 初级
访问情况 : 1204 次浏览
评论: 


实际上,任何编写计算机程序的人都熟悉对象概念。用对象编程的一个主要的好处是一个特别有用的对象,如一个字符格式化程序,能被一个应用程序的很多不同部分利用。如果您把这种哲学用到逻辑结论,就没有理由问为什么不能把应用程序本身看作是对象或被其它应用程序作为对象来使用。这就是设计“组件对象模型”(Component Object Model)或者说 COM 来帮助创建的那种环境。

软件开发者可以使用 COM 的框架来快速、简单地把独立的应用程序改造成大应用程序的工作部分。但一些高级语言,象 Visual Basic 和 Java 语言,不能与 COM 简单建立接口。一个称为 自动控制器的层必需介入 COM 对象和用这些语言写的对象之间。鉴于越来越多的大的应用程序是用 Java 语言写的,需要一种便于集成的工具。Microsoft 所采用的 Java 平台 ― Visual J++,有内置的自动控制器,但是标准 Java 用户没有这个好处。

Bridge2Java 通过在 Java 程序中允许 COM 对象象其它 Java 对象一样使用来解决这个 Windows 问题。在这篇文章里,我将给您一个 Bridge2Java 的高级概述;我同时也提供一个展示如何使用它的示例。如果您愿意了解更多关于 COM 的知识,请查看下面的 参考资料部分。

忧愁河上的金桥

一个支持 COM 的程序(也称为 COM 服务器)允许其它程序(也称为 COM 客户机)访问自己的方法和属性的过程称为 自动化。每一个支持自动化的 COM 服务器必须公开一个称为 IDispatch 的特殊接口。通过使用 IDispatch 接口和 Invoke() 方法,一个 COM 客户机可以调用 COM 服务器想公开的任何函数。Bridge2Java 通过用 Invoke() 方法来允许 Java 程序和 COM 服务器通信;这个方法也把值返回给 Java 程序。从 Java 程序员的角度来说,Bridge2Java 允许 COM 对象就象其它 Java 对象一样被 Java 代码"看到"。可以从对象调用函数;数据类型全是 Java 的数据类型;甚至连 COM 事件也被捕获并发送到 Java 程序。

什么是 JNI?

Java 语言的设计者认识到创建 100% 的纯 Java 应用程序是个宏伟的目标。他们也知道事实上,这个目标通常很难达到。随着开发新的 Java 应用程序,开发者经常不情愿丢弃以前写的可能很昂贵或者很难的原码。 Java 的本机接口或者说 JNI,提供了一个由 Java 虚拟机(JVM)出来并进入 JVM 在运行的本机计算机世界的通道(doorway)。通过使用这个通道,Java 程序员可以使用先前昂贵的或者不可能的原码来重写成 Java 代码。JNI 允许本机代码调用 JVM,创建并访问对象,调用对象方法并访问实例变量。这种折中为开发者丢弃了 Java 平台的“写一次,在任何地方运行”这个好处,因为调用的任何本机代码将会被捆绑到特殊的平台。了解更多关于 JNI 的知识,请查看 参考资料获得后续信息。


JNI:基本原理

Java 世界和 COM 世界的边界被用“Java 本机接口”(Java Native Interface(JNI))桥接起来了。只有两个 JNI 调用是必需的:一个是创建 COM 服务器,另一个是处理 Invoke() 方法。只要发生了一次 Java 函数调用就调用 Invoke() ;它事实上是整个“Java 到 COM”过程的要核。然而,如果连接 Java 和 COM 对象和通过 Invoke() 传送一个从 Java 代码到 COM 的调用一样简单,那么 Bridge2Java 将会是一个非常简单的程序。Bridge2Java 的实际工作是在把 Java 变量转变成 COM 能理解的变量类型来完成的。变量称为 VARIANT 并且是包含所有可能类型和指出存储的数据实际类型值的结构。大多数 Java 变量巧妙映射到 VARIANT ― 例如,一个 int 很容易地映射到 VARIANT 中的 VT_I4 类型。实际的困难是在于将象 SAFEARRAYBYREF 值这样的 COM 类型映射到 Java 的等价类型。

转换变量的过程由一个 Java 代理调用开始,该调用创建并批量装入一个自定义建立的 Java 版的 VARIANT ,称为 Jvariant 。这个 Jvariant 能包含所有的 Java 变量类型,再加上一个域,该域指出包含的数据应该被转换成 COM 端的哪种类型。Bridge2Java 中的 SAFEARRAYS 被以 Jvariant 数组形式从 Java 代码传入。Bridge2Java 然后在 COM 端构建适当类型的数组并用输入数组的值批量装入它。如果此数组(或任何其它值)是 BYTEREF ,那么 Bridge2Java 必须能用更新的值替代传入的值。它通过使用数个来自 COM 端的允许更新 Java 数组元素的 JNI 调用之一做到这一点。

图 1 展示 Bridge2Java 如何把 Java 命令传送到 COM 服务器的纵览。


图 1. Bridge2Java 纵览
Bridge2Java 纵览

一个样本应用程序:建桥

使用 Bridge2Java 的第一步是把 COM 服务器的接口、方法和属性转换成 Java 代理对象和方法。这是由代理生成器(包括 Bridge2Java)完成的,并且要求用户为 COM 服务器定位 typelib。( typelib 仅仅是 COM 服务器程序员提供的便利;它为 COM 服务器提供了所有接口、方法和属性的有序清单。)Bridge2Java 代理生成器遍历 typelib,并为它所发现的每一个 IDispatch 接口生成 Java 对象。这样创建的每一个 Java 对象包含来自自 IDispatch 接口的所有方法和属性。属性将被生成为 get_set_ 方法,例如 get_Visible()set_Visible(BOOL visible)

我们的样本应用程序将展示 Java 开发者如何能使用 Bridge2Java 和 COM 调用 Lotus 1-2-3 功能。清单 1 展示了来自代理生成器的片段。这个示例类是用于我们应用程序指向 Lotus 1-2-3 的 IDispatch 接口。(1-2-3 的 typelib 称为 L123TYP.TLB )。

这个示例中有几个重要的事情值得注意。一个是列在文件上部的 cslid ;这是 IDispatch 接口的唯一标识并是 COM 访问注册表找到 Lotus 1-2-3 位置时使用的值。当 Bridge2Java 启动 1-2-3 时,COM 传回一个指向 IDispatch 接口的指针,它将被随后的 Invoke() 调用所利用来和 COM 服务器通信。

“Java 到 COM”过程的另一个重要部分是创建并初始化包含传入值和类型的 Jvariant 类。 invoke_method() 调用通常创建几个 Jvariant ,用于每一个传入的参数。在只返回一个值的情况下, Jvariant 就被隐式地创建并且只传回返回值。

Bridge2Java 也使用所有存在于 invoke_method() 调用的十六进制值。这些值称为 dispids 并且它们唯一标识 _Application 接口中的每一个方法。 Invoke() 使用这些值,连同上面提到的 IDispatch 接口指针和任何必需的 VARIANT ,来唯一定位和调用由这个接口提供的所有方法。


列表 1. Application.java
// Dispatch Proxies 
package Lot123;
import com.ibm.bridge2java.*;
import java.util.Date;
public class Application extends Dispatch implements COMconstants
{
   public static final String clsid = "{29130071-2EED-1069-BF5D-00DD011186B7}";
   public Application() 
   {
      super(clsid);
   }
   public Application(String clsidin) 
   {
      super(clsidin);
   }
   public Application(int IDispatch) 
   {
      super(IDispatch);
   }
   public Application(Object theObject) 
   {
      super(theObject);
   }
   public Application(int canvasHWND, int nullval) 
   {
      super(clsid, canvasHWND);
   }
   public Application(String clsidin, int canvasHWND, int nullval) 
   {
      super(clsidin, canvasHWND);
   }
   public String ExtendedName(Object nametype)
   {
      Jvariant args[] = {new Jvariant(nametype,VT_VARIANT)};
      return invoke_method(args, 0x1000300, DISPATCH_METHOD).StringVal();
   }
   public void Goto()
   {
      invoke_method_void(null, 0x1000304, DISPATCH_METHOD);
   }
   .
   .
   .
   public Object get_Run()
   {
      return invoke_method(null, 0x100ea00, DISPATCH_PROPERTYGET).ObjectVal();
   }
   public void set_Run(Object value)
   {
      Jvariant args[] = {new Jvariant(value, VT_VARIANT)};
      invoke_method_void(args, 0x100ea00, DISPATCH_PROPERTYPUT);
   }
   public String get_ProductVersion()
   {
      return invoke_method(null, 0x14c0211, DISPATCH_PROPERTYGET).StringVal();
   }
   public void set_ProductVersion(String value)
   {
      Jvariant args[] = {new Jvariant(value, VT_BSTR)};
      invoke_method_void(args, 0x14c0211, DISPATCH_PROPERTYPUT);
   }
} 

生成代理之后,现在用户可以写 Java 应用程序来和 COM 服务器会话了。清单 2 展示了一个小的程序,它将启动 1-2-3,把一行写到一个单元格,复制那一行,等待一秒钟,然后不保存地关闭 1-2-3。这是个简单的示例,但是它说明了构建一个更复杂的程序所必需的每一件事。很多示例包括在 Bridge2Java 包中,和其它的一起,该包展示了如何捕获事件并在 Java 画布中描绘 COM 服务器。


列表 2. Quick123.java
// Description: This is a Bridge2Java Lotus 1-2-3 demo.  This demo brings up 
//              1-2-3, writes "This is a test" in the first cell, 
//              copies the first cell to the cell below it, waits 1 second,
//              then quits.
//
// Setup:  None
//
// Author:  Bill Phillips
//
import Lot123.*;
public class Quick123
{
    public static void main(java.lang.String[] args) {
        Application app;
        Ranges ranges;
        Document doc;
        Range rangeA1, rangeA2;
        try
        {
            // Set up the com environment.
            com.ibm.bridge2java.OleEnvironment.Initialize();
            // Create a new document (which starts 123).
            doc = new Document();
            // Get the application object.
            app = new Application(doc.get_Parent());
            // Make the application visible.
            app.set_Visible(new Boolean("true"));
            // Open the Range workbook.
            doc = new Document(app.NewDocument());
            // Get all of the ranges.
            ranges = new Ranges(doc.get_Ranges());
            // Get cell A1.
            rangeA1 = new Range(ranges.Item(new String("A1")) );
            // Set the contents of cell A1
            rangeA1.set_Contents("This is a test");
            // Get cell A2.
            rangeA2 = new Range(ranges.Item(new String("A2")) );
            // Copy the contents of cell A1 into cell A2
            rangeA1.QuickCopy(rangeA2);
            // Wait one second
            Thread.sleep(1000);
            // Quit 123 without saving
            app.Quit("false");
        } catch (com.ibm.bridge2java.ComException e)
        {
            System.out.println( "COM Exception:" );
            System.out.println( Long.toHexString((e.getHResult())) );
            System.out.println( e.getMessage() );
        } catch (Exception e)
        {
            System.out.println("message: " + e.getMessage());
        } finally
        {
            app = null;
            com.ibm.bridge2java.OleEnvironment.UnInitialize();
        }
    }
}


总结

COM 提供了一种体系结构,该体系结构允许在真实组件级别使用程序而不用关心它们的版本、写程序所用的语言甚至它们运行的位置。Java 平台提供了一个易于临时用户学习和使用的语言。Bridge2Java 跨越了复杂仍强大的 COM 世界和 Java 语言的简单性之间的鸿沟。

Bridge2Java 当前是 IBM alphaWorks 技术,这意味着可以下载并评估它,与开发小组分享您的想法。您也可以获取许可把它用到您自己的产品中。单击下面 参考资料中关于 alphaWorks 的 Bridge2Java 页的链接。


参考资料

  • 您可以参阅本文在 developerWorks 全球站点上的 英文原文.

  • 请参与关于这篇文章的 讨论论坛

  • 您可以下载并评估 IBM alphaWorks 的 Bridge2Java 包


  • About.com拥有一套关于 COM 和相关技术的资源。


  • 获得更多关于 JNI 的信息,请查看关于这个主题的 Sun 站点


  • 请查看如何用 COM 体系结构使用 IBM 的 MQSeries 中间件


  • 电子商务工具”(2001 年 1 月 的合作者世界)解释了许多不同类型的对象,包括 Java 和 COM 如何能在单独的异构企业系统中共存。


  • 您在为运行 OS/390 的大型机编程吗? 获得更多关于在这样的环境中如何使用 JNI 的信息。


  • 开发人员 Java 技术专区获得更多 Java 技术。

关于作者

William F. Phillips 为位于纽约的 Endicott 的 IBM 工作,是从事类似 Bridge2Java 和 DirectDOM 这样的项目。请通过 billphil@us.ibm.com 和 William 取得联系。

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Java technology
ArticleID=53465
ArticleTitle=弥补和 COM 的缝隙
publish-date=10102001
author1-email=billphil@us.ibm.com
author1-email-cc=billphil@us.ibm.com

标签

Help
使用 搜索 文本框在 My developerWorks 中查找包含该标签的所有内容。

使用 滑动条 调节标签的数量。

热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。

我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。

使用搜索文本框在 My developerWorks 中查找包含该标签的所有内容。热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。