使用 xsd:anyType 表示服务接口中的 XML 文档
作者:Sean Brydon、Smitha Kangath 及 Sameer Tyagi
问题描述
开发者在设计 Web 服务交互环境(客户端和服务在其中交换 XML 文档)时,需要选择一种表示服务接口中的 XML 文档的类型。类型的选择会带来多方面的影响。选定的类型将在 WSDL 服务描述文件和服务实现代码中反映出来。在 Java[TM] 2 Platform, Enterprise Edition(J2EE[TM] 平台)1.4 应用程序中,XML 文档(如订单或发票)是使用基于 XML 的远程过程调用的 Java API (JAX-RPC) 交换的。在设计服务接口时,选择表示 XML 文档的类型时有许多可供考虑的策略:
- 使用字符串表示 XML 文档
- 使用结构定义的类型表示 XML 文档
- 使用 XML 片段表示 XML 文档(使用 xsd:anyType)
- 使用 XML 片段表示 XML 文档(使用 xsd:any)
- 使用附件打包 XML 文档
选择使用 xsd:anyType 表示面向文档的服务中的 XML 文档时,此解决方案重点考虑的是设计因素。有关所有这些策略的描述,请参见面向文档的服务项。
解决方案
让我们考虑一些在将 XML 片段与 xsd:anyType 结合使用表示客户端和服务之间交换的 XML 文档时出现的问题。
策略:将 XML 片段与 xsd:anyType 一起使用来表示 XML 文档
此策略将 XML 业务文档表示为 XML 片段。对于服务 Java 接口和实现,这意味着此类型会被指定为 SOAPEelement。在 JAX-RPC 中,如果 XML 结构类型没有标准的 Java 映射,则它会被映射为 XML 文档片段。XML 到 Java 的映射使用接口 javax.xml.soap.SOAPElement 来表示 wsdl:operation 元素的 Java 映射中的类型消息部分。对于 WSDL 文件,您可以选择使用 xsd:anyType 作为表示 XML 文档(如订单)的类型。
让我们考虑一下如何在 WSDL 文件中使用 xsd:anyType。在 XML 结构中,xsd:anyType 是对基本类型的一种抽象表示,所有简单类型和复杂类型都来自基本类型。anyType 类型对数据内容没有任何限制或约束,因此很有可能像使用其他结构类型一样使用 anyType。可以使用 anyType 在服务客户端和服务端点之间传递 XML 文档。JAX-RPC 实现需要将 xsd:anyType 映射到 javax.xml.soap.SOAPElement。因此依赖于 anyType 数据类型的一个最大缺点是,JAX-RPC 规范没有为 xsd:anyType 定义标准的 Java 映射,因此不是 J2EE 1.4 中的所有 JAX-RPC 实现在将该类型映射到 SOAPElement 时行为结果相同。实际上,JAX-RPC 的实现是否支持 xsd:anyType 是可选的。使用 anyType 还会出现可移植性和互操作性的问题。使用 XSD:anyType 的一个好处是,可以将操作和有效负载放在一起进行传递。这在创建一个接受使用同一操作的多种文档类型的多态处理程序时,是有用的。例如,请考虑这样的单一服务:它接收一组不同类型的订单,其中每种类型都具有不同的结构。
使用 anyType 时要注意的一点是,它强制客户端将 xml 文档(如订单文档)封装在父元素中,此元素与 WSDL 为该参数元素类型指定的名称相匹配。有关更多详细说明,请参见服务接口中的使用 anyType 的设计文档,但是我们在这里还需简单地了解一下。请考虑这样一个示例方案:其中 Web 服务接口具有提交订单 XML 文档的操作,并具有一个类似代码示例 1 的 WSDL 文件。请注意,此 WSDL 文件会声明一个名为 BusinessDocumentRequest <element name="BusinessDocumentRequest" type="anyType"/>
的元素,然后该元素会映射到接收为 submitPO 操作输入的消息。因此,如果已为订单定义了结构,则从本质上说,它将在父元素内进行嵌套,这样传输到服务的 xml 就会与订单结构有所不同。例如,订单文档将需要封装在父元素内,如代码示例 2 所示。这对开发者来说是不方便的,同时 XML 文档不能保持其与结构定义的完整性。
<types>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="urn:AnyTypePurchaseOrderService">
<complexType name="submitPO">
<sequence>
<element name="BusinessDocumentRequest"
type="anyType" />
</sequence>
</complexType>
...
<element name="submitPO" type="tns:submitPO"/>
...
</schema>
</types>
...
<message name="AnyTypePurchaseOrderServiceSEI_submitPO">
<part name="parameters"
element="ns1:submitPO"/>
</message>
<portType name="AnyTypePurchaseOrderServiceSEI">
<operation name="submitPO">
<input
message="tns:AnyTypePurchaseOrderServiceSEI_submitPO"/>
...
</operation>
</portType>
代码示例 1:使用 anyType 的服务的 WSDL 中的代码片段
将 anyType 作为文档类型的 WSDL 文件的服务结果是客户端需要将代码写入该文件中。因此,如果客户端具有一个订单结构,它还需要创建一个与该结构匹配的订单文档,然后将该文档封装在父元素中。因为 anyType 实际上定义了在 WSDL 中命名的元素的数据类型,在 SOAP 正文中传递的业务文档位于 WSDL 标识的该元素中。(例如,在代码示例 2 中,PurchaseOrder 在 BusinessDocumentRequest 元素中。)这意味着必须在 WSDL 中标识被传递的文档的根元素,或者在元素中正确构造该文档或将该文档立即封装在元素中。
<BusinessDocumentRequest>
<PurchaseOrder>
.... the rest of purchase order
elements here ...
</PurchaseOrder>
</BusinessDocumentRequest>
代码示例 2:在 WSDL 中指定的名为 BusinessDocumentRequest 的元素内嵌套订单 XML 的样例
除了使用 xsdanyType 外,还使用 xsd:any 表示服务接口中的 XML 文档设计某些服务。让我们看一下使用 xsd:any 替代策略的情况,并将其与使用 xsd:anyType 进行比较。在 XML 结构中,<any> 元素允许通过结构未指定的元素扩展复杂类型。在 JAX-RPC 中,使用 xsd:any 结构类型元素来表示元素通配符时,复杂类型的映射将像通常那样映射到 JavaBeans[TM] 组件,但是,如果 <any> 元素在 maxOccurs 等于 1 时,会产生一个名为 _any 的其他属性映射到 javax.xml.soap.SOAPElement(如果 maxOccurs 大于 1,则它会映射到 javax.xml.soap.SOAPElement 的数组中)。可以利用 <any> 元素的映射以 document-literal 格式在线路上传输 XML 文档。已经在 JAX-RPC 1.1 中实现了将 xsd:any 映射到 SOAPElement 的标准化定义,这意味着您可以依赖在不同的应用服务器上使用的这一类型。另一个优点是,xsd:any 可以扩展在结构中未定义的任意内容的现有元素。这意味着尽管在 WSDL 中命名了某元素,并且传递的业务文档出现在线上元素的内部,但是 Web 服务及其客户端仍然能够处理完成的 XML 文档并维护结构的完整性,无须包含作为这些元素下的文档内容(anyType 策略就有所不同了)。XML 文档仍然保持其与结构定义的完整性。
除了在此策略中将 WSDL 中的 xsd:any 或 xsd:anyType 用法进行比较以外,我们还要考虑一些其他问题。通过使用 XML 文档片段表示 XML 业务文档(如 PurchaseOrder)的策略,客户端或端点的开发者需要使用 SOAPElement API 进行文档处理。这些 API 不是熟知的 API,因此使用起来不是很方便。如果开发者需要使用 Java 对象处理文档,则需要编写代码以绑定到与文档(如 PurchaseOrder)对应的那些 Java 对象。这可能会影响某些性能。
参考资料
有关本主题的详细信息,请参阅以下资料:
© Sun Microsystems 2005。Java BluePrints Solutions Catalog 中的所有内容受版权保护,未经 Sun Microsystems 的明确书面许可,不得在其他产品中发布。