WSDL绑定样式各种组合优劣势比较

时间:2022-09-21 18:25:10

WSDL绑定样式各种组合优劣势比较  


目前Web服务的相关标准是WSDL【Web服务描述语言】,一种标准的类似XML Schema的语言,用它来详细说明Web服务和SOAP【简单对象访问协议】Web服务使用的实际的沟通协议就是SOAP。WSDL 绑定样式由两个属性组合而成:style、use;style可以是RPC/Document,use可以是Encoded/Literal;下面解释下这4个名词的意思:

RPC 样式

RPC样式指定<soap:body>元素包含一个将被调用的web方法的名称的元素(wrapper element(封装元素))。这个元素依次为该方法的每个参数还有返回值作了记录。

Document 样式

如果是document 样式,就没有像在RPC样式中的wrapper元素。转而代之的是消息片断直接出现在<soap:body>元素之下。没有任何SOAP格式化规则规定<soap:body>元素下能包含什么;它包含的是一个发送者和接收者都达成一致的XML文档。

Encoded 编码 

如果use的值是encoded”,则每个消息片段将使用类型属性来引用抽象类型。通过应用由 encodingStyle属性所指定的编码样式,可使用这些抽象类型生成具体的消息。最常用到的SOAP编码样式是在SOAP1.1中定义的一组序列化规则,它说明了对象、结构、数组和图形对象应该如何序列化。通常,在应用程序中使用SOAP编码着重于远程进程调用和以后适合使用RPC消息样式。

Literal 文字? 

如果use的值是Literal, 则每个片段使用element 属性(对于简单片段)或type 属性(对于复合片段)来引用具体架构,例如,数据根据指定的架构来序列化,这架构通常使用W3C XML架构来表述。

根据不同的组合,形成了四种绑定模型;另外,还有一种用Document模拟RPC样式的包装组合也很常见;

  1. RPC/Encoded
  2. RPC/Literal
  3. Document/Encoded
  4. Document/Literal
  5. Document/Literal Wrapped

从生成soap消息的角度看:

rpc和document的差别在于方法的操作名是否出现在生成的Soap消息中。use="literal" 意味着type定义遵循xml模式定义

document:<soap:body>的内容由定义在<wsdl:type>中的xml模式指定。他不需要遵循特定的soap规范。简言之,
soap消息是通过<soap:body>中的document发送出去,而没有额外的要遵循的格式规则。document style是一种默认的选择。

      rpc: <soap:body>元素的结构需要遵循特定的规则(soap1.1规范第7部分有细节)。根据这些规则,<soap:body>可以
包含唯一一个元素,这个元素在operation后被命名,所有的参数都必须写成这个元素的子元素。

      literal和encoded编码方式的差别在于参数类型是否出现在生成的Soap消息中。use="encoded" 参考xml中已有的应用数据,通常指的是soap1.1规范中的soap编码规则。如果文档中没有自定义数据,就可以选择encoded。


对于以上5种组合方式,由于Document/Encoded不被现有平台所支持,在实际中应用很少,所以这里就暂时不讨论该种组合;对于剩下的4种组合,我们结合一个表格和实例来对比下各自的优劣情况;

Binding Type Advantage/DisAdvantage
RPC/ Encoded 优点:
  1. WSDL文件的定义遵循直观和众所周知的远程进程调用的沟通模式。
  2. 操作名显示在消息中,因此接收者很容易就把消息分派给它的实现。
  3. 如果你正在你的服务中使用数据图形或者多态,这是惟一能使用的样式

缺点:

  1. SOAP消息包含的类型编码信息就如xsi:type="xsd:int",这些就是一种开销。
    性能比较差。 
  2. 通常验证SOAP消息是很困难的,因为在WSDL Shcema中没有描述。
  3. RPC样式引起了一种在服务提供者和客户之间的紧密耦合,任何对接口的
    更改都会导致服务和客户间联系的中断。
  4. 不被WSI一致性标准所支持。
RPC/ Literal

优点:

  1. WSDL定义仍然像RPC/Encoded样式一样简单直接。
  2. 操作名仍然出现在SOAP消息中。
  3. 把类型编码从消息中排除了,因此提升了吞吐性能。

缺点:

  1. 服务和客户之间仍然有紧密耦合。
  2. 仍然难以用SOAP消息来验证传输的数据。
  3. 它也不被WSI一致性标准所支持。 
Document/Litaral

优点:

  1. SOAP消息中没有类型编码信息。
  2. 你总能用任何XML验证器来验证消息,在soap体中任何东西都在schema
    有定义。
  3. 使用document样式,规则不是那么严格,还有对XML Schema进行增强和
    更改时不会破坏接口。
  4. 如果使用某特殊序列进行多进程调用,Document 样式可以保持应用程序的
    状态。
  5. Document样式更加适合异步处理。
  6. 许多document-messaging服务能够选择文档的DOMSAX两种处理方式的
    其中一种,结果就是能最小化在内存中的处理。

缺点:

  1. WSDL定义变得更加复杂。
  2. SOAP消息中的操作名没有了,没有了名称,把消息分派给它的实现方法
    就变得困难或不可能了。 
    WS-I 基本概要(WS-I Basic Profile)规定文档/文字的消息的组成部分引用
    元素而不是类型
Document/LiteralWrapped

优点:

  1. 包含了所有Document/Literal样式的优点。
  2. 操作名出现在SOAP消息中。

缺点:

  1. 即使WSDL定义变得更加复杂,但仍然有不少缺点。
  2. 如果你在web服务中重载了操作,你就不能使用该样式。 

假设我们需要调用的WS的method为:public void myMethod(int x); 各种绑定样式生成的WSDL/SOAP片段如下:

Binding Type WSDL SOAP
RPC/ Encoded
<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>  
    <!-- RPC/encoded. -->  
</binding>
<soap:envelope>  
<soap:body>  
  <myMethod>  
<x xsi:type="xsd:int">5</x>
  </myMethod>  
</soap:body>
</soap:envelope> 
RPC/ Literal
<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>  
    <!-- RPC/literal. -->  
</binding>  
<soap:envelope>  
    <soap:body>  
        <myMethod>  
          <x>5</x>  
        </myMethod>  
    </soap:body>  
</soap:envelope>  

Document/ Litaral
<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>  
    <!-- document/literal. -->  
</binding> 
<soap:envelope>  
  <soap:body>  
   <xElement>5</xElement>  
  </soap:body>  
</soap:envelope> 
Document/ Literal Wrapped
<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>  
    <!-- document/literal. -->  
</binding>  
<soap:envelope>  
    <soap:body>  
      <myMethod>  
          <x>5</x>  
      </myMethod>  
    </soap:body>  
</soap:envelope> 

采用 RPC/编码的理由有很多。其中两个主要的原因是: 
数据图形
多态性
数据图形

设想您有一个二进制树,其中的节点定义在 清单12中。


清单12. 二进制树节点 Schema
       
       
<complexType name="Node"> 
<sequence>
<element name="name" type="xsd:string"/>
<element name="left" type="Node" xsd:nillable="true"/>
<element name="right" type="Node" xsd:nillable="true"/>
</sequence>
</complexType>

 

根据这种节点定义,我们可以构造一个树形结构,它的根节点 A 通过它左边和右边的的链接可以指向节点 B(请参见 图1)。


WSDL绑定样式各种组合优劣势比较

发送数据图形的标准方式是使用 href 标记,它是 RPC/编码的样式( 清单13)的一部分。


清单:13. RPC/编码的二进制树
<A>      <name>A</name>      <left href="12345"/>      <right href="12345"/></A><B id="12345">      <name>B</name>      <left xsi:nil="true"/>      <right xsi:nil="true"/></B>  

在任何文字的样式中,href 属性都是不可用的,这样图形链接就不再起作用了( 清单14图2)。您仍然有一个根节点 A,它从左边指向一个节点 B,从右边指向另一个节点 B。这两个 B 节点是等同的,但它们不是相同的节点。是复制了数据而不是引用了两次数据。


14. 文字二进制树
<A>      <name>A</name>      <left>          <name>B</name>          <left xsi:nil="true"/>          <right xsi:nil="true"/>      </left>      <right>          <name>B</name>          <left xsi:nil="true"/>          <right xsi:nil="true"/>      </right>
</A>

WSDL绑定样式各种组合优劣势比较

在文字样式中,您可以通过各种方法构造图形,但是却没有标准的方法;所以您做的任何事情很可能不能与网络中其他端点上的服务进行互操作。

多态性

看一看 清单15中使用多态性 Schema 的 WSDL。

清单 15. 一个多态性 WSDL 的示例
<types>    <schema>      <complexType name="animal">        <sequence>          <element name="name" type="xsd:string"/>        </sequence>      </complexType>      <complexType name="dog">        <complexContent mixed="false">          <extension base="animal">            <sequence>              <element name="breed" type="xsd:string"/>            </sequence>          </extension>        </complexContent>      </complexType>    </schema></types><message name="in">    <part name="trainee" type="animal"/></message><message name="empty"/><portType name="AnimalTrainer">    <operation name="train">      <input message="in"/>      <output message="empty"/>    </operation></portType>  

当您把一个 dog 的实例传送给 train 操作时,所生成的 SOAP 消息必须包含类型编码信息,这样接收终端才能知道它所接收的是 animal 的哪一个扩展(请参见 清单16)。这种类型编码信息可用在 RPC/编码的样式中。

清单 16. 一个多态性 SOAP 消息
<soap:envelope>    <soap:body>      <train>        <trainee xsi:type="Dog">          <name>Bob</name>          <breed>Bloodhound</breed>        </trainee>      </train>    </soap:body>  </soap:envelope>

1、使用普通Document/literal模式的情形:
    当存在方法重载(overload)时,
      public void myMethod(int x, float y);
      public void myMethod(int x);
    此时,我们无法在WSDL中定义两个相同名称的复杂类型作为方法的输入参数。
    (wrapper模式要求方法输入参数的复杂类型名誉方法名相同)

2、使用RPC/literal的情形:
    当同时存在重载方法与不同名但参数列表相同的方法时
    (1)public void myMethod(int x, float y);
    (2)public void myMethod(int x);
    (3)public void someOtherMethod(int x, float y);
    此时,Document/literal由于没有方法名无法区分(1)方法与(3)方法

3、使用RPC/encoded的情形:
    当需要传递数据图(data graph)信息时,需要使用href属性。
    而任何literal风格的SOAP消息是不允许使用href属性的

转自:老唐 的专栏
           我应该彩哪一种WSDL样式 (Russell Butek, 软件工程师, IBM)
           SOAP风格中 RPC与Document的区别
           Web Service描述语言 WSDL 详解