Arjen Poutsma谈Spring Web Services 2011-11-26
http://www.infoq.com/cn/articles/arjen-poutsma-spring-ws
http://www.infoq.com/articles/arjen-poutsma-spring-ws;jsessionid=33A73F5FE6E82810211187E9A2B66811
ArjenPoutsma谈SpringWebServices
作者StefanTilkov译者俞黎敏发布于2007年12月6日
领域语言&开发,企业架构主题Java,SOA,Web服务标签Spring框架,XML,Web服务标准,SpringWebServices
SpringFramework作为一种更轻量化的“企业”框架选择,它在Java开发人员中非常流行。最新增加的其中一项是SpringWebServices子项目,根据网站上的说法,是“专注于创建文档驱动(document-driven)的WebServices,[并]帮助推动契约优先(contract-first)的SOAP服务开发,允许利用操作XMLpayloads的多种方法之一来创建灵活的WebServices。
InfoQ的StefanTilkov和SpringWebServices的创建者ArjenPoutsma进行了一次对话,谈到了整体的WebServices,并特别讨论了Spring的支持。
InfoQ:您能向我们介绍一下您自己吗?
ArjenPoutsma(以下简称AP):我是Interface21的高级顾问。我现在从事企业应用程序开发已经13年了,刚开始用C++,后来用Java,有两年我还从事过一些.NET的开发。我大约四年前开始对WebServices感兴趣,并且建议了一些大公司如何去实现它们。
在刚过去的一年半中,我一直在从事SpringWebServices项目,这是SpringPortfolio中的一个产品,专注于创建契约优先、文档驱动的WebServices。近来,我们已经发布了SpringWebServices的Milestone3,我们还计划在2007年的第二季度发布1.0。
InfoQ:构建SpringWebServices的主要动机是什么?Java还没有足够的WebServices框架吗?
AP:在我作为顾问的工作中,我遇到过WebServices有严重问题的客户。例如,他们想要维护一个Service契约的多个版本,或者直接处理得到的XML,而不用先转化成对象。当时,现成的SOAP堆栈专注于使“SOAP化”现有的Java类变得更容易,而不是正确地完成它:从编写一个Service契约开始,并编写可以处理得到的XML的类。虽然有可能进行契约优先的WebService设计,但也不容易。就像整个SpringPortfolio所做得那样,SpringWebServices使得以正确方式进行变得更加容易,并向人们展示了如何使WebServices符合他们现有的架构。
InfoQ:许多人认为,将XML转化成对象再转化回来,这正是他们在WebServices堆栈中寻求的功能。您对此似乎并不认同——能解释一下吗?
AP:我认为开发人员应该要能选择以他们想要的方式来处理得到的XML,XML封送(marshalling)就是一种(方便的)方式。
然而,XML封送有几个问题。其中一个就是有些封送引擎十分脆弱,例如,当它们遇到它们不能识别的XML时就会爆炸,这真的不太符合Postel法则(发送时严谨,接收时宽松)。
另一个问题是,在面向对象的语言如Java或者C#,和基于树的语言如XML之间有许多结构上的差别。例如以对象图为例。我们假设有一个Person类,它有一个spouse(配偶)属性,以便spouse的spouse指向同一个对象。用XML表示这种关系并没有标准的方法;你只能求助于定制机制。另一个问题是数据类型的:在Java中我们有一个java.util.Map,它一般有两个实现(HashMap和TreeMap)。XMLSchema(XSD)没有字典结构的数据类型,因此当我将一个HashMap封送给XML时会发生什么呢?
我希望从中得到某种XML,但是当我再次解封它时,我就可能得不到与当初相同的HashMap了。
因此没有透明封送这回事,就像没有透明的对象持久化一样。你必须指示封送引擎如何将你的对象转化成XML,就像你指示一个对象/关系映射工具在SQL和对象之间进行转化一样。这就是我更喜欢称它为对象/XML映射而不是封送的原因,因为这显然也要注意对象/XML阻抗不匹配的问题。
InfoQ:您对JAX-RPC/JAX-WS怎么看?
AP:JAX-RPC发布时,人们只是把WebServices当成远程过程调用(RemoteProcedureCalls)的另一种方法。规范的名称明显说明了这一点。在那些年里,我们发现像RPC这样进行WebServices的行为驱动方式,并不是最佳的前进方式。它导致客户端和服务之间更加紧耦合,并且完全忽略了像延时、失败、缺乏共享的内存访问等东西。像消息这样的数据驱动法反而更适合。
JAX-WS是JAX-RPC的一种改进。我特别喜欢的东西是ProviderAPI,它提供了一种处理得到的SOAP请求的消息关注方式。我不喜欢的是,规范的其余内容仍然十分关注RPC,并且强烈依赖Java5特性,即使有很好的Java1.4时也一样。好像目前出现的每一个JSR都必须定义一对注解。外面仍然有许多Java1.4甚至1.3的用户,他们无法使用泛型(generic)、枚举(enum)和注解(annotation),当你使用上述的ProviderAPI时这三种都需要。
InfoQ:是什么东西使SpringWebServices变得如此独树一帜,为什么我要用它而不用Axis、XFire或者ActiveSOAP?
AP:SpringWebServices有几个独特的特性。首先,它完全专注于契约优先的WebService设计。这基本上意味着你必须编写自己定义XML消息的XSDSchema。你可以引用WSDL中的Schema(虽然SpringWebServices也可以从XSD中生成WSDL),并将它用于验证。值得关注的事情是,当人们使用契约优先的开发风格时,他们在WebServices方面的许多互通性问题就消失了。这就是契约优先之所以被普遍当作是一种最佳实践的原因。你基本上是在设计一个XMLAPI:你用Java实现这个API的事实,只是没有客户会在意的一个实现细节而已。
其次,SpringWebServices提供了契约和实现之间的一种松耦合:没有wsdl2java工具将契约直接连接到一个类;而是用你喜欢的任何方式(DOM、SAX、StAX,甚至XML封送技术如JAXB、Castor、JIBX或者XMLBeans),实现处理得到的XML的端点(endpoint)。你将得到的请求映射到端点的方式,完全由你自己决定;默认情况下,我们提供基于消息内容的映射,或者SOAPActionHeader。主要的思想是,你不用处理方法调用,而是处理XML消息。
最后,你可以从Spring项目中期待这些特性:
WS-Sercurity实现与AcegiSecurity整合;
JMS支持使用Spring2的MessageDrivenPOJO;
主客户端类(WebServiceTemplate)提供一种类似于JdbcTemplate的API;
XML封送支持完全独立于WebServices(以便它可以用在其他的设置中);
它适用于JDK1.4及以上版本(虽然也有特定于Java5的特性)。
InfoQ:因此在默认情况下,我的应用程序是从消息传送XML的?以哪种形式——以DOM树、流、Reader还是其他形式?
AP:应用程序传送一个XML输入抽象进行读取,并且一个输出抽象写入(相应为javax.xml.transform.Source和javax.xml.transform.Result)。这样你的代码就不依赖任何特殊的XML处理API了。这个机制的实际实现取决于你选择使用的消息工厂。我们给SOAP提供了两种工厂:默认的是基于SAAJ的(javax.xml.soap,J2EE1.4的一部分),它在底层使用DOM。对于更大的消息,我们支持Axis2的AXIOM,它使用一种StAX流。
InfoQ:SpringWebServices如何处理WS-*标准——你能开箱即用地支持它们中的任何一种标准吗?
AP:SpringWebServices支持SOAP1.1和1.2、WS-Security,并支持在XSDSchema里面生成1.1WSDL,WS-Addressing计划在1.0中发布。我基本上趋向于等到有足够的用户请求它时才会实现一种标准。目前为止,人们似乎对现状十分满意。
InfoQ:你对WS-*的前景整体上怎么看?
AP:嗯,有一部分我喜欢,有一部分不喜欢。我喜欢SOAP,我认为它是跨传输器发送XML消息的一种很好的方式。我不太喜欢WSDL,因为它提供了一个几乎是面向对象的WebService模型,包含操作、接口等等,它不太适合SOAP。因为SOAP没有操作,它只是一种XML消息。从这一点上来说,我更喜欢SSDL(SOAPServiceDescriptionLanguage)。
我喜欢WS-Addressing的理念:把地址信息放在SOAPHeader里面,但我不喜欢它有五个不同的不可兼容的版本在使用。基本上,如果有人告诉你他们的服务支持WS-Addressing,你就需要问:“你是支持2004年3月的版本,还是2004年8月的版本,或者其他的版本呢?”
最后,我认为WS-Security十分有用。它没有试图去重新发明轮子,而是在必要的地方使用XML-DSig和XML-Enc。
InfoQ:你对REST有什么评价,以及你认为SpringWebServices将来总有一天会支持它吗?
AP:我喜欢REST,我喜欢它通过把自身基于HTTP上,来解决我们在WS-*中面临的许多问题的方式,这是一种公认的技术。也就是说,我认为REST就像SOAP一样受限制,或者更甚。在编写一个REST服务时,你对于你有什么资源、你的哪些数据格式支持它们(REST不仅仅是关于XML的!),以及它们意味着什么等等,都必须了然于胸。所有这一切也都必须清楚地写成文档,HTTP规范不足以达到这个目的。
许多人说他们在做REST,但是他们实际上在做的只是被DonBox称之为POX(PlainOldXML)的事情。POX是一种XML消息协议,在这里,你只要发送XML消息,而不需要用SOAP包将它封装起来。SpringWebServices已经支持这一点了。
至于“真正”的REST支持,我认为我们未来将会支持它,但不是在SpringWebServices的1.0版本中。它与SOAP和POX非常不同,例如,并不总是有XML消息进来。我们不想通过从HTTP请求中创建一个XML消息,将它射入3毫秒后要在那里被再次解析的管道中,以此来支持REST:这成本简直太高了。我们而是将把REST支持放在Spring-MVC中,它是Spring的Web框架。
InfoQ:非常感谢!
注:SpringWebServices产品可以从Spring网站上下载,Arjen还在维护一个关于WebServices的博客。
查看英文原文:ArjenPoutsmaonSpringWebServices