作者 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的问题开始有微妙的转变,人们不再问“你喜欢哪个平台?”,而开始问一个更有趣而且有力的问题:“我怎样才能把两个平台结合使用?”
完全列出可用的将两个丰富的平台进行整合的方法超出了本文的范围。我们可以来看几个比较吸引人的方式,并且在理念和代码上体会一下。
方案:从WPF到WCF,再到Java Web Service
关于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服务代理与JSP
自从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参考,第三版》。
方案:Office与Spring
狂热的开源分子听到这一方案可能有些难以接受。毫无疑问,在过去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本身的功能仍然完整保留。
其他方案
当然,以上并非全部可用方案,只是最近几次讨论和客户会谈中想到的一些。其它方案还有:
- 使用连接Java的Cmdlets的PowerShell:PowerShell将在不久的未来成为Windows上最重要的管理工具,而围绕它搭建一系列通过JMX与Java服务器沟通的Cmdlets简直轻而易举。这样一来,我们可以非常轻松地建立检查IIS或其它Java服务器的状态与性能的脚本,并将结果显示为美观的图表(就像PowerGadgets中cmdlets所显示的一样),或者通过方法调用打开、关闭系统的部分功能。
- 使用Speech Server的Java:Vista中加入了一些新的语音合成功能,而微软的Speech Server提供了Java平台中从未有过的强大的语音识别功能。随着我们对残障人士用户的日益关注,语音和通过语音与用户交互(通过电话或者电脑话筒)将带来越来越高的吸引力。
- 调用Java的Workflow操作:Windows Workflow具有一个预编译操作,用于调用Web Service,但如之前所说,Web Service在特定环境下有用,却未必能满足所有交互要求。自定义操作可以利用其它Java/.NET交互方式与Java组件沟通。
- 内置Workflow的Java:Workflow引擎最强大的特性,在于它可以嵌入多种环境之中,如ASP.NET。当然,它也完全可以嵌入Java系统,比如Tomcat或Jetty, 从而开启Workflow的“信息工人”访问性,与Java和.NET网络应用程序连接。
- 与Java交互的Windows Mobile设备:随着移动设备世界越来越火热,微软的Windows Mobile平台成为使手写软件能够在Smartphone等移动设备上运行的可选方案之一。现在移动设备越来越普及,IT企业都希望把它们与自己的各种环境相整合,其中自然包括Java。有时这种通讯通过Web Service完成,但有时需要更加有针对性的通讯手段,比如使用商业工具JNBridge Pro等ZeroC’s ICE。
越来越多的开发人员开始意识到结合使用.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:
- Java 5企业版:最近由上一个名字“Java2企业版”更改而来,通常被简称为J2EE。该标准是总合性标准,覆盖了许多其它企业级标准。虽然不太准确,许多人将J2EE与EJB同等使用。
- Enterprise JavaBeans (3.0):EJB是描述软件组件寻求生命周期,布署连接与分布式事务管理的容器标准。可以将EJB视为事务处理框架系统的逻辑Java后续版本。
- JDBC (4.0):标准Java调用层对关系数据库API接口的实现。不同的厂商有不同的“提供者”(驱动)来实现JDBC API,使开发人员与实际的数据库实现方式隔离(理论上属于松散耦合)。
- Servlets (2.5):Servlet标准描述了布署用于搭建动态HTTP页面的软件组件的标准。一个Servlet实质上是一个Java类及扩展的特殊接口。
- Java Server Pages (2.2):JSP页面是针对输出的创建Servlet的方式,与ASP或ColdFusion类似。JSP文件会被解释为Java源文件(servlets)并进行编译。
- 远程方法调用:RMI是Java版本的对象远程过程调用(ORPC)堆栈。RMI有两种,一种使用本地Java传输格式,称为“RMI/JRMP”;另一种使用OMG的CORBA传输格式,称为“RMI/IIOP”。官方推荐的J2EE系统使用RMI/IIOP, 但实际使用更广的是RMI/JRMP。
- Java信息服务(1.1):JMS是对任意Java平台消息服务(不是指电子邮件)的标准访问API。
- JavaMail:JavaMail是对任意电子邮件服务(SMTP, POP3, IMAP, and so on)的标准访问API。
- Java命名与目录接口:对任意提供命名与/或目录服务,比如LDAP的标准访问API。
- Java WebStart:通过HTTP URL本地调用Java程序并存储在客户端机器上以备将来使用(必要时可以脱机使用)的布署技术。
- Java API for XML Binding(2.0):JAXB是自动进行Java到XML或XML到Java翻译的标准API。
- Java API for Web Services (2.0):JAXWS是Java基于XML的服务的标准API。JAXWS最初名为“Java API for XML RPC (JAX-RPC)”, 在2.0版中这个名字遭到反对,因为JAXWS加入了更加面向消息的实现方式。
- Spring (2.0):实际是提供轻量级Java组件服务的开源容器(又称“POJOs”,“Plain Old Java Objects”的缩写)。通常被视为J2EE的代替品。
- Swing:官方名称为“Java基础类”。Swing是跨平台的构建富客户端界面的工具包。因为其目的在于创建平台兼容的外观,许多绘图和显示逻辑都是自己编写的。
- 标准窗口工具包(SWT):开源的Eclipse编译器的核心显示技术。SWT与Swing不同的是使用本地系统级UI功能来完成绘图与显示逻辑。
.NET:
- Windows分布式编程框架(WCF):以前的代码名称为“Indigo”。WCF展现出微软的下一代任意程序之间通讯的API,从消息队列到安全/可靠/事务型服务,以及WS-* web service。
- Windows表示层编程框架(WPF):以前的代码名称为“Avalon”。WPF展现出微软的下一代表示层,充分利用近年来业界在图形显示卡上的巨额投资所获得的成就。WPF代码有两种利用方式,一种是在每个.NET开发实例中调用并编译,或者使用名为“XML应用程序标记语言”(XAML)的XML进行定义,从而编译在应用程序之中,或者通过HTTP请求传送至IE7中进行动态显示。WPF的子集WPF/E用于非IE的浏览器。
- Windows工作流编程框架(WWF):正如其名,提供工作流编程支持。
- Windows表单:.NET对传统Windows界面功能进行的包装(User32.dll和GDI32.dll).
- 活动目录(AD):AD是用于企业级“带名称资源”部署的目录服务,比如用户和服务器。AD也有一个用于单个应用程序的较轻量级版本“ADAM”。
- ASP.NET:创建动态Web/HTTP功能的.NET实现方式。ASP.NET管道提供面向编程的ASHX和面向输出的ASPX两种表单,用于生成最终用户可视内容,同时还有面向编程的Web service(ASMX)。
- ADO.NET:对关系数据库实现的调用级接口API。不同的厂商有不同的“提供者”(驱动)来实现ADO.NET API,使开发人员与实际的数据库实现方式隔离(理论上属于松散耦合)。
- .NET远程调用:.NET版本的对象远程过程调用(ORPC)技术。
- Microsoft消息队列(4.0):MSMQ是微软的消息服务,对所有版本的Windows都可用(4.0与Vista一同提供).
- COM+/企业服务:COM+是为“管理下的应用程序”(这是原始的名称)提供事务与生命周期服务的容器。.NET组件使用System.EnterpriseServices命名空间调用COM+。
- Microsoft Office:世界上安装最多的办公室生产效率软件系列,主要包括Microsoft Word, Microsoft Excel, Microsoft PowerPoint and Microsoft Outlook。