use属性可以为literal,encoded;style可以为rpc,document,我们来对五种类型的style/use决定的binding作一比较,分别是rpc/literal, document/literal none-wrapper, document/literal with wrapper, rpc/encoded, 以及document/encoded。
从生成soap消息的角度看
rpc和document的差别在于方法的操作名是否出现在生成的Soap消息中。
literal和encoded编码方式的差别在于参数类型是否出现在生成的Soap消息中。
rpc/encoded能够完整地表示一个方法调用,但性能很差,而且不能校验Soap消息的有效性。
rpc/literal不对参数类型进行编码,但仍然无法对Soap消息进行校验。
document/encoded没有意义,因为没有方法名,对参数类型编码没有什么意义。
document/literal none-wrapper无法生成操作名,适用于完整的文档作为参数传递给方法的场景。
document/literal with wrapper应该是目前使用最多的方式。
WSDL 绑定样式可以是 RPC 样式或文档样式。用法可以是编码的,也可以是文字的。您如何决定使用哪一种样式/用法的组合呢?本文将帮助您解决这个问题。
Web 服务是通过 WSDL 文档来描述的。WSDL 绑定描述了如何把服务绑定到消息传递协议(特别是 SOAP 消息传递协议)。WSDL SOAP 绑定可以是 RPC 样式的绑定,也可以是文档样式的绑定。同样,SOAP 绑定可以有编码的用法,也可以有文字的用法。这给我们提供了四种样式/用法模型:RPC/编码、RPC/文字、文档/编码、文档/文字
除了这些样式之外,还有一种样式也很常见,它称为文档/文字包装的样式,算上这一种,在创建 WSDL 文件时您就有了五种绑定样式可以从中选择。您应该选择哪一种呢?
对于本文的讨论,让我们从 清单1中的 Java 方法开始,并且对其应用 JAX-RPC Java-to-WSDL 规则。清单 1. Java 方法
public void myMethod(int x); |
RPC/编码
清单 2. 用于 myMethod 的 RPC/编码的 WSDL
<message name="myMethodRequest"> </message> <message name="empty"/> <portType name="PT"> </portType> <binding .../> <!-- I won't bother with the details, just assume it's RPC/encoded. --> |
清单 3. 用于 myMethod 的 RPC/编码的 SOAP 消息
<soap:envelope> </soap:envelope> |
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/文字的样式。
RPC/文字
清单 4. 用于 myMethod 的 RPC/文字的 WSDL
<message name="myMethodRequest"> </message> <message name="empty"/> <portType name="PT"> </portType> <binding .../> <!-- I won't bother with the details, just assume it's RPC/ |
清单 5. 用于 myMethod 的RPC/文字的 SOAP 消息
<soap:envelope> </soap:envelope> |
文档/文字的 WSDL
文档/文字的 WSDL对 RPC/文字的 WSDL 作了一些更改。它们之间的不同之处显示在 清单6中。
清单6. 用于 myMethod 的文档/文字的 WSDL
<types> </types> <message name="myMethodRequest"> </message> <message name="empty"/> <portType name="PT"> </portType> <binding .../> <!-- I won't bother with the details, just assume it's |
而现在的 SOAP 应该如 清单 7所示:
清单7. 用于 myMethod 的文档/文字的 SOAP 消息
<soap:envelope> </soap:envelope> |
下面是这种方法的优点和缺点:
文档/文字包装的样式
清单
8和
清单9中的 WSDL 和 SOAP 消息。
清单8. 用于 myMethod 的文档/文字包装的 WSDL
<types> </types> <message name="myMethodRequest"> </message> <message name="empty"/> <portType name="PT"> </portType> <binding .../> <!-- I won't bother with the details, just assume it's document/literal. --> |
清单9)。
清单:9. 用于 myMethod 的文档/文字包装的 SOAP 消息
<soap:envelope> </soap:envelope> |
SOAP 消息的一种巧妙方式。
文档/文字包装的样式的特征有:
下面是这种方法的优点和缺点:
方法名又出现在 SOAP 消息中。
WSDL 甚至更复杂,但是这仍然是一个非常小的缺点。
如您所见,文档/文字包装的样式还是有一些缺点,不过与优点比起来,它们都显得无足轻重。
RPC/文字包装的样式?
文档/文字的样式在哪里定义?
Web 服务互操作组织(Web Services Interoperability Organization)这样的独立团体来帮助对此进行稳定化和标准化。
为什么不始终采用文档/文字包装的样式
采用文档/文字非包装的样式的理由
如果您已经重载了操作,就不能采用文档/文字包装的样式。
想象一下,除了我们一直在使用的方法之外,还有另一种方法,请参见
清单10。
清单10. 用于文档/文字包装的问题方法
public void myMethod(int x); public void myMethod(int x, String y); |
采用 RPC/文字的样式的理由
清单11中的一组方法。
清单11. 用于文档/文字非包装的样式的问题方法
public void myMethod(int x); public void myMethod(int x, String y); public void someOtherMethod(int x); |
清单
7中看一看它)。服务器应该发送哪一种方法呢?所有您能确切知道的就是,它一定不是 myMethod(int x, String x) ,因为消息只有一个参数,而这种方法需要两个参数。它可能是其他两种方法中的一种。采用文档/文字的样式,您没有办法知道是哪一种方法。
清单5中的),而不是文档/文字的消息。对于这种消息,服务器很容易决定把它发送到哪一种方法。您知道操作名是 myMethod,并且也知道只有一个参数,所以它必定是 myMethod(int x) 。
采用 RPC/编码的理由有很多。
其中两个主要的原因是:
数据图形
多态性
数据图形
设想您有一个二进制树,其中的节点定义在
清单12中。
清单12. 二进制树节点 Schema
<complexType name="Node"> </complexType> |
图1)。
发送数据图形的标准方式是使用 href 标记,它是 RPC/编码的样式(
清单13)的一部分。
清单:13. RPC/编码的二进制树
<A> </A> <B id="12345"> </B> |
在任何文字的样式中,href 属性都是不可用的,这样图形链接就不再起作用了(
清单14和
图2)。您仍然有一个根节点 A,它从左边指向一个节点 B,从右边指向另一个节点 B。这两个 B 节点是等同的,但它们不是相同的节点。是复制了数据而不是引用了两次数据。
14. 文字二进制树
<A> </A> |
多态性
看一看
清单15中使用多态性 Schema 的 WSDL。
<types> </types> <message name="in"> </message> <message name="empty"/> <portType name="AnimalTrainer"> </portType> |
清单16)。这种类型编码信息可用在 RPC/编码的样式中。
<soap:envelope> </soap:envelope> |
有四种绑定样式(其实真正有五种,不过文档/编码的样式没有什么意义)。虽然每种样式都有自己的用武之地,但是在大多数情况下,最好的样式是文档/文字包装的样式。