理解web服务模式(一):应该采用哪一种 WSDL样式?

本文探讨了WSDL绑定样式中的RPC/编码、RPC/文字、文档/编码、文档/文字及文档/文字包装等五种模型。通过示例对比了各种样式的优缺点,为读者选择合适的WSDL绑定样式提供指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

RPC/编码、RPC/文字、文档/文字?应该采用哪一种?

WSDL 绑定样式可以是 RPC 样式或文档样式。用法可以是编码的,也可以是文字的。您如何决定使用哪一种样式 / 用法的组合呢?本文将帮助您解决这个问题。
Web 服务是通过 WSDL 文档来描述的。 WSDL 绑定描述了如何把服务绑定到消息传递协议(特别是 SOAP 消息传递协议)。 WSDL SOAP 绑定可以是 RPC 样式的绑定,也可以是文档样式的绑定。同样, SOAP 绑定可以有编码的用法,也可以有文字的用法。这给我们提供了四种样式 / 用法模型
1. RPC/ 编码
2. RPC/ 文字
3. 文档 / 编码
4. 文档 / 文字
除了这些样式之外,还有一种样式也很常见,它称为文档 / 文字包装的样式,算上这一种,在创建 WSDL 文件时您就有了五种绑定样式可以从中选择。您应该选择哪一种呢?
于本文的讨论,让我们从 清单1 中的 Java 方法开始,并且对其应用 JAX-RPC Java-to-WSDL 规则(请参见 参考资料 )。
清单 1. Java 方法
public void myMethod(int x);
RPC/ 编码
采用 清单1 中的方法并且使用您喜欢的 Java-to-WSDL 工具来运行它,指定您想让它生成 RPC/ 编码的 WSDL 。您最后应该得到如 清单2 所示的 WSDL 片断。
清单 2. 用于 myMethod RPC/编码的 WSDL
<message name="myMethodRequest">
<part name="x" type="xsd:int"/>
</message>
<message name="empty"/>
<portType name="PT">
<operation name="myMethod">
<input message="myMethodRequest"/>
<output message="empty"/>
</operation>
</portType>
<binding .../>
<!-- I won't bother with the details, just assume it's RPC/encoded. -->
现在用 “5” 作为参数 x 的值来调用此方法。我们将发送一个与 清单3 类似的 SOAP 消息。
清单 3. 用于 myMethod RPC/编码的 SOAP 消息
<soap:envelope>
<soap:body>
<myMethod>
<x xsi:type="xsd:int">5</x>
</myMethod>
</soap:body>
</soap:envelope>
为了简单起见,在本文的大部分 XML 示例中,我省略了名称空间和前缀。不过,我还是使用了少数前缀,您可以假定它们是用下列名称空间进行定义的。
  • xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  • xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  • xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
对于这个 RPC/ 编码的示例中的 WSDL SOAP 消息,有许多需要注意的事项:
  • WSDL 基本达到了尽可能地简单易懂的要求。
  • 操作名出现在消息中,这样接收者就可以很轻松地把消息发送到方法的实现。
  • 类型编码信息(比如xsi:type="xsd:int")通常就是降低吞吐量性能的开销。
  • 您不能简单地检验此消息的有效性,因为只有<x xsi:type="xsd:int">5</x>行包含在 Schema 中定义的内容;其余的soap:body内容都来自 WSDL 定义。
有没有一种方法能够保留这些优点而消除其中的缺点呢?或许有。让我们来看一看 RPC/ 文字的样式。
RPC/ 文字
用于我们的方法的 RPC/ 文字的 WSDL 看起来与 RPC/ 编码的 WSDL 几乎一样(请参见 清单4 )。只是绑定的用法由 编码 改为 文字 。仅此而已。
清单
4.
用于 myMethod RPC/文字的 WSDL
<message name="myMethodRequest">
<part name="x" type="xsd:int"/>
</message>
<message name="empty"/>
<portType name="PT">
<operation name="myMethod">
<input message="myMethodRequest"/>
<output message="empty"/>
</operation>
</portType>
<binding .../>
<!-- I won't bother with the details, just assume it's RPC/
literal. -->
RPC/ 文字的 SOAP 消息又是怎样的呢(请参见 清单 5 )?这里的更改要多一点。去掉了类型编码。
清单 5. 用于 myMethod
RPC/
文字的 SOAP 消息
<soap:envelope>
<soap:body>
<myMethod>
<x>5</x>
</myMethod>
</soap:body>
</soap:envelope>
下面是这种方法的优点和缺点:
  • WSDL 还是基本达到了尽可能地简单易懂的要求。
  • 操作名仍然出现在消息中。
  • 去掉了类型编码。
  • 您仍然不能简单地检验此消息的有效性,因为只有<x xsi:type="xsd:int">5</x>行包含在 Schema 中定义的内容;其余的soap:body内容都来自 WSDL 定义。
文档样式如何呢?它们能够帮助克服这些困难吗?
文档
文档 / 文字的 WSDL RPC/ 文字的 WSDL 作了一些更改。它们之间的不同之处显示在 清单6 中。

清单 6. 用于 myMethod 的文档 / 文字的 WSDL
<types>
<schema>
<element name="xElement" type="xsd:int"/>
</schema>
</types>
<message name="myMethodRequest">
<part name="x"
element="xElement" />
</message>
<message name="empty"/>
<portType name="PT">
<operation name="myMethod">
<input message="myMethodRequest"/>
<output message="empty"/>
</operation>
</portType>
<binding .../>
<!-- I won't bother with the details, just assume it's
document /literal. -->
而现在的 SOAP 应该如 清单 7 所示:

清单 7. 用于 myMethod 的文档 / 文字的 SOAP 消息
<soap:envelope>
<soap:body>
<xElement>5</xElement>
</soap:body>
</soap:envelope>
关于消息组成部分的注意事项
我本来可以只更改绑定,就像我从 RPC/ 编码转到 RPC/ 所做的那样。它将是合法的 WSDL 。然而, WS-I 基本概要( WS-I Basic Profile )(请参见 参考资料 )规定文档 / 文字的消息的组成部分引用元素而不是类型,所以我遵循了 WS-I (并且此处使用元素部分可以很好地把我们带到关于文档 / 文字包装的样式的讨论)。
下面是这种方法的优点和缺点:
优点
  • 没有编码信息
  • 您可以在最后用任何 XML 检验器检验此消息的有效性。soap:body<xElement>5</xElement>)中每项内容都定义在 Schema 中。
缺点
  • WSDL 变得有些复杂。不过,这是一个非常小的缺点,因为 WSDL 并没有打算由人来读取。
  • SOAP 消息中缺少操作名。而如果没有操作名,发送就可能比较困难,并且有时变得不可能。
文档 / 文字的样式看起来似乎只是重新安排了 RPC/ 文字的模型的优点和缺点。您可以检验消息的有效性,但是您失去了操作名。有没有一种方法可以改进这一点呢?有的。它就是文档 / 文字包装的样式。
文档
在我说明文档 / 文字包装的样式的含义之前,让我给您展示 清单 8 清单9 中的 WSDL SOAP 消息。

清单 8. 用于 myMethod 的文档 / 文字包装的 WSDL
<types>
<schema>
<element name="myMethod"/>
<complexType>
<sequence>
<element name="x" type="xsd:int"/>
</sequence>
</complexType>
</element>
</schema>
</types>
<message name="myMethodRequest">
<part name="
parameters " element="
myMethod "/>
</message>
<message name="empty"/>
<portType name="PT">
<operation name="myMethod">
<input message="myMethodRequest"/>
<output message="empty"/>
</operation>
</portType>
<binding .../>
<!-- I won't bother with the details, just assume it's document/literal. -->
WSDL Schema 现在把参数放在包装中(请参见 清单9 )。

清单 :9. 用于 myMethod 的文档 / 文字包装的 SOAP 消息
<soap:envelope>
<soap:body>
<myMethod>
<x>5</x>
</myMethod>
</soap:body>
</soap:envelope>
注意到此 SOAP 消息看起来非常类似于 RPC/ 文字的 SOAP 消息。您可能会说,它看起来与 RPC/ 文字的 SOAP 消息是完全一样的,不过,这两种消息之间存在着微妙的区别。在 RPC/ 文字的 SOAP 消息中, <soap:body> <myMethod> 子句是操作的名称。在文档 / 文字包装的 SOAP 消息中, <myMethod> 子句是单个输入消息的组成部分引用的元素的名称。因此,包装的样式具有这样的一个特征,输入元素的名称与操作的名称是相同的。此样式是把操作名放入 SOAP 消息的一种巧妙方式。
文档 / 文字包装的样式的特征有:
  • 输入消息只有一个组成部分。
  • 该部分就是一个元素。
  • 该元素有与操作相同的名称。
  • 该元素的复杂类型没有属性。
下面是这种方法的优点和缺点:
  • 没有编码信息。
  • 出现在 soap:body 中的每项内容都是由 Schema 定义的,所以您现在可以很容易地检验此消息的有效性。
  • 方法名又出现在 SOAP 消息中。
  • WSDL 甚至更复杂,但是这仍然是一个非常小的缺点。
如您所见,文档 / 文字包装的样式还是有一些缺点,不过与优点比起来,它们都显得无足轻重。
文档 /文字的样式在哪里定义

这种包装的样式来源于 Microsoft 。没有定义这种样式的规范;所以虽然这种样式是一个好的东西,但不幸的是,为了与 Microsoft 和其他公司的实现进行互操作,现在惟一的选择就是根据 Microsoft WSDL 的输出来猜测它是如何工作的。文档 / 文字包装的样式也实现在 IBM WebSphere SDK for Web Services 中(请参见 参考资料 )。在这个示例中,样式是相当明显的;但是也存在个别情况,在这些情况中,由于缺少定义而导致需要操作的适当事项不够特别清晰。我们希望看到的最理想的情况就是将来能有像 Web 服务互操作组织( Web Services Interoperability Organization )这样的独立团体来帮助对此进行稳定化和标准化。
为什么不始终采用文档 /文字包装的样式
至此,本文已经给了您这样的一个印象,文档 / 文字包装的样式是最好的方法。而实际的情况往往确实如此。不过,仍然存在着一些情况,在这些情况下,您最好是换一种别的样式。
采用文档 /文字非包装的样式的理由

如果您已经重载了操作,就不能采用文档 / 文字包装的样式。
想象一下,除了我们一直在使用的方法之外,还有另一种方法,请参见 清单10

清单 10. 用于文档/文字包装的问题方法
public void myMethod(int x);
public void myMethod(int x, String y);
WSDL 的下一个版本可能将不允许重载的操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值