作者 Ted Neward译者 张立楠 发布于 2007年7月13日 上午2时19分
大概五年前,微软发布了.NET Framework,这是Java/J2EE和.NET平台上最流行的几个“专家级”产品之一。从那以来,我一直在讲Java/.NET的协调性。无论我在哪里讲,都有一个出现频率极高的问题(来自我的朋友,参会人员,咨询客户等等)。
问:说实话,我不会传出去的。你最喜欢哪一个?是Java还是.NET?
我并不偏好哪一个,两个我都同样喜欢。说实话这个答案不太容易令人信服。所以我通常用得最多的回答是下面这个。
答:看情况。
我们的业界已经被深深地分成了两边,核心问题是:“你使用哪种平台?你是Java开发者,还是.NET开发者?”从这个问题的相关讨论来看,有人可能会认为这是目前最主要的话题,其中往往伴随着激烈的争吵和辩论。暂且不管传统的“征用权”与“皇权侵略”的争论,以及那些主流媒体认为与伊拉克和东北非的动荡同样重要的各种文章。如果计算其中情感的力量,世界上最重要的问题莫过于你编程时主要使用Eclipse还是Visual Studio。
讽刺而有趣的是这些争论毫无重点。Java和.NET虽然有些方面存在冲突,实际上它们是两种截然不同的平台,存在各自的优点和缺点。两种平台都是从各自所在的社区和文化中开发(或产生)出来的,因此它们通常针对不同的问题,使用不同的方法和实现手段。
而且近年来它们本身已经开始出现分歧。以前的各种会议上,我可以说,人们选择Java或者.NET更多是出于文化因素,“任何你通过其中一个可以做到的事,都可以通过另一个在同样的工作量下实现”。现在不是这样了。以前说.NET 1.0/1.1与Java相当是可以的,而现在它们已经开始不同的发展方向,实现它们独有的创新和用户群的反馈。Java社区目前致力于各种语言与平台之间的合作,比如说与微软最新版本.NET 3.0,两个截然不同的平台间进行的标准统一。于是关于Java和.NET的问题开始有微妙的转变,人们不再问“你喜欢哪个平台?”,而开始问一个更有趣而且有力的问题:“我怎样才能把两个平台结合使用?”
完全列出可用的将两个丰富的平台进行整合的方法超出了本文的范围。我们可以来看几个比较吸引人的方式,并且在理念和代码上体会一下。
关于Java/.NET的协调性,最常用的例子大概就是广泛使用的Web Service,通常使用Windows表示层编程框架(WPF)或WinForms界面,结合Windows分布式编程框架(WCF)将数据实际传送到另一端以某种Java容器形式保存的Java Web Service,可能是WebLogic,WebSphere,Spring,Tomcat,等等。搭建Web Service的酸甜苦辣有许多文章进行了描写,所以在此不必多费笔墨。但如果将Web Service作为CORBA或.NET远程控制(或者说分布式对象技术)的扩展,会大量消耗额外的工作和精力。使用恰当的服务,能够创建比希望换掉的分布式对象工具更松散的耦合,尤其是能够更轻松地突破我们所讨论的技术壁垒。WCF和JAX-WS的核心观念都是“传输消息,而非对象”,只有表面层的一些API使它们看上去比较像RMI或.NET远程控制。因此在搭建Web Service时可以利用它们良好的协调性。本方案最明显的优点是每种技术都集中于它所专长的部分。前端界面使用平台独有的技术,因此可以发挥全部性能;而后端使用的开发平台则因性能和可测量性著称。
自从SQL Server 2005发布以来,一种新的消息处理方式诞生了,这就是SQL Server服务代理,用于搭建基于消息的通讯程序。这种方式基于SQL Server的数据引擎实现(服务代理中的队列均为高效数据表,顶层以简单的外壳包装),并且具有足够的强壮性,能够用于事务型和有序传输保证。服务代理为开发人员提供强制消息平台,尤其是在那些已经有数据库的数据中心里。然而使用Java访问SQL Server服务代理和访问其它JDBC数据库同样简单。Java应用程序,——无论是客户端程序,还是服务器处理引擎,——都可以通过微软SQL Server 2005 JDBC驱动(可以在MSDN上免费下载)访问服务代理,或者向服务代理程序发送信息,以及必要的时候接收来自服务代理的信息。
在本示例中,一个虚拟的公寓大楼需要在网上生成维护人员的工作顺序,以便住户不必打电话要求办公室来安排传票(从而花费办公室人员三倍的宝贵时间来填写纸质表格;事实上办公室人员很讨厌对住户的要求视而不见)。
因此,解决方案提供者构建了一个简单而轻便的网络系统,其中只有两个JSP页面:一个供住户将传票放入服务中,另一个供维护人员收集传票并浏览。系统的目的很简单,第一个页面收集传票信息,包括问题描述,公寓本身,住户姓名和电话等,然后将信息排入ServiceBroker的队列中,等待维护部门访问第二个JSP页面来获取待处理的任务列表。
至于实现方式,从Java的角度来说,使用ServiceBroker和使用其它以JDBC为驱动的数据库并没有很大区别。要把消息送入队列中,只需要一个对SQL Server实例的JDBC调用,就像传统方式写一个INSERT或者UPDATE语句一样:
获取消息的方式更为直接,使用SQL Server的RECEIVE关键字:
或许会有许多人提出疑问,这里为何使用SQL Server服务代理,而不使用对Java更加友好的JMS实现方式,比如开源的ActiveMQ或商业的SonicMQ。要回答这个问题,可能会回到以往Java/.NET兼容性问题中常用的答案上:“我们这样做是迫不得已。”更有说服力的答案是:为了“会话”。ServiceBroker提供了JMS标准中前所未有的会话功能。与事务型消息传递相类似,会话表现为往返传递的一系列信息,每个会话都有唯一的标识符。本质上而言,这是连续RPC调用和独立的单独路径信息的结合。它提供了消息通讯系统中通常难以具备的可靠性和健壮性。在我们上面的虚拟示例中,会话的使用有些随意,它在长时间运行的商业流程中也同样可以非常强大。上面代码中的标识符conversationId在每个ServiceBroker实例中是唯一的,标识本次用户交互中消息的集合(本例中只有一个)。
另一个可能出现的问题是为何使用JSP来编写网页界面,而不使用ASP.NET; 对于非Windows平台而言,这仍然是个“迫不得已”的选择。但JSP有其独到之处,就是用于生成美观界面的丰富的工具和预编译组件。如果我们讨论所有的Java/Web space工具,比如Struts, Seam, WebWork, JSF, Google Web Toolkit等等,都使Web开发体验与传统ASP.NET的拖放方式截然不同。(对不熟练的Web开发人员,拖放方式或许很适用,但熟练者都有自己喜欢的方式,并且觉得ASP.NET的设计与他们的方式相冲突。)关于SQL Server服务代理更详细的讨论,请见勃切明与苏利文的《SQL Server 2005开发人员指南》。关于Servlet和JSP更详细的讨论,请见杰森?弗克纳和凯文?琼斯的《Java Servlet与JSP》。关于JDBC更详细的讨论,请见费舍尔、艾利斯和布鲁斯的《JDBC教程与API参考,第三版》。
狂热的开源分子听到这一方案可能有些难以接受。毫无疑问,在过去10年中,微软的Office提供了世界上最流行的办公室生产效率软件系列。世界上被安装次数最多的软件可能就是Office,其次是Windows本身。
近年来,Java社区在讨论富客户端程序,抛弃以往的点击、等待、阅读的网络模式,寻求更具有交互性的用户体验。AJAX实现了其中的部分功能,代价是需要编写大量额外的脚本代码以应对不同的浏览器或浏览器版本(而有些浏览器禁止使用AJAX)。Java社区中有人将Eclipse富客户端平台视为解决法宝,有人推崇JavaWebStart, 或者Adobe Flex等等。
最好的富客户端应该基于终端用户机器上已经安装的软件。因为Office是安装范围最广的,尤其是在企业范围内的机器,何不利用Office的优秀扩展接口,将Office用作富客户端,在后端使用Java?
为了出版Office对象模型和使用方法相关的书籍,文章,教程和参考文档,我们不知道已经砍伐了多少森林。算上.NET和未使用的COM,Office接口非常复杂,在此列举也没有意义。本文将集中于Office扩展模型之一,智能标签,以及使用XML定义文件来识别Office文档中词汇(通常是在Excel和Word中使用,不过PowerPoint和Access也可以使用)并提供下拉菜单供用户跳转到某个网站的智能标签列表。
在这种情况下,虚拟环境很简单:一家在线电子经销商发现他们的在线宠物商店非常火爆(他们终于解决了通过与世界各地的宠物商店谈判后水路邮递宠物的问题),而他们使用Spring JPetStore范例编写的首页现在需要处理各种复杂的计算,遵守公司内财务人员和市场人员提出的商业规则。简单的订单都留给首页处理,但复杂一些的订单将由销售人员通过面谈或电话完成。
复杂的计算法则需要复杂的处理语言来实现,而这正是Excel的用武之地——财务人员和市场人员都可以在Excel中使用公式语言来自己编写法则,——我们要做的下一步是将Excel中的数据表格显示为Spring前端首页。此时第一步只需要从Excel文档中识别出订单和产品号,然后显示出智能标签将销售人员指向Spring编写的网站中准确的页面。(进一步的改进可以在保存数据表格时自动下订单,或者在试图销售没有库存的宠物时弹出警告信息等。)
用简单的XML文件实现这些,要比使用Java和.NET代码更加实用。幸好URL天性灵活,智能列表标签不必介意URL所指向的网站其实是用Spring编写的。如下所示的智能标签会每天刷新,随时显示出新的商品ID。(“看啊,孩子们,我们现在有雪貂的库存!”)
简单来说,我们需要建立两个智能标签。一个用来识别产品ID(FL-DSH-01等等),另一个用来识别项目ID(EST-16, EST-17等等). 我们只需要在URL中使用ID值来替换{TEXT}占位符并访问网站。这里的ID编码很复杂,但<updateurl></updateurl>标签中列出的是一个.jsp页面——其中的代码会向底层数据库查询所有的产品与项目ID,并在获得新版本列表时刷新显示(Office会自动覆盖旧版本列表,位置在C:\Program Files\Common Files\Microsoft Shared\Smart Tag\Lists directory)。Office会每5分钟刷新一次智能标签列表,因为智能标签列表将自己定义为可更新的(因为其中有上述的<updateable></updateable> 和<autoupdate></autoupdate>标签), 因此它会每5分钟进行一次更换查询(间隔可以在<updatefrequency></updatefrequency>标签中定义). 也就是说,每当新的产品和项目被加入数据库时,智能标签都会自动更新,而无需人工操作。
智能标签的能力远远超出这个简单的例子所展现的。Visual Studio Tools for Office API可以让.NET开发人员在所需要的智能标签后面编写任意形式的代码,所以在激活智能标签时向JPetStore引擎进行远程调用(使用Web Service调用或其它商业工具,例如JNBridge或者ZeroC’s ICE)来获取当前库存量等操作也完全可以实现。
智能标签并不是Office整合能力的极限。文档表格可以通过自定义为任何Java系统充当用户界面,Excel的公式语言可以通过自定义公式进行扩展(当然可以通过本地JVM使用Java API或者远程调用Java系统),等等。而且方式不止一种——必要的时候,Word和Excel都可以装入Eclipse RCP,或者说,任何一个COM自动对象都可以这样使用,而Word和Excel本身的功能仍然完整保留。
当然,以上并非全部可用方案,只是最近几次讨论和客户会谈中想到的一些。其它方案还有:
越来越多的开发人员开始意识到结合使用.NET和Java的优势,因此越来越多的方案将得到实施。Java和.NET社区都在进行更多的创新,因此双方都会更加开放而诚恳地考虑如何更好地解决客户的问题。毕竟最后不论你喜欢哪种技术,我们的目的都是一个:为客户提供解决方案。
Ted Neward是Neward & Associate公司的主要负责人,该公司是致力于使用Java、.NET、XML及其它必要工具的企业系统的咨询公司。他从1991年起开始使用C++,从1997年起开始使用Java,从2000年起开始使用.NET。他兼任PluralSight的.NET讲师,独立教授Java,在世界Java和.NET社区中的各种会议上发言,为MSDN、InfoQ和TheServerSide撰写文章,并著有《果壳中的C#》,《SSCLI本质》与《有效的企业级Java》等书籍。这些信息记录于网站http://www.tedneward.com。
需要注意,本文的读者通常对两种技术中的一个比较熟悉,而不是都熟悉。因此,下面将列出两种平台的主要构成。这里并不是要对每种组件进行介绍,或者进行详细的列举。读者可以通过文末的参考文献寻找更多信息。
Java:
.NET: