Arjen Poutsma 谈 Spring Web Services

阅读数:1388 2007 年 12 月 6 日

话题:JavaSOA语言 & 开发架构

Spring Framework作为一种更轻量化的“企业”框架选择,它在 Java 开发人员中非常流行。最新增加的其中一项是Spring Web Services 子项目,根据网站上的说法,是“专注于创建文档驱动(document-driven)的 Web Services,[并] 帮助推动契约优先(contract-first)的 SOAP 服务开发,允许利用操作 XML payloads 的多种方法之一来创建灵活的 Web Services。

InfoQ 的 Stefan Tilkov 和 Spring Web Services 的创建者Arjen Poutsma进行了一次对话,谈到了整体的 Web Services,并特别讨论了 Spring 的支持。

InfoQ:您能向我们介绍一下您自己吗?

Arjen Poutsma(以下简称 AP):我是 Interface21 的高级顾问。我现在从事企业应用程序开发已经 13 年了,刚开始用 C++,后来用 Java,有两年我还从事过一些.NET 的开发。我大约四年前开始对 Web Services 感兴趣,并且建议了一些大公司如何去实现它们。

在刚过去的一年半中,我一直在从事Spring Web Services 项目,这是 Spring Portfolio 中的一个产品,专注于创建契约优先、文档驱动的 Web Services。近来,我们已经发布了 Spring Web Services 的 Milestone 3,我们还计划在 2007 年的第二季度发布 1.0。

InfoQ:构建 Spring Web Services 的主要动机是什么?Java 还没有足够的 Web Services 框架吗?

AP:在我作为顾问的工作中,我遇到过 Web Services 有严重问题的客户。例如,他们想要维护一个 Service 契约的多个版本,或者直接处理得到的 XML,而不用先转化成对象。当时,现成的 SOAP 堆栈专注于使“SOAP 化”现有的 Java 类变得更容易,而不是正确地完成它:从编写一个 Service 契约开始,并编写可以处理得到的 XML 的类。虽然有可能进行契约优先的 Web Service 设计,但也不容易。就像整个 Spring Portfolio 所做得那样,Spring Web Services 使得以正确方式进行变得更加容易,并向人们展示了如何使 Web Services 符合他们现有的架构。

InfoQ:许多人认为,将 XML 转化成对象再转化回来,这正是他们在 Web Services 堆栈中寻求的功能。您对此似乎并不认同——能解释一下吗?

AP:我认为开发人员应该要能选择以他们想要的方式来处理得到的 XML,XML 封送(marshalling)就是一种(方便的)方式。

然而,XML 封送有几个问题。其中一个就是有些封送引擎十分脆弱,例如,当它们遇到它们不能识别的 XML 时就会爆炸,这真的不太符合 Postel 法则(发送时严谨,接收时宽松)。

另一个问题是,在面向对象的语言如 Java 或者 C#,和基于树的语言如 XML 之间有许多结构上的差别。例如以对象图为例。我们假设有一个 Person 类,它有一个 spouse(配偶)属性,以便 spouse 的 spouse 指向同一个对象。用 XML 表示这种关系并没有标准的方法;你只能求助于定制机制。另一个问题是数据类型的:在 Java 中我们有一个 java.util.Map,它一般有两个实现(HashMap 和 TreeMap)。XML Schema(XSD)没有字典结构的数据类型,因此当我将一个 HashMap 封送给 XML 时会发生什么呢?

我希望从中得到某种 XML,但是当我再次解封它时,我就可能得不到与当初相同的 HashMap 了。

因此没有透明封送这回事,就像没有透明的对象持久化一样。你必须指示封送引擎如何将你的对象转化成 XML,就像你指示一个对象 / 关系映射工具在 SQL 和对象之间进行转化一样。这就是我更喜欢称它为对象 /XML 映射而不是封送的原因,因为这显然也要注意对象 /XML 阻抗不匹配的问题。

InfoQ:您对 JAX-RPC/JAX-WS 怎么看?

AP:JAX-RPC 发布时,人们只是把 Web Services 当成远程过程调用(Remote Procedure Calls)的另一种方法。规范的名称明显说明了这一点。在那些年里,我们发现像 RPC 这样进行 Web Services 的行为驱动方式,并不是最佳的前进方式。它导致客户端和服务之间更加紧耦合,并且完全忽略了像延时、失败、缺乏共享的内存访问等东西。像消息这样的数据驱动法反而更适合。

JAX-WS 是 JAX-RPC 的一种改进。我特别喜欢的东西是 Provider API,它提供了一种处理得到的 SOAP 请求的消息关注方式。我不喜欢的是,规范的其余内容仍然十分关注 RPC,并且强烈依赖 Java 5 特性,即使有很好的 Java 1.4 时也一样。好像目前出现的每一个 JSR 都必须定义一对注解。外面仍然有许多 Java 1.4 甚至 1.3 的用户,他们无法使用泛型(generic)、枚举(enum)和注解(annotation),当你使用上述的 Provider API 时这三种都需要。

InfoQ:是什么东西使 Spring Web Services 变得如此独树一帜,为什么我要用它而不用 Axis、XFire 或者 ActiveSOAP?

AP:Spring Web Services 有几个独特的特性。首先,它完全专注于契约优先的 Web Service 设计。这基本上意味着你必须编写自己定义 XML 消息的 XSD Schema。你可以引用 WSDL 中的 Schema(虽然 Spring Web Services 也可以从 XSD 中生成 WSDL),并将它用于验证。值得关注的事情是,当人们使用契约优先的开发风格时,他们在 Web Services 方面的许多互通性问题就消失了。这就是契约优先之所以被普遍当作是一种最佳实践的原因。你基本上是在设计一个 XML API:你用 Java 实现这个 API 的事实,只是没有客户会在意的一个实现细节而已。

其次,Spring Web Services 提供了契约和实现之间的一种松耦合:没有 wsdl2java 工具将契约直接连接到一个类;而是用你喜欢的任何方式(DOM、SAX、 StAX,甚至 XML 封送技术如 JAXB、Castor、JIBX 或者 XMLBeans),实现处理得到的 XML 的端点(endpoint)。你将得到的请求映射到端点的方式,完全由你自己决定;默认情况下,我们提供基于消息内容的映射,或者 SOAPAction Header。主要的思想是,你不用处理方法调用,而是处理 XML 消息。

最后,你可以从 Spring 项目中期待这些特性:

  • WS-Sercurity 实现与 Acegi Security 整合;
  • JMS 支持使用 Spring 2 的 Message Driven POJO;
  • 主客户端类(WebServiceTemplate)提供一种类似于 JdbcTemplate 的 API;
  • XML 封送支持完全独立于 Web Services(以便它可以用在其他的设置中);
  • 它适用于 JDK 1.4 及以上版本(虽然也有特定于 Java 5 的特性)。

InfoQ:因此在默认情况下,我的应用程序是从消息传送 XML 的?以哪种形式——以 DOM 树、流、Reader 还是其他形式?

AP:应用程序传送一个 XML 输入抽象进行读取,并且一个输出抽象写入(相应为 javax.xml.transform.Source 和 javax.xml.transform.Result)。这样你的代码就不依赖任何特殊的 XML 处理 API 了。这个机制的实际实现取决于你选择使用的消息工厂。我们给 SOAP 提供了两种工厂:默认的是基于 SAAJ 的(javax.xml.soap,J2EE 1.4 的一部分),它在底层使用 DOM。对于更大的消息,我们支持 Axis2 的 AXIOM,它使用一种 StAX 流。

InfoQ:Spring Web Services 如何处理 WS-* 标准——你能开箱即用地支持它们中的任何一种标准吗?

AP:Spring Web Services 支持 SOAP 1.1 和 1.2、WS-Security,并支持在 XSD Schema 里面生成 1.1 WSDL,WS-Addressing 计划在 1.0 中发布。我基本上趋向于等到有足够的用户请求它时才会实现一种标准。目前为止,人们似乎对现状十分满意。

InfoQ:你对 WS-* 的前景整体上怎么看?

AP:嗯,有一部分我喜欢,有一部分不喜欢。我喜欢 SOAP,我认为它是跨传输器发送 XML 消息的一种很好的方式。我不太喜欢 WSDL,因为它提供了一个几乎是面向对象的 Web Service 模型,包含操作、接口等等,它不太适合 SOAP。因为 SOAP 没有操作,它只是一种 XML 消息。从这一点上来说,我更喜欢 SSDL(SOAP Service Description Language)。

我喜欢 WS-Addressing 的理念:把地址信息放在 SOAP Header 里面,但我不喜欢它有五个不同的不可兼容的版本在使用。基本上,如果有人告诉你他们的服务支持 WS-Addressing,你就需要问:“你是支持 2004 年 3 月的版本,还是 2004 年 8 月的版本,或者其他的版本呢?”

最后,我认为 WS-Security 十分有用。它没有试图去重新发明轮子,而是在必要的地方使用 XML-DSig 和 XML-Enc。

InfoQ:你对 REST 有什么评价,以及你认为 Spring Web Services 将来总有一天会支持它吗?

AP:我喜欢 REST,我喜欢它通过把自身基于 HTTP 上,来解决我们在 WS-* 中面临的许多问题的方式,这是一种公认的技术。也就是说,我认为 REST 就像 SOAP 一样受限制,或者更甚。在编写一个 REST 服务时,你对于你有什么资源、你的哪些数据格式支持它们(REST 不仅仅是关于 XML 的!),以及它们意味着什么等等,都必须了然于胸。所有这一切也都必须清楚地写成文档,HTTP 规范不足以达到这个目的。

许多人说他们在做 REST,但是他们实际上在做的只是被 Don Box 称之为 POX(Plain Old XML)的事情。POX 是一种 XML 消息协议,在这里,你只要发送 XML 消息,而不需要用 SOAP 包将它封装起来。Spring Web Services 已经支持这一点了。

至于“真正”的 REST 支持,我认为我们未来将会支持它,但不是在 Spring Web Services 的 1.0 版本中。它与 SOAP 和 POX 非常不同,例如,并不总是有 XML 消息进来。我们不想通过从 HTTP 请求中创建一个 XML 消息,将它射入 3 毫秒后要在那里被再次解析的管道中,以此来支持 REST:这成本简直太高了。我们而是将把 REST 支持放在 Spring-MVC 中,它是 Spring 的 Web 框架。

InfoQ:非常感谢!

注:Spring Web Services 产品可以从Spring 网站上下载,Arjen 还在维护一个关于Web Services 的博客

查看英文原文:Arjen Poutsma on Spring Web Services
译者简介:俞黎敏(网名:阿敏总司令),技术顾问,自由撰稿人,开源爱好者,曾经参与 Spring 中文论坛组织 Spring 2.0 Reference 中文版的技术审校和满江红开源组织 Seam 1.2.1 Reference 的中文翻译工作;另外他还翻译了《CSS: The Missing Manual》、《Java Persistence with Hibernate》等书籍,并担任 CSDN、CJSDN、Dev2Dev、Matrix、JavaWorldTW 等技术网站 Java 论坛版主。他的博客是:http://YuLimin.JavaEye.com