迹忆博客
当前位置: 主页 > 学无止境 > 网络 > 文章

WSDL原来是这样的

发布时间: 2016-01-11 作者: 迹忆 浏览次数:

在刚开始学习Webservice的时候,发现里面涉及到的知识点还真不少,每一点单拿出来都可以自成一派了。尤其是看到WSDL的时候,查了很长时间的资料,依然是有些迷惑,对其没有一个清晰的认识。随着在以后的工作中,自己写了一些WSDL的案例,才逐渐的对其内部原理有了一些认识。

首先先看一下WSDL的作用:WSDL(Web Service Description Language)用XML格式的文件来描述可用的Web服务。其实说白了就是一个标准,终端按照这个标准在网络中创建Web服务,客户端也按照此标准去连接这个服务,并且根据WSDL文件获知自己所需要的操作。

接下来我想说一下WSDL的发展过程,了解WSDL的产生历史,在以后的学习过程中不至于产生迷惑。

WSDL的第一个版本是WSDL1.0 在2000年9月有IBM,Microsoft以及Ariba开发,目的就是描述Web Service 的SOAP工具包。随后在2001年3月,WSDL 1.1版本发布,此举标志着WSDL走向了正轨。但是在1.0 和1.1之间并没有产生多大的变化。时隔两年,在2003年6月最为W3C的工作草案 WSDL1.2发布。按照W3C的说法,WSDL1.2相对于1.1版本来说开发者使用起来更简单并且更灵活了。但是WSDL1.2并不支持大多数的SOAP服务。

在2007年6月,WSDL1.2被正式更名为WSDL2.0,此时WSDL2.0也成为了W3C的推荐版本。做出这一改变的原因是2.0版本相对于1.1版本来说有了实质性的改变,所以上升了一个等级。

所以说现在WSDL流行的两个版本是WSDL2.0 和 WSDL1.1。虽说WSDL2.0 是W3C推荐的版本,但是现在大多数的厂商支持的还是WSDL1.1。举个例子来说,我们都知道PHP的一款官方IDE——zendstudio还有java IDE——Eclipse,当我们使用它们新建WSDl文件时,这个WSDl文件所遵循的格式还是WSDL1.1版本的格式。在我平时的工作中,使用的WSDL也是遵循的1.1版本的格式。

那WSDL1.1和WSDL2.0的格式究竟是怎样的呢,下面我来向大家介绍介绍。

首先我们看一下WSDL1.1,按照此标准,在WSDL文件中包含下面七项内容

1. Types

可以认为是一个容器,容器里的内容是数据类型的描述,当然需要借助于XML Schema 来达到这一目的。那么这个容器的格式如下

<wsdl:types>
    <xsd:schema targetNamespace="http://www.test.com/WSDLFile/">
      <xsd:element name="Operation">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="in" type="xsd:string"/>
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
      <xsd:element name="OperationResponse">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="out" type="xsd:string"/>
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
    </xsd:schema>
  </wsdl:types>

2. Message

对操作接口进行一个抽象的定义。格式如下:

<wsdl:message name="OperationRequest">
    <wsdl:part element="tns:Operation" name="parameters"/>
  </wsdl:message>
<wsdl:message name="OperationResponse">
    <wsdl:part element="tns:OperationResponse" name="parameters"/>
  </wsdl:message>

Messages包含了一个或者多个part 元素,对于Message的属性name的值是唯一的,和当前整个WSDL文件中的人和一个Message的name值都不能相同。Part的属性name的值也是唯一的,和当前Message中的其它的任何一个part的name的值都不能相同,当然处于不同的Message中的part的name的值可以相同。

每一个part元素都关联message-type属性,这个message-type属性一般包含两部分:element和type。Message中的每一个part对应Types中的一个element元素,并且part的element属性的值为 Types中的element的name的值,前面再加上tns: ,举例如下(下面的代码是摘自 http://www.w3.org/TR/wsdl#_introduction):

<types>
        <schema .... >
           <element name="PO" type="tns:POType"/>
           <complexType name="POType">
               <all>
                   <element name="id" type="string/>
                   <element name="name" type="string"/>
                   <element name="items">
                       <complexType>
                           <all>
                               <element name="item" type="tns:Item" minOccurs="0" maxOccurs="unbounded"/>
                           </all>
                       </complexType>
                   </element>
              </all>
           </complexType>
 
           <complexType name="Item">
               <all>
                   <element name="quantity" type="int"/>
                   <element name="product" type="string"/>
               </all>
           </complexType>
           <element name="Invoice" type="tns:InvoiceType"/>
           <complexType name="InvoiceType">
               <all>
                   <element name="id" type="string"/>
               </all>
           </complexType>
        </schema>
    </types>
<message name="PO">
        <part name="po" element="tns:PO"/>
        <part name="invoice" element="tns:Invoice"/>
    </message>

对于Message这一项在WSDL2.0中已经去掉了。

3. Port Type

由终端定义的一系列的抽象方法,其格式如下  

<wsdl:portType name="WSDLFile">
    <wsdl:operation name="Operation">
      <wsdl:input message="tns:OperationRequest"/>
      <wsdl:output message="tns:OperationResponse"/>
    </wsdl:operation>
</wsdl:portType>

同样的,port type 的属性name的值不同于整个WSDL文档中其他的prottype的name的值。

WSDL有四种传递方式:

One-way: 终端服务接受消息

<wsdl:operation name="Operation">
      <wsdl:input message="tns:OperationRequest"/>
 </wsdl:operation>

Request-response:终端服务接受消息,并且发送相关的消息给客户端

<wsdl:operation name="Operation">
      <wsdl:input message="tns: OperationRequest"/>
      <wsdl:output message="tns:OperationResponse"/>
</wsdl:operation>

Solicit-response:终端发送一个消息,并且接受一个相关消息

<wsdl:operation name="Operation">
<wsdl:output message="tns:OperationResponse"/>
      <wsdl:input message="tns: OperationRequest"/>
</wsdl:operation>

Notification:终端服务发送一个消息

<wsdl:operation name="Operation">
<wsdl:output message="tns:OperationResponse"/>
</wsdl:operation>

对于input和output的name的值来说,每一个input或者output的name的值在所有的input和output中是唯一的。当然WSDL也提供了默认的命名规则。此外对于input或者output的属性message的值为Message元素中的属性name的值,前面加上tns:

4. Binding

为porttype中的operation和message指定一个具体的传输协议(SOAP协议)和数据格式

<wsdl:binding name="WSDLFileSOAP" type="tns:WSDLFile">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="Operation">
      <soap:operation soapAction="http://www.test.com/WSDLFile/Operation"/>
      <wsdl:input>
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>

同样的binding的属性name的值在所有的binding的name中是唯一的。此时binding是通过type和porttype进行绑定的,type的值为porttype的name的值在前面加上tns:。然后binding中的子元素wsdl:operation 参照 上面的operation,只是对每一个元素进行了SOAP绑定。

除了这些,在上面的示例中我们还看到有 soap:binding,soap:operation,soap:body等,这些的作用就是将soap协议绑定到接口上,因为在传输的过程中是按照soap协议传输的。

首先看soap:binding,其style的值就是operation的type属性的默认值,所以在wsdl:operation中我们可以不指定type属性。接下来是soap:operation,soapAction指定了消息请求的地址,也就是消息发送到哪个接口或者操作方法。还有就是soap:body指定了消息部分在SOAP协议中是以什么方式传输的。其中use属性是必须的,除此之外还有parts,encodingstyle和namespace属性,但是这几个不是必须的。use属性的值有两个literal和encoded,以此判断消息部分是否使用某种编码规则进行编码,或者定义一种具体的模式。

在实际应用中SOAP协议对于开发者来说是透明的,编程语言中都将SOAP协议封装成了具体的函数来供我们开发调用。如果想要详细了解SOAP协议的机制,可以参考http://www.w3.org/TR/soap12-part1/#soapbody

5. Port

定义了链接web service的地址,这个地址就是一个HTTP URL

<wsdl:service name="WSDLFile">
    <wsdl:port binding="tns: WSDLFileSOAP" name="WSDLFileSOAP">
      <soap:address location="http://www.test.com/"/>
    </wsdl:port>
</wsdl:service>

Port的name值在所有的Port的name中是唯一的。属性binding的值为上面binding元素中的name的值前面加上tns:

这里需要注意的是一个Port只能指定一个address,并且在port中除了address不能包含其他的元素。

6. Service

可以理解为一组相关的port

<wsdl:service name="WSDLFile">
    <wsdl:port binding="tns: WSDLFileSOAP" name="WSDLFileSOAP">
      <soap:address location="http://www.test.com/"/>
    </wsdl:port>
</wsdl:service>

同样其name值在所有的service的name中是唯一的。在一个service下面的一组port是有关系的。一、每个port之间不能相互通信;二、如果一个service中的多个port共享一个porttype,但是每个port又有不同的address和binding,那么这些port需要提供等价的行为,以便WSDL文档可以根据某个标准来选择相应的port进行通信。三、因为这些port提供的信息有一定的关联性,所以可以根据这些port了解一个service的porttype。

以上就是WSDL1.1版本的格式,在WSDL2.0中除了去掉了Message这一项外,而且还替换了port Type 为Interface。由于我在平时使用的时候,都是用的WSDL1.1,没有使用过2.0版本,所以我对此还不是很了解。待我好好研究研究2.0,之后再为大家奉上WSDL2.0的版本。当然如果大家有什么好的建议,也欢迎在下面留言,大家共同讨论,共同进步。

赞助
迹忆博客

除非注明转载,本站文章均为原创,欢迎转载,转载请以链接形式注明出处

本文地址: