大概五年前,微软发布了.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 编码很复杂,但标签中列出的是一个.jsp 页面——其中的代码会向底层数据库查询所有的产品与项目 ID,并在获得新版本列表时刷新显示(Office 会自动覆盖旧版本列表,位置在 C:\Program Files\Common Files\Microsoft Shared\Smart Tag\Lists directory)。Office 会每 5 分钟刷新一次智能标签列表,因为智能标签列表将自己定义为可更新的 (因为其中有上述的 和标签), 因此它会每 5 分钟进行一次更换查询 (间隔可以在标签中定义). 也就是说,每当新的产品和项目被加入数据库时,智能标签都会自动更新,而无需人工操作。
智能标签的能力远远超出这个简单的例子所展现的。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。
查看英文原文: Best of Both Worlds: Java & .NET for Fun & Profit (PDF 文档)
评论