内容


WSDL 设计中的 Wrapped Document/Literal 模式的使用

简介

在使用消息的 Document/Literal 样式在 WSDL 中定义一个高度互操作的 Web 服务时,所有服务供应商都要采用一个被称为 Wrapped-Document/Literal 的 “模式”。在 WSDL 中,此模式融合了 RPC/Literal 以及 Document/Literal 消息的最佳功能的优势,通过:

  1. 在 SOAP Message – Feature of RPC/Literal 中插入 SEI(Service Endpoint Interface)操作名称。
  2. 在 W3C XML Schema – Feature of Document/Literal 中完成 SOAP Message 的定义。

WSDL 通过定义其界面、该界面上的操作、传输协议的绑定以及它们可使用的网络地址来描述 web 服务。WSDL 绑定描述了 web 服务如何绑定到消息协议,也就是说,什么消息格式或结构正在与服务进行交换,以及该消息将通过什么样的传输协议发送。如今在 web 服务中最流行的消息协议是 SOAP 消息协议(另一种选择是使用基于 REST 的消息)。对于使用 SOAP 消息协议的 web 服务,绑定的 “样式” 可以是 RPC(Remote-Procedure-Call,远程程序调用)或文档样式。从 Web Service Operation 以及相应的 SOAP Request/Response 消息结构的 Input & Output 消息的 WSDL 定义的观点来看,选定的绑定样式是很重要的。在这两种绑定样式的 WS-I(Web Service – interoperability organization,Web 服务 — 互操作性组织)建议中只支持表示消息的 “Literal”(每一种元素或类型都是架构定义的且序列化遵循 W3C XML 模式的定义)方式。

在消息的 Document/Literal 样式中,存在着一种被称为 Wrapped-Document/Literal 的模式。这只是一种模式,且不是 WSDL 规范的一部分。此模式会在 JSR 224 中提到(JAX-WS:Java API for XML based web services,基于 XML 的 web 服务的 Java API)。

本文为 WSDL 中的此种模式提供了规则且有意强调此模式在 WSDL 设计中的使用。此样式/模式将在以下部分中讨论。

Document/Literal 的规则 — SOAP 消息的 Wrapped 模式样式

在 WSDL 设计期间 “Wrapped” 惯例的规则如下:

  1. 在 WSDL 的输入和输出消息中只有 “一个” 部件定义
    “Wrapped” 是 一种 Document/Literal 形式。定义 WS-I 兼容 Document/Literal 服务时,在您的输入消息中最多只能存在一个主体部件且在输出消息中也只能存在一个主体部件。您*不能*在消息定义中将每种方法参数都定义为一个独立部分。(相反,要在 WSDL “类型” 部分定义参数。)
  2. “Part” 定义是包装器元素
    每个 Part 定义都必须引用一个已定义的参数(不是一种类型,类型用于 RPC)以便使其成为消息的文档样式。可以导入该元素定义或者将其包括在 WSDL 文档的类型部分中。这些元素定义都是 “包装器” 的元素(该惯例的名称)。在这些包装器元素中将输入和输出参数定义为元素结构。
  3. “Part” 元素类型的子元素将成为 SEI 方法参数
    必须将输入包装器元素定义一个复杂类型(一些列元素)。将生成(在 WSDL 上使用代码生成工具时)此序列中的每一个子元素类型作为服务界面中的操作参数。
  4. Input Wrapper Element 名称应与 Operation 名称相匹配
    输入包装器元素的名称在 WSDL 中必须与 web 服务操作名称相同。
  5. <Output Wrapper Element Name> = <Operation Name> + "Response"
    输出包装器元素的名称可能是(但不必是)附有 “Response” 的操作名称(例如,如果操作名称是 “add”,那么输出包装元素就应该称为 “addResponse”)。
  6. 在 WSDL Binding 部分,soap:binding style = "document"
    因为样式是适用于包装模式的 Document/Literal,因此在绑定定义中,soap:binding 应该指定 style=“document”(虽然这是默认值,但可以忽略属性),且 soap:body 定义必须指定 use=“literal”。您不必在 soap:body 定义中指定名称空间或 encodingStyle 属性。

浏览 Which style of WSDL should I use 中的图表来完成此模式的说明。

在下面的清单 1 中,您可以看到与 portType 部分中的操纵名称 “myMethod” 相匹配的包装器元素 “myMethod”。

清单 1. myMethod 的 Document/Literal Wrapped WSDL
<types>
    <schema>
        <element name="myMethod">
            <complexType>
                <sequence>
                    <element name="x" type="xsd:int"/>
                </sequence>
            </complexType>
        </element>
        <element name="myMethod Response">
            <complexType>
                <sequence>
                    <element name="z" type="xsd:int"/>
                </sequence>
            </complexType>
        </element>
    </schema>
</types>
<message name="myMethodRequest">
    <part name="parameters" element="myMethod"/>
</message>
<message name="myMethodResponse">
    <part name="parameters" element="myMethodResponse"/>
</message>
<portType name="PT">
    <operation name="myMethod">
        <input message="myMethodRequest"/>
        <output message="myMethodResponse"/>
    </operation>
</portType>
<binding.../>

SOAP Request Message 如清单 2 所示。

清单 2. myMethod 的 Document/Literal Wrapped SOAP 消息
<SOAP-ENV:Body>
    <myMethod>
        <x>-0</x>
        <y>3.14</y>
    </myMethod>
</SOAP-ENV:Body>

以下是从 WSDL(使用来自 JWSDP 2.0 的 “wsimport” 设备)生成的 Java SEI 的快照。该 WSDL 使用 Document/Literal-wrapped 模式。可以注意到,方法名称将与输入元素名称相匹配。

清单 3. 来自 wsimport 的 Java SEI 运行在 myMethod 的 Document/Literal Wrapped WSDL 上
/**
  *This class was generated by JAXWS SI.
  *JAX-WS RI 2.0-b62-ea3
  *Generated source version: 2.0
  *
  */
  @WebService(name ="PT", wsdlLocation = "PT.wsdl")
  public interface PT {

  /**
  *
  *@param y
  *@param x
  *@return
  *   returns int
  */
  @WebMethods
  @WebResult(name ="z")
  @RequestWrapper(localname = "myMethod", className = "myMethod")
  @ResponseWrapper(localname = "myMethodResponse", className = "MyMethodResponse")

  public int myMethod (
    @WebParam(name = "x", targetNameSpace = "")
    int x,
    @WebParam(name = "y", targetNameSpace = "")
    float y);
}

Document/Literal 的优点 — Wrapped 模式

可根据这种模式考虑以下优点:

  1. web 服务供应商之间普遍认同的 Wrapped-Document/Literal 样式
    Wrapped-Document/Literal 模式提供了高度互操作的 web 服务设计,且在定义 Web 服务时已被服务供应商社区作为事实标准接受。包装模式从 Microsoft® 环境演变而来。鉴于该事实
    1. Microsoft 没有明确支持 RPC-Literal,且
    2. 使用该 wrapped 模式,Microsoft 工具会默认生成 WSDL,

      在涉及到互操作性时,它本质上增加了此样式/模式的受欢迎程度。

      双重优势:
    1. soap:Body 下完整的 SOAP Message 可对架构进行验证,且
    2. 通过仅允许 soap:Body 下的一个子元素,此模式 “总是” 满足 WS-I。

相比于 Web 服务(如 RPC/Literal 或 Document/Literal un-wrapped)中其他消息样式,此模式的高互操作性指标已经在行业中被广泛接受。此外,在开发 web 服务中使用自下而上的方法时,IBM WebSphere® 工具会使用此模式生成 WSDL。

  1. 用于将 SOAP Request “分派” 到适当的 Web 服务提供商的 SOAP Engine 的优点
    因为在解组(XML 到 Java/C# 等)期间,SOAP 引擎具有一个清晰且简单的命名惯例(这与其用于 RPC 样式中是相同的),所以 SOAP 引擎有该模式的优点。这种优点可以在输入 SOAP 请求消息(非 WS-Address)中保存来自匹配参数的额外执行。
图 1. SOAP 消息分派到端点实现
SOAP 消息分派到端点实现
SOAP 消息分派到端点实现

使用这种模式,SOAP 引擎将使用 wsdl:portType 来确定应该分派给 SOAP 消息的界面和方法名称。在具有操作名称的 SOAP 消息中,分派流程的行业 SOAP 引擎先驱(例如,Apache Axis2)具有 soap:Body 下第一个子元素的映射。

Web 服务的部署描述符包含 wrapped 模式上的信息。如果 Web 服务中的两种不同的方法都具有相似的输入参数名称,那么 SOAP 引擎会越来越难于确定确切的操作名称(其中应分派 SOAP 消息)。对于 wrapped 模式来说,就是这样映射操作名称的,对于给定 web 服务来说不存在对不同方法中的不同输入参数名称的其他限制。

  1. 最优方法
    该样式通常被认为是一种最优方法,它可以增强可维护性、理解性、可移植性以及在一定程度上增强性能。在此模式中性能会更好,这主要是由于以下原因 —
    1. 不使用编码(“literal” 的优势)。
    2. SOAP 消息中复杂数据结构的直接分析器和已优化的验证(Document 类型消息的优点)。
    3. 某些测试还声称在 RPC/Literal 上具有更好的性能。
  2. 具有多个输入参数的 web 服务操作的更好选择
    如果您具有在超过一个参数中采用的方法,并希望将其作为 web 服务公开,那么您将面对以下两个受到 WS-I 投诉其中之一 —
    1. RPC/Literal
    2. Wrapped-Document/Literal。

您无法使用 unwrapped-Document/Literal ,因为在 SOAP Message 中 soap:Body 下多个子元素都不被 WS-I 所允许。在 RPC/Literal 上的 Wrapped-Document/Literal 的优点是 soap:Body 下的全部消息都是架构定义的,并可在架构分析器的帮助下进行验证。在 RPC/Literal 中,web 服务操作名称和部件名称不是 XML Schema 的一部分。

  1. Document/Literal (Unwrapped) 上 Document/Literal-Wrapped 的优点
    虽然 Document/Literal-Wrapped 是消息的 Document/Literal 样式的一种形式,但是如果整体 Document/Literal 样式的消息是相对于 restricted/wrapped Document/Literal,那么具有使用Document/Literal (Unwrapped) 的 SOAP 消息的缺点就是不包含对应传入 XML 文档的 web 服务操作的详细信息。因此,如果 Web 服务的两种不同操作都具有相同类型的方法参数,那么对于 SOAP 引擎来说分派将会很难。操作信息可与 RPC 样式的消息一起使用。通过在表示操作的输入参数的文档周围添加包装器,文档文本包装模式设计解决了 Document/Literal 样式的缺点。

讨论:Overloaded Methods & Wrapped Document/Literal 模式

方法过载

清单 4. 过载的方法 “add”
public void add(int addReq){}
public void add(String addReq){}
  1. 这个模式不能用于方法重载。使用此模式的方法重载在 WSDL 类型/模式中将需要具有相同名称的两个元素。然而,通过 XML Schema 规则(不同的命名空间)这是有可能的,但是如果是 Web 服务,不鼓励方法重载。
  2. WS-I Basic Profile 1.0(参见 R2304)需要 wsdl:portType 中的操作以便进行命名。因此,从 WS-I 遵从性角度来看,不应该存在操作重载的情况。
  3. WSDL 2.0 不支持操作重载。因此重载的操作在将来可能没有出头之日,且应该避免重载操作。

结束语

本文介绍了由 WSDL 设计中的 wrapped 文档文本模式提供的附加价值,以及方法重载编程实践中的缺点。但是 WS-I 并不建议方法重载本身,留给 “可互操作的” web 服务设计师在定义该 web 服务时明确选择 Wrapped Document/Literal 样式的绑定。

通过其普遍接受的优点和高指标的互操作性,此模式还添加值以便关闭企业系统的 web 服务和 SOA 之间的关系,其中异步系统彼此交互且每一个自下而上和自上而下的设计方法都是同样常见的实现。


相关主题

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=SOA and web services
ArticleID=749016
ArticleTitle=WSDL 设计中的 Wrapped Document/Literal 模式的使用
publish-date=07282011