一、jcom简介
据gartner的研究分析,在名列全球前1000名的企业中,大约90%都混合应用了java和windows技术。然而,java技术和微软技术分别提供了丰富但却迥然不同的解决方案,或至少说这两种方案之间的差异是巨大的。
为了解决这一矛盾,sun率先提出了jni解决方案。jni,即java本机接口,是编写java本机方法和把java虚拟机嵌入到本机应用程序中的标准编程接口。java本机接口的主要目的就是保证本机方法库在不同平台上的java虚拟机中的二进制兼容性。使用jni编写程序,就可以很方便地做到程序的跨平台可移植。尽管如此,sun提供的jni解决方案只是底层的api包装,在实际开发中用到大量java/com互操作时,直接从jni级进行开发显然效率并不高。
为此,大大小小的公司甚至个人都试图提供全部或局部的java/com互操作解决方案。例如,weblogic提供的jcom技术,bridge2java(ibm提供的基于java本机接口和com技术,允许把activex对象容易地集成到java环境中),jacozoom(是一个java类库―它允许你在java程序中使用activex控件和activex服务器,基于java本机接口和com技术,允许使用于windows平台上的任何java环境中),j-integra for com(http://j-integra.intrinsyc.com/),还有一个小型的jcom桥接库(http://sourceforge.net/projects/jcom/,它也支持从java中调用com对象,例如excel工作簿,vb的com对象等)。其中,weblogic提供的jcom技术为微软的com对象和java对象提供一个稳定、无缝的机制,让这两种对象可以协同工作。
jcom,即java/com桥,它是一种用软件实现的桥接机制,可以帮助java应用程序快速访问微软的com/dcom组件。而且,微软的com应用程序也可以通过这个机制访问基于java的对象。jcom不仅具有实现相对简单的特点,而且其最吸人的部分在于它的透明性。对java程序员来说,com对象看起来与其他java对象没有什么不同。而对com开发人员来说,远程java对象看起来就象是本机com组件。在这些对象中可以找到jcom运行时刻引擎进行动态类型映射,因此从表面上屏蔽了数据类型间的差异。远程对象的数据类型被动态地转换成调用程序所使用的基元类型。对java开发人员来说,com数据类型表现得就象java基元类型;而对com开发人员来说,java数据类型看起来就象是com数据类型。
本文将重点讨论bea的java/com解决方案。
二、jcom工作原理
jcom声称以双向方式工作,实际只是允许在java和com组件之间,在任意一个方向上通信―java对象可以调用com组件,com组件又可以调用java对象。当然,在这两种不同的分布式组件框架之间,有着两种截然不同的底层体系结构负责线路级通信。在运行时,jcom内部设置了一个双协议栈环境,实现对底层两个彼此独立的基础结构的支持(参考图1)。对于com组件,有一个在dce远程过程调用之上的com/dcom实现。对于java对象,有一个在java远程方法iiop(internet inter-orb)之上的远程方法调用(rmi)实现。调用要通过这些协议栈,并通过内部的协议转换进行处理,内部的协议转换能够有效地屏蔽掉低一级的协议。对于ejb来说,来自com客户的调用看起来就好像是来自java客户的调用。对于com组件来说,来自java客户的调用看起来就好象是来自一个普通的com客户。
jcom提供了能够自动生成更高级别com/dcom代理以及rmi存根的工具。客户程序用com/dcom代理以及rmi存根在这两个不同的基础结构间封装并传送调用。jcom可以设置成本机模式,这样就可以利用本机操作系统的动态链接库,从而减轻dcom的网络负荷,并极大地提高系统性能。
下面看一下java对象如何调用com对象:
|
图1演示了当java对象访问com组件的时候事件产生的标准流程。首先,jcom为要访问的com组件生成―个代理对象,java对象开始调用这个代理对象。然后,代理对象与jcom运行时引擎通信,jcom运行时引擎又把代理对象的消息封装成远程过程调用的com/dcom形式,通过tcp/ip发送到windows环境里的com组件。在最低的一层上,jcom使用服务器上的标准java网络类进行调用。
图1.jcom运行时刻环境 点击看原图
三、使用jcom工具
在实际开发中,除了使用weblogic中的一些配置外,多数情况下还需要使用jcom提供的工具程序。这些程序是jcom的核心,在不同平台间公开对象时,要用这些工具建立、部署所需要的元素。其中,常用的有:com2java、java2com、regjvm、regtlb等。篇幅所限,在此仅介绍后面示例中直接用到的com2java。
com2java的作用是,建立访问com组件所需要的java代理代码模块。
所有的com对象都有与其相关的类型库,类型库可以独立存在,或者在其它文件里,它们定义组件所包含的接口和类。不过,要找到和一个组件相关的类型库并不太容易。这是因为,类型库(扩展名为.tlb或.olb,代表类型库)有可能包含在其它文件里,比如dll文件里,而在visual basic里,类型库则保存在应用程序可执行文件自身中。
找到需要公开出来的com组件所在的类型库之后,要把它交给com2java处理,让com2java生成对应的java类,供java客户一端使用。com2java会扫描类型库,寻找它能找到的所有枚举、com接口以及com类。
下面我们看一下com2java根据类型库里找到的内容为com建立的类。
对于从类型库中找到的每个枚举,会建立一个java接口,里面包含常量声明,每个常量对应枚举中的一个项目。对于从类型库中找到的每个com类,会建立一个对应的java类,类名称与com类相同。这些类是客户程序通常要调用的类。
com2java会为从类型库里找到的每个接口建立java接口和java类。生成的java接口的名称与com接口的名称相同,java类的名称也与com接口的名称相同,只是在类名称最后加上proxy这个后缀,表示这是一个代理类。例如,如果有一个com接口,名字是windowshelper,那么生成的java接口名称就是windowshelper,而实现类(实现这个接口)的名称就是windowshelperproxy。可以想象,生成的java接口能把com接口映射成java可以识别的格式,而生成的对应的java代理类可以访问实现这个com接口的com对象。
其实,除了前面介绍的功能之外,com组件也可以通过com2java生成的java类访问实现这个接口的java对象中的方法。com2java的这种用途是com2java的特殊用法。
com2java既有gui版本,也有命令行版本。可以在\bea\webloogic81\server\bin目录下找到com2java.exe(gui版本)和com2javacmd.exe(命令行版本)。
weblogic server 8.1的发行包中带有大量参考示例,其中有专门供jcom使用的示例,但遗憾的是这些全部的jcom示例,演示的都是用基于com的前端访问weblogic server上基于ejb的后端。故本文中仅提供从java前端访问基于com的后端的示例。
在本例中,我们构建一个简单的银行帐户接口应用程序。在这个程序中,我们用jsp程序从前端访问服务器上com组件里包含的业务逻辑。我们假定在用户计算机上已经安装了weblogic server服务器。
一、建立jsp前端
首先,要为银行帐户应用程序建立jsp前端。为简单起见,我们把表示层和业务逻辑层都一起包含到了bankaccount.jsp应用中(在使用本文源代码时,只需把解压后得到的bankaccount.jsp源文件复制到%weblogic_home%/samples/server/examples/build/exampleswebapp目录下)。第一件需要注意的是,从java的角度来看,引入要调用的com组件时,没有用任何java认识的方法,使用的就是一个正常的java类。访问com组件的所有底层代理机制,从表面来看都被隐藏了。实际开发中,我们一般把业务逻辑从bankaccount.jsp分离出来,以servlet的形式放在中间层;但是在此为了演示的方便性,我们把表示层和业务层都放在jsp文件里了。请参考列表1中的代码片断。
列表1.bankaccount.jsp(在此仅列出主要代码片断)
|
二、建立后端帐户com组件
接下来,要建立后端的银行账户com组件。为了简化,本示例假定和com组件在同一台计算机上运行并且选用visual basic 6.0来创建这里的银行账户com组件。
1.启动visual basic,新建一个activex dll项目。
2.把项目名称修改为account,类名设置为clsaccount。
3.在clsaccount类中建立如下代码:
'定义全局变量 |
4.单击菜单“文件-项目另存为”,把项目保存在d:/myex/jcom/banksamp目录下。
5.在文件菜单中,单击“make account.dll”,建立组件的动态链接库。
三、在服务器上安装com组件
在服务器上安装com需要好几项操作。上面创建的com组件要通过jcom公开给java客户机,然后,java对象即可以象调用其它java类一样调用这个com组件。
1.注册组件
我这里试验用的服务器为windows 2000 server。在windows上注册com组件是非常简单的事情,只需使用下列命令:
regsvr32 account.dll /s
2.设置组件服务
在这个示例中,我们所用的操作系统是简体中文windows 2000 server(以下步骤可能因os的不同而有所不同),可以按如下步骤在计算机上设置组件服务:
1.在“控制面板”上“管理工具”下,打开“组件服务”。
2.在“组件服务”控制台里,依次展开“组件服务”->“计算机”-“我的电脑”,选择“com+应用程序”,在菜单里选择“操作”->“新建->应用程序”,建立一个空的服务器应用程序,应用程序名称为jcom。
3.在“组件服务”里,右键单击刚建立的应用程序上,在菜单中选择属性,在“安全设置”选项卡里选择“仅在进程级执行访问检查”,然后把“调用的身份验证级”设置为“连接”。
4.下一步,打开“jcom”目录下的“组件”目录。把刚刚建立的account.dll组件文件拖动到这个“组件”目录下。
3.用com2java生成代理文件
在设置服务器之前要做的最后一步就是生成jcom中间件,用它把前后端各层连接起来。请遵循如下步骤生成中间件:
1.进入%weblogic_home%/server/bin目录下,运行com2java.exe。
2.选择刚才创建的account.dll作为要扫描的类型库。
3.用com.jcomsample.account作为包名称。
4.单击“generate proxies”,选择一个临时目录,保存程序生成的代理文件。
最后,com2java生成4个代理文件,用于在api一级访问银行账户com组件之用。这4个代理文件分别是_clsaccount.java、_clsaccountproxy.java、clsaccount.java和jintegrainit.java。编译这4个类,把它们放到weblogic server上示例应用程序能够访问到的目录中。
所有与jcom相关的、编译时要使用的类,都保存在/bea/weblogic81/server/lib/weblogic.jar这个文件里。要确保在编译时,在类路径里引用这个jar文件。
在weblogic server上,建立目录结构/beaweblogic81/samples/server/examples/build/exampleswebapp/webinf/classes/com/jcomsample/account,把4个编译好的类都放在这里,以便示例应用程序能够找到它们。
四、weblogic server设置
jcom随weblogic server 8.1一起安装,但是必须通过管理控制台激活。现在要做的是让应用程序能够调用com:
1.打开管理控制台。
2.在左边窗格里,单击server,然后打开examples server。
3.在右边窗格里,单击protocols选项卡,然后jcom选项卡。
4.选中“enable com”复选框。
5.单击apply按钮。
6.重新启动服务器。所做的设置在服务器重新启动后生效。
五、运行银行帐户客户端应用程序
打开浏览器,在地址栏中输入http://localhost:7001/exampleswebapp/bankaccount.jsp。观察实验结果,如果一切正常,你将会得到一个银行帐户接口数据操作表单。
在这个程序中,客户的请求由jsp页面处理,jsp页面通过clsaccount对象调用银行帐户com组件。为了简单起见,在整个会话期间,所有数据都持久保存在com对象中(在实际开发中,后端组件应该把信息缓存到数据库里)。
注意 如果你想修改前面用vb创建的com组件,而且没有设置二进制兼容,那么必须重新运行com2java实用工具,以确保正确的代码同步。
总结
本文在较全面地分析了weblogic server的jcom实现技术之后,通过一个具体实例来说明了jcom的具体使用过程。
其实,java/com互操作是个相当复杂的主题,对市场上提供的各种方案的选用应视具体的环境而定。总之,如果想寻找一个稳定可靠的,而且无缝地在java对象和微软com对象之间通信的机制的话,我建议优先考虑jcom。
闽公网安备 35060202000074号