接上篇WebService原理浅析, SOAP编码有多种方式,我们在上一篇中使用的只是其中的一种,上一篇中我们介绍了WSDL的binding部分描述了WebService使用的协议及封装格式,其中封装格式是由样式( style )和编码(encode)控制的,本文将介绍样式和编码的组合是怎么影响SOAP封装,每种组合的优缺点以及使用建议。
WebService有两种通信样式( style ):
documentrpc通过WSDL文件的binding部分可以判断WebService属于哪种样式(style),document示例如下:
...... <!-- document style示例 --> <binding name="HelloWorldPortBinding" type="tns:HelloWorld"> <!-- style 属性表明使用的是哪种style --> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> .....rpc示例如下:
...... <!-- rpc style示例 --> <binding name="HelloWorldPortBinding" type="tns:HelloWorld"> <!-- style 属性表明使用的是哪种style --> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/> .....
WebService有两种编码( encode )方式:
encodeliteral同样,通过WSDL文件的binding部分可以判断WebService属于哪种编码(encode),encode示例如下:
...... <binding name="HelloWorldPortBinding" type="tns:HelloWorld"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <operation name="sayHelloWorld"> <soap:operation soapAction=""/> <input> <!-- use属性表明使用的编码格式--> <soap:body use="encode"/> </input> ......literal示例如下:
...... <binding name="HelloWorldPortBinding" type="tns:HelloWorld"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <operation name="sayHelloWorld"> <soap:operation soapAction=""/> <input> <!-- use属性表明使用的编码格式--> <soap:body use="literal"/> </input> ......
样式和编码有四种组合:
rpc encoderpc literaldocument encodedocument literal每种组合对应不同的SOAP协议格式,下文将使用上一篇( WebService原理浅析 )中的sayHelloWorld方法举例说明每种组合对应的协议格式,sayHelloWorld对应的Java签名如下:
public String sayHelloWorld(String arg0)
WSDL文件看起来如下:
...... <message name="sayHelloWorldRequest"> <part name="arg0" type="xsd:string"/> </message> ...... <portType name="HelloWorld"> <operation name="sayHelloWorld"> <input message="sayHelloWorldRequest"/> ...... </operation> </portType> <binding ....../>调用sayHelloWorld方法SOAP的协议封装看起来如下:
<soap:envelope> <soap:body> <sayHelloWorld> <arg0 xsi:type="xsd:string">jack</arg0> </sayHelloWorld> </soap:body> </soap:envelope>优点:
WSDL文件简单明了消息里面有方法名sayHelloWorld和参数名arg0缺点:
参数里面包含了类型信息,这样会降低传输性能,因为要多传输类型信息无法验证SOAP表示的xml,元素sayHelloWorld和arg0根本就没有定义
WSDL文件看起来如下:
...... <message name="sayHelloWorldRequest"> <part name="arg0" type="xsd:string"/> </message> ...... <portType name="HelloWorld"> <operation name="sayHelloWorld"> <input message="sayHelloWorldRequest"/> ...... </operation> </portType> <binding ....../>调用sayHelloWorld方法SOAP的协议封装看起来如下:
<soap:envelope> <soap:body> <sayHelloWorld> <arg0>jack</arg0> </sayHelloWorld> </soap:body> </soap:envelope>优点:
WSDL文件简单明了消息里面有方法名sayHelloWorld和参数名arg0缺点:
无法验证SOAP表示的xml,元素sayHelloWorld和arg0没有定义。
没有人使用这种风格,所以我们不做介绍。
WSDL文件看起来如下:
...... <types> <schema> <element name="arg0" type="xsd:string"/> <schema> </type> <message name="sayHelloWorldRequest"> <part name="arg0" element="arg0"/> </message> ...... <portType name="HelloWorld"> <operation name="sayHelloWorld"> <input message="sayHelloWorldRequest"/> ...... </operation> </portType> <binding ....../>调用sayHelloWorld方法SOAP的协议封装看起来如下:
<soap:envelope> <soap:body> <arg0>jack</arg0> </soap:body> </soap:envelope>优点:
SOAP表示的xml可以验证,可以找到元素arg0的定义。缺点:
WSDL文件复杂了一些,因为定义了 一些新的xml元素arg0消息里面没有方法名sayHelloWorld
综合四种组合的优缺点document literal wrapped应运而生, WSDL文件看起来如下:
...... <types> <schema> <element name="sayHelloWorld"> <complexType> <element name="arg0" type="xsd:string"/> </complexType> </element> <schema> </types> <message name="sayHelloWorldRequest"> <part name="parameters" element="sayHelloWorld"/> </message> ...... <portType name="HelloWorld"> <operation name="sayHelloWorld"> <input message="sayHelloWorldRequest"/> ...... </operation> </portType> <binding ....../>调用sayHelloWorld方法SOAP的协议封装看起来如下:
<soap:envelope> <soap:body> <sayHelloWorld> <arg0>jack</arg0> </sayHelloWorld> </soap:body> </soap:envelope>优点:
包含了方法名和参数SOAP的xml文件可以验证,sayHelloWorld和arg0元素都已经定义了缺点:
WSDL文件变复杂了,增加了sayHelloWorld和arg0元素
虽然document literal wrapped 会增加WSDL的复杂度,但是WSDL文件往往不需要人来处理,有现成的框架可以读取WSDL文件生成代码。所以document literal wrapped是最好的一种协议封装方式,我们应该优先使用这种方式,上一篇中便是使用了这种封装方式。
document literal wrapped虽好但是也有它不适用的场景,当WebService中有重载的方法名时,document literal wrapped 将不再适用,因为无法在xml中定义两个相同的方法名元素。
style用来控制SOAP封装里面是否有方法名,document没有方法名,rpc有方法名,document wrapped也有方法名。
encode/literal用来控制SOAP封装的参数是否有数据类型,encode有数据类型,literal没有数据类型。
参考:
https://www.ibm.com/developerworks/library/ws-whichwsdl/index.html