WebService之样式(Style)和编码(Encode)

    xiaoxiao2023-09-28  174

     

    接上篇WebService原理浅析, SOAP编码有多种方式,我们在上一篇中使用的只是其中的一种,上一篇中我们介绍了WSDL的binding部分描述了WebService使用的协议及封装格式,其中封装格式是由样式( style )和编码(encode)控制的,本文将介绍样式和编码的组合是怎么影响SOAP封装,每种组合的优缺点以及使用建议。

     

    样式( style )

     

    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"/> .....

     

    编码( encode )

     

    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)

     

    rpc encode

     

    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根本就没有定义

     

    rpc literal

     

    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没有定义。

     

    document encoded

     

    没有人使用这种风格,所以我们不做介绍。

     

    document literal

     

    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

     

    综合四种组合的优缺点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

     

    最新回复(0)