在详细介绍如何重用错误定义之前,让我们先看一个可重用错误定义的示例。清单 1 显示了 XML 模式,清单 2 显示了 WSDL。
清单 1. 用于可重用错误定义的模板模式
<
xsd:schema
targetNamespace
="urn:SchemaTemplates"
xmlns:xsd
="http://www.w3.org/2001/XMLSchema"
>
<
xsd:complexType
name
="Fault"
>
<
xsd:sequence
>
<
xsd:element
minOccurs
="0"
name
="reason"
type
="xsd:string"
/>
</
xsd:sequence
>
</
xsd:complexType
>
</
xsd:schema
>
清单 2. 可重用错误定义的模板 WSDL
<wsdl:definitions
targetNamespace="urn:WSDLTemplates"
xmlns:tns="urn:WSDLTemplates"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:types>
<xsd:schema
targetNamespace="urn:WSDLTemplates"
xmlns:tns="urn:WSDLTemplates"
xmlns:t="urn:SchemaTemplates"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:importnamespace="urn:SchemaTemplates"schemaLocation="Fault.xsd"/>
<xsd:elementname="op1"type="tns:op1"/>
<xsd:complexTypename="op1">
<xsd:sequence>
<xsd:elementname="input"type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:elementname="op1Response"type="tns:op1Response"/>
<xsd:complexTypename="op1Response">
<xsd:sequence>
<xsd:elementname="output"type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:elementname="fault"type="t:Fault"/>
</xsd:schema>
</wsdl:types>
<wsdl:messagename="op1RequestMsg">
<wsdl:partname="op1Parameters"element="tns:op1"/>
</wsdl:message>
<wsdl:messagename="op1ResponseMsg">
<wsdl:partname="op1Result"element="tns:op1Response"/>
</wsdl:message>
<wsdl:messagename="faultMsg">
<wsdl:partname="fault"element="tns:fault"/>
</wsdl:message>
<wsdl:portTypename="Interface">
<wsdl:operationname="op1">
<wsdl:inputname="op1Request"message="tns:op1RequestMsg"/>
<wsdl:outputname="op1Response"message="tns:op1ResponseMsg"/>
<wsdl:faultname="fault"message="tns:faultMsg"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:bindingname="Binding"type="tns:Interface">
<soap:binding
style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operationname="op1">
<soap:operationsoapAction=""/>
<wsdl:inputname="op1Request">
<soap:bodyuse="literal"/>
</wsdl:input>
<wsdl:outputname="op1Response">
<soap:bodyuse="literal"/>
</wsdl:output>
<wsdl:faultname="fault">
<soap:faultuse="literal"name="fault"/>
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
<wsdl:servicename="Service">
<wsdl:portname="Port"binding="tns:Binding">
<soap:addresslocation="http://www.example.org/"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
如果您定义的 WSDL 符合此模式,则可以获得可重用的错误定义。但是可重用性具有许多级别。您没有必要遵守此处介绍的全部可重用性。让我们看一下这些级别。
WSDL 内重用 是本地级别的重用:即 WSDL 文件中的重用。要实现 WSDL 内重用,请避免不必要的关联;特别是,避免将操作名称放入错误名称中。这听起来非常容易,但是一些工具可创建此类错误名称。例如,可能将消息名称生成为 op1_faultMsg。使用工具和图形编辑器可以非常容易地完成许多繁锁的工作,但是它们生成的内容有时可能不是您需要的。如果错误定义包含操作名称,那么在创建新的操作(例如 op2),并需要重用 op1 的错误时,在 op2 中引用 op1_faultMsg 看起来就有些奇怪了。您可以创建名为 op2_faultMsg 的另一个 WSDL 消息,它可引用 op1_faultMsg 引用的同一模式元素,但这是不必要的额外开销。如果将错误的消息名称与操作名称分离,则可以重用该消息,并且看起来也不感到陌生(请参见清单 3)。
.
.
.
<
wsdl:operation
name
="op2"
>
<
wsdl:input
name
="op2Request"
message
="tns:op2RequestMsg"
/>
<
wsdl:output
name
="op2Response"
message
="tns:op2ResponseMsg"
/>
<
wsdl:fault
name
="fault"
message
="tns:faultMsg"
/>
</
wsdl:operation
>
.
.
.
WSDL 间重用 是 WSDL 之间的重用,其中多个 WSDL 可以使用同一错误定义。这里需要避免两种情况:
- 显然,在 WSDL 的类型部分中不能定义您的错误定义。在 WSDL 类型部分中直接定义的任何内容仅对该 WSDL 可视。其他 WSDL 不可重用这些内容。
- 第二种情况比较难,需要考虑到编程语言的映射。请看一下错误类型。因为
fault包含单一字符串字段,您可能更愿意采用简单的路由,并将字符串直接放入错误元素中,而不是通过t:Fault获得该字符串。某些工具可创建此类错误(请参见清单 4)。
清单 4. 简单的错误定义
.
.
.
<
xsd:schema
...
>
.
.
.
<
xsd:element
name
="fault"
type
="xsd:string"
/>
</
xsd:schema
>
.
.
.
<
wsdl:message
name
="faultMsg"
>
<
wsdl:part
name
="fault"
element
="tns:fault"
/>
</
wsdl:message
>
.
.
.
当重用模式元素和模式类型时,请考虑 WSDL 要映射的编程语言。语言映射(如 Java™ API for XML-based RPC (JAX-RPC))以直接的方式将模式类型映射到语言构造。但是如何映射元素并不总是显而易见的。对于 JAX-RPC,错误定义可映射为一个异常类。如果使用类型定义错误,则从该错误的类型名称和命名空间映射该异常的名称和包。如果仅将错误定义为一个元素,则从消息名称映射异常的名称,从消息的命名空间映射数据包(请参见清单 5)。因此,错误定义仅在消息的封闭命名空间中可重用,没有普遍的可重用性。您可以定义重用现有错误元素的另一个错误消息,但是 JAX-RPC 仍将其映射为另一个异常;它不重用现有异常。
清单 5. 清单 4 中 WSDL 的 Java 签名
public String op1(String input) throws RemoteException, WSDLTemplates.FaultMsg; |
重用的最后一个级别更抽象一些。按以往方法定义一个错误,它不仅是一种错误,而且是一种数据类型。当错误数据必须位于 SOAP 错误的外部时,这特别有用,。例如,如果您在处理批操作时。在简单的操作中,您将有一组输入和一组输出。此操作的批量版本将包含输入集的数组和输出集的数组。如果操作的非批量版本也可以抛出错误,则应通过一种方法将错误数据插入输出数组。在定义与本文中类似的错误时,此操作非常容易。清单 6 和清单 7 显示了一个批量示例。它从清单 1 和清单 2 中 XML Schema Definition (XSD) 和 WSDL 的基础上构建,并添加一个称为 batchOp1 的 op1 批量版本以及它的其他数据类型。
清单 6. 用于批量操作错误的 XSD
<
xsd:schema
targetNamespace
="urn:SchemaTemplates"
xmlns:tns
="urn:SchemaTemplates"
xmlns:xsd
="http://www.w3.org/2001/XMLSchema"
>
<
xsd:complexType
name
="Fault"
>
<
xsd:sequence
>
<
xsd:element
minOccurs
="0"
name
="reason"
type
="xsd:string"
/>
</
xsd:sequence
>
</
xsd:complexType
>
<
xsd:complexType
name
="Response"
abstract
="true"
/>
<
xsd:complexType
name
="NormalResponse"
>
<
xsd:complexContent
>
<
xsd:extension
base
="tns:Response"
>
<
xsd:sequence
>
<
xsd:element
name
="response"
type
="xsd:string"
/>
</
xsd:sequence
>
</
xsd:extension
>
</
xsd:complexContent
>
</
xsd:complexType
>
<
xsd:complexType
name
="FaultResponse"
>
<
xsd:complexContent
>
<
xsd:extension
base
="tns:Response"
>
<
xsd:sequence
>
<
xsd:element
name
="fault"
type
="tns:Fault"
/>
</
xsd:sequence
>
</
xsd:extension
>
</
xsd:complexContent
>
</
xsd:complexType
>
</
xsd:schema
>
<
wsdl:definitions
targetNamespace
="urn:WSDLTemplates"
xmlns:tns
="urn:WSDLTemplates"
xmlns:wsdl
="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap
="http://schemas.xmlsoap.org/wsdl/soap/"
>
<
wsdl:types
>
<
xsd:schema
targetNamespace
="urn:WSDLTemplates"
xmlns:tns
="urn:WSDLTemplates"
xmlns:t
="urn:SchemaTemplates"
xmlns:xsd
="http://www.w3.org/2001/XMLSchema"
>
<
xsd:import
namespace
="urn:SchemaTemplates"
schemaLocation
="Fault.xsd"
/>
<
xsd:element
name
="op1"
type
="tns:op1"
/>
<
xsd:complexType
name
="op1"
>
<
xsd:sequence
>
<
xsd:element
name
="input"
type
="xsd:string"
/>
</
xsd:sequence
>
</
xsd:complexType
>
<
xsd:element
name
="op1Response"
type
="tns:op1Response"
/>
<
xsd:complexType
name
="op1Response"
>
<
xsd:sequence
>
<
xsd:element
name
="output"
type
="xsd:string"
/>
</
xsd:sequence
>
</
xsd:complexType
>
<
xsd:element
name
="batchOp1"
type
="tns:batchOp1"
/>
<
xsd:complexType
name
="batchOp1"
>
<
xsd:sequence
>
<
xsd:element
name
="input"
type
="xsd:string"
maxOccurs
="unbounded"
/>
</
xsd:sequence
>
</
xsd:complexType
>
<
xsd:element
name
="batchOp1Response"
type
="tns:batchOp1Response"
/>
<
xsd:complexType
name
="batchOp1Response"
>
<
xsd:sequence
>
<
xsd:element
name
="output"
type
="t:Response"
maxOccurs
="unbounded"
/>
</
xsd:sequence
>
</
xsd:complexType
>
<
xsd:element
name
="fault"
type
="t:Fault"
/>
</
xsd:schema
>
</
wsdl:types
>
<
wsdl:message
name
="op1RequestMsg"
>
<
wsdl:part
name
="op1Parameters"
element
="tns:op1"
/>
</
wsdl:message
>
<
wsdl:message
name
="op1ResponseMsg"
>
<
wsdl:part
name
="op1Result"
element
="tns:op1Response"
/>
</
wsdl:message
>
<
wsdl:message
name
="faultMsg"
>
<
wsdl:part
name
="fault"
element
="tns:fault"
/>
</
wsdl:message
>
<
wsdl:message
name
="batchOp1RequestMsg"
>
<
wsdl:part
name
="batchOp1Parameters"
element
="tns:batchOp1"
/>
</
wsdl:message
>
<
wsdl:message
name
="batchOp1ResponseMsg"
>
<
wsdl:part
name
="batchOp1Result"
element
="tns:batchOp1Response"
/>
</
wsdl:message
>
<
wsdl:portType
name
="Interface"
>
<
wsdl:operation
name
="op1"
>
<
wsdl:input
name
="op1Request"
message
="tns:op1RequestMsg"
/>
<
wsdl:output
name
="op1Response"
message
="tns:op1ResponseMsg"
/>
<
wsdl:fault
name
="fault"
message
="tns:faultMsg"
/>
</
wsdl:operation
>
<
wsdl:operation
name
="batchOp1"
>
<
wsdl:input
name
="batchOp1Request"
message
="tns:batchOp1RequestMsg"
/>
<
wsdl:output
name
="batchOp1Response"
message
="tns:batchOp1ResponseMsg"
/>
</
wsdl:operation
>
</
wsdl:portType
>
<
wsdl:binding
name
="Binding"
type
="tns:Interface"
>
<
soap:binding
style
="document"
transport
="http://schemas.xmlsoap.org/soap/http"
/>
<
wsdl:operation
name
="op1"
>
<
soap:operation
soapAction
=""
/>
<
wsdl:input
name
="op1Request"
>
<
soap:body
use
="literal"
/>
</
wsdl:input
>
<
wsdl:output
name
="op1Response"
>
<
soap:body
use
="literal"
/>
</
wsdl:output
>
<
wsdl:fault
name
="fault"
>
<
soap:fault
use
="literal"
name
="fault"
/>
</
wsdl:fault
>
</
wsdl:operation
>
<
wsdl:operation
name
="batchOp1"
>
<
soap:operation
soapAction
=""
/>
<
wsdl:input
name
="batchOp1Request"
>
<
soap:body
use
="literal"
/>
</
wsdl:input
>
<
wsdl:output
name
="batchOp1Response"
>
<
soap:body
use
="literal"
/>
</
wsdl:output
>
</
wsdl:operation
>
</
wsdl:binding
>
<
wsdl:service
name
="Service"
>
<
wsdl:port
name
="Port"
binding
="tns:Binding"
>
<
soap:address
location
="http://www.example.org/"
/>
</
wsdl:port
>
</
wsdl:service
>
</
wsdl:definitions
>
batchOp1 返回 Response 的数组。Response 是一种抽象类型,因此,您必须使用具体的扩展填充该数组。Response 数组元素可以包含 NormalResponse 对象或 FaultResponse 对象。
|
尽可能扩展 WSDL 错误定义非常有用。希望您已了解了本文中介绍的操作方式。
本文介绍了如何在WSDL中重用错误定义,包括不同级别的重用策略:WSDL内的重用、WSDL间的重用及对象重用,并探讨了在不同情况下如何有效地实现错误定义的重用。
1776

被折叠的 条评论
为什么被折叠?



