天天看點

Web Service (二) WSDL詳解

1.Web Service的一些相關概念

web service:遠端調用的一種方案。一種解決跨平台、跨語言間的分布式系統的內建(整合)方案

esb:enterprise service bus企業服務總線

soap:simple object access protocal簡單對象通路協定(http + xml)

soa:service oriented acrchietecture(面向服務的架構)

wsdl:web service description language ,web service 描述語言

2.WSDL詳解

大部分内容來自:http://www.ibm.com/developerworks/cn/webservices/ws-wsdl/index.html

 1)Web Service "Stack"

Web Service (二) WSDL詳解

       其中,綠色部分是先前已經定義好的并且廣泛使用的傳輸層和網絡層的标準:IP、HTTP、SMTP等。而藍色部分是目前開發的Web服務的相關标準協定,包括服務調用協定SOAP、服務描述協定WSDL和服務發現/內建協定UDDI,以及服務工作流描述語言WSFL。而橙色部分描述的是更高層的待開發的關于路由、可靠性以及事務等方面的協定。黃色部分是各個協定層的公用機制,這些機制一般由外部的正交機制來完成。

       其中,一個可以使用的Web服務應當按照需要選用若幹層次的功能,而無需所有的特性。但是無論如何為了實作一個一般意義上的Web服務,具備Web服務的基礎特性:跨平台調用和接口可機器識别,那麼必需使用WSDL和SOAP。SOAP是用來最終完成Web服務調用的,而WSDL則是用于描述如何使用SOAP來調用Web服務的。

      WSDL 是一種XML Application,他将Web服務描述定義為一組服務通路點,用戶端可以通過這些服務通路點對包含面向文檔資訊或面向過程調用的服務進行通路(類似遠端過程調用)。WSDL首先對通路的操作和通路時使用的請求/響應消息進行抽象描述,然後将其綁定到具體的傳輸協定和消息格式上以最終定義具體部署的服務通路點。相關的具體部署的服務通路點通過組合就成為抽象的Web服務。

      在具體使用中,我們可以對 WSDL 進行擴充(類似SOAP的可擴充性),這樣無論通信時使用何種消息格式或網絡協定,都可以對服務通路點及其使用的消息格式進行描述。在WSDL的架構中,可以使用任意的消息格式和網絡協定,如同SOAP中可以使用任意的網絡協定一樣。在WSDL規範中,定義了如何使用SOAP消息格式、HTTP GET/POST消息格式以及MIME格式來完成Web服務互動的規範。

2)WSDL概述

        由于通信協定和消息格式在 Web 技術圈子裡已經達到了标準化,我們知道在通常的開發過程中,對于對象的Interface一定具備相應的SDK描述文檔,Web服務也是一種對象,隻不過它是被部署在Web上而已。很自然的,我們也完全需要有對Web服務這個對象的界面的SDK描述文檔。然而這兩者又不盡相同,一來目前在Web上的應用已經完全接受了XML這個基本的标準,基本上所有新出台的技術都是基于XML标準的,二來Web服務的目标是即時裝配,松散耦合以及自動內建的,這意味着SDK描述文檔應當是具備被機器識别的能力的。

       也就是說,對于使用标準化的消息格式/通信協定的Web服務,它需要以某種結構化的方式(即XML)對Web服務的調用/通信加以描述,而且實作這一點也顯得非常重要,這是Web服務即時裝配的基本保證。WSDL正是這樣一種描述語言,WSDL 定義了一套基于 XML的 文法,将Web服務描述為能夠進行消息交換的服務通路點的集合,進而滿足了這種需求。WSDL 服務定義為分布式系統提供了可機器識别的SDK文檔,并且可用于描述自動執行應用程式通信中所涉及的細節。

        WSDL 文檔将Web服務定義為服務通路點或端口的集合。在 WSDL 中,由于服務通路點和消息的抽象定義已從具體的服務部署或資料格式綁定中分離出來,是以可以對抽象定義進行再次使用:消息,指對交換資料的抽象描述;而端口類型,指操作的抽象集合。用于特定端口類型的具體協定和資料格式規範構成了可以再次使用的綁定。将Web通路位址與可再次使用的綁定相關聯,可以定義一個端口,而端口的集合則定義為服務。是以,WSDL 文檔在Web服務的定義中使用下列元素:

  • Types - 資料類型定義的容器,它使用某種類型系統(一般地使用XML Schema中的類型系統)。
  • Message - 通信消息的資料結構的抽象類型化定義。使用Types所定義的類型來定義整個消息的資料結構。
  • Operation - 對服務中所支援的操作的抽象描述,一般單個Operation描述了一個通路入口的請求/響應消息對。
  • PortType - 對于某個通路入口點類型所支援的操作的抽象集合,這些操作可以由一個或多個服務通路點來支援。
  • Binding - 特定端口類型的具體協定和資料格式規範的綁定。
  • Port - 定義為協定/資料格式綁定與具體Web通路位址組合的單個服務通路點。
  • Service - 相關服務通路點的集合。

大家可以參考下圖,來了解一下WSDL文檔的結構組織:

Web Service (二) WSDL詳解

 其中,Types是一個資料類型定義的容器,包含了所有在消息定義中需要的XML元素的類型定義.

Message具體定義了在通信中使用的消息的資料結構,Message元素包含了一組Part元素,每個Part元素都是最終消息的一個組成部分,每個Part都會引用一個DataType來表示它的結構。Part元素不支援嵌套(可以使用DataType來完成這方面的需要),都是并列出現。

PortType具體定義了一種服務通路入口的類型,何謂通路入口的類型呢?就是傳入/傳出消息的模式及其格式。一個PortType可以包含若幹個Operation,而一個Operation則是指通路入口支援的一種類型的調用。在WSDL裡面支援四種通路入口調用的模式:

  1. 單請求;
  2. 單響應;
  3. 請求/響應;
  4. 響應/請求。

在這裡請求指的是從用戶端到Web服務端,而響應指的是從Web服務端到用戶端。PortType的定義中會引用消息定義部分的一個到兩個消息,作為請求或響應消息的格式。比如,一個股票查詢的通路入口可能就會支援兩種請求消息,一種請求消息中指明股票代碼,而另一種請求消息中則會指明股票的名稱,響應消息可能都是股票的價格等等。

以上三種結構描述了調用Web服務的抽象定義,這三部分與具體Web服務部署細節無關,是可複用的描述(每個層次都可以複用)。如果與一般的對象語言做比較的話,這部分可以堪稱是IDL描述的對象,描述了對象的接口标準,但是到底對象是用哪種語言實作,遵從哪種平台的細節規範,被部署在哪台機器上則是後面的元素所描述的。

Service描述的是一個具體的被部署的Web服務所提供的所有通路入口的部署細節,一個Service往往會包含多個服務通路入口,而每個通路入口都會使用一個Port元素來描述。

Port描述的是一個服務通路入口的部署細節,包括通過哪個Web位址(URL)來通路,應當使用怎樣的消息調用模式來通路等。其中消息調用模式則是使用Binding結構來表示。

Binding結構定義了某個PortType與某一種具體的網絡傳輸協定或消息傳輸協定相綁定,從這一層次開始,描述的内容就與具體服務的部署相關了。比如可以将PortType與SOAP/HTTP綁定,也可以将PortType與MIME/SMTP相綁定等。

在介紹了WSDL的主要元素之後,大家會發現,WSDL的設計理念完全繼承了以XML為基礎的當代Web技術标準的一貫設計理念:開放。WSDL允許通過擴充使用其他的類型定義語言(不光是XML Schema),允許使用多種網絡傳輸協定和消息格式(不光是在規範中定義的這些:SOAP/HTTP,HTTP-GET/POST以及MIME等)。同時WSDL也應用了當代軟體工程中的複用理念,分離了抽象定義層和具體部署層,使得抽象定義層的複用性大大增加。比如我們可以先使用抽象定義層為一類Web服務進行抽象定義(比如UDDI Registry,抽象定義肯定是完全一緻的遵循了UDDI規範),而不同的營運公司可以采用不同的具體部署層的描述結合抽象定義完成其自身的Web服務的描述。

3.WSDL文檔示例

下面的WSDL即為我上篇文章HelloWorld Webservice的描述文檔:

<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions name="HelloWorldService" targetNamespace="http://test.demo1/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://test.demo1/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <wsdl:types>
<xs:schema elementFormDefault="unqualified" targetNamespace="http://test.demo1/" version="1.0" xmlns:tns="http://test.demo1/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="sayHello" type="tns:sayHello"/>
<xs:element name="sayHelloResponse" type="tns:sayHelloResponse"/>
<xs:complexType name="sayHello">
<xs:sequence>
<xs:element minOccurs="0" name="arg0" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="sayHelloResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
  </wsdl:types>
  <wsdl:message name="sayHelloResponse">
    <wsdl:part element="tns:sayHelloResponse" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="sayHello">
    <wsdl:part element="tns:sayHello" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="HelloWorld">
    <wsdl:operation name="sayHello">
      <wsdl:input message="tns:sayHello" name="sayHello">
    </wsdl:input>
      <wsdl:output message="tns:sayHelloResponse" name="sayHelloResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="HelloWorldServiceSoapBinding" type="tns:HelloWorld">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="sayHello">
      <soap:operation soapAction="" style="document"/>
      <wsdl:input name="sayHello">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="sayHelloResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="HelloWorldService">
    <wsdl:port binding="tns:HelloWorldServiceSoapBinding" name="HelloWorldPort">
      <soap:address location="http://localhost:8080/helloWorld"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>      

         Web service中一個wsdl對應一個web service位址,可以想象成一個商店,商店裡面出售很多手機(portTypes),每個手機上有很多功能(opeations),每個功能對應很多輸入和輸出參數(message)  

  這裡沒有類,隻有端口。。。沒有方法,隻有端口裡面的操作,沒有參數,隻有傳遞給端口中某個操作的消息  

 xml文檔第一句:

definitions--WSDL文檔的根元素,該元素的屬性指明了wsdl文檔的名稱,文檔的目标名字空間,以及WSDL文檔應用的名字空間的速記定義。它指明了此WebService的名稱為:HelloWorldImplService

然後找到名為“HelloWorldImplService”的service具體定義如下所示:

<wsdl:service name="HelloWorldImplService">
     <wsdl:port binding="tns:HelloWorldImplServiceSoapBinding" name="HelloWorldImplPort">
        <soap:address location="http://localhost:8080/helloWorld" /> 
    </wsdl:port>
 </wsdl:service>      

       service---相關port元素的集合,使用者組織endpoint定義。

port--通過binding和實體位址定義的endpoint,這個元素将所有抽象定義聚集在一起

 這部分是具體的Web服務的定義,在這個名為 HelloWorldImplService的Web服務中,提供了一個服務通路入口,通路位址是"http://localhost:8080/helloWorld",使用的消息模式是由前面的binding

“HelloWorldImplServiceSoapBinding”所定義的。

<wsdl:binding name="HelloWorldImplServiceSoapBinding" type="tns:HelloWorld">
  <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> 
    <wsdl:operation name="sayHello">
       <soap:operation soapAction="" style="document" /> 
      <wsdl:input name="sayHello">
         <soap:body use="literal" /> 
      </wsdl:input>
    <wsdl:output name="sayHelloResponse">
      <soap:body use="literal" /> 
    </wsdl:output>
  </wsdl:operation>
 </wsdl:binding>       

         binding---一個endpoint的實際資料格式說明,一個binding元素定義如何将一個抽象消息映射到一個具體資料格式。該元素指明諸如參數順序,傳回值等資訊。           

       每個被支援的資訊格式和資訊傳送方式組合,就叫做 binding  (就是如果你要和商店裡的服務員溝通,那麼你們必須規定好用什麼語言溝通,binging就是把某個服務員(比如銷售nokia的服務員)和某種語言綁定wsdlsoap:binding 就是用 soap語言通話  )

      這段xml定義的操作“sayHello”使用的是SoapDocumentProtocol消息格式(style="document")。輸入和輸出參數格式都是“Literal”(use="literal")

關于:SQAP的消息格式可以參考文章:http://www.cnblogs.com/linyawen/archive/2011/07/20/2111177.html

<wsdl:portType name="HelloWorld">
  <wsdl:operation name="sayHello">
  <wsdl:input message="tns:sayHello" name="sayHello" /> 
  <wsdl:output message="tns:sayHelloResponse" name="sayHelloResponse" /> 
  </wsdl:operation>
  </wsdl:portType>
      

 portType---描述服務邏輯接口的operation元素的集合。HelloWorld隻有一個操作sayHello.

     這部分定義了服務通路點的調用模式的類型,表明 HelloWorld Service的sayHello入口類型是請求/響應模式,請求消息是sayHello,而響應消息是sayHelloResponse。

<wsdl:message name="sayHelloResponse">
     <wsdl:part element="tns:sayHelloResponse" name="parameters" /> 
  </wsdl:message>
   <wsdl:message name="sayHello">
        <wsdl:part element="tns:sayHello" name="parameters" /> 
  </wsdl:message>      

 這部分是消息格式的抽象定義,其中定義了兩個消息格式:

  • sayHelloResponse( 響應消息格式 ): 由一個消息片斷組成,該消息片斷的名字是parameters,包含的具體元素類型是sayHelloResponse。
  • sayHello( 請求消息格式 ) : 由一個消息片斷組成,該消息片斷的名字是 parameters ,包含的具體元素類型是sayHello。
<xs:element name="sayHello" type="tns:sayHello" /> 
  <xs:element name="sayHelloResponse" type="tns:sayHelloResponse" /> 
 <xs:complexType name="sayHello">
 <xs:sequence>
     <xs:element minOccurs="0" name="arg0" type="xs:string" /> 
  </xs:sequence>
  </xs:complexType>
 <xs:complexType name="sayHelloResponse">
   <xs:sequence>
      <xs:element minOccurs="0" name="return" type="xs:string" /> 
    </xs:sequence>
  </xs:complexType>
      

上面這部分是資料類型的定義,其中為定義了兩個元素的結構:

  • sayHello(請求參數的類型): 将該元素定義為包含一個字元串元素(arg0)的複合類型元素。
  • sayHelloResponse(響應參數的類型):  将該元素定義為包含一個字元串元素(return)的複合類型元素。
<xs:element minOccurs="0" name="arg0" type="xs:string" />       

     <xs:element minOccurs="0" name="return" type="xs:string" /> 

其中的name="arg0", name="return"中的“arg0”,“return”是可以指定的,因為我前面一章的HelloWorld輸入輸出參數都是使用的預設的參數名,是以生成的xml是這樣子。

如果HelloWorld接口中的方法修改成

public @WebResult(name="responseResult")String sayHello(@WebParam(name="name")String name) ;
           

 也就是給輸入參數與傳回結果指定一個標明的名字,則生成的xml如下所示:

<xs:complexType name="sayHello">
<xs:sequence>
<xs:element minOccurs="0" name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="sayHelloResponse">
<xs:sequence>
<xs:element minOccurs="0" name="responseResult" type="xs:string"/>
</xs:sequence>
</xs:complexType>      

4.請求及響應的具體消息格式如下所示:

請求消息:

- <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://test.demo1/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <soapenv:Body>
- <q0:sayHello>
  <arg0>xxl</arg0> 
  </q0:sayHello>
  </soapenv:Body>
  </soapenv:Envelope>      

 響應消息:

- <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
- <soap:Body>
- <sayHelloResponse xmlns:ns2="http://test.demo1/">
  <return>hello xxl</return> 
  </sayHelloResponse>
  </soap:Body>
  </soap:Envelope>      

繼續閱讀