編程學習網 > PHP技術 > WSDL : 描述你的Web服務——WSDL詳解
2015
06-30

WSDL : 描述你的Web服務——WSDL詳解

一、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 描述語言

二、WSDL詳解

1)Web Service "Stack"

Web Service Stack

其中,綠色部分是先前已經定義好的并且廣泛使用的傳輸層和網絡層的標準: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文檔的結構組織:

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服務的描述。

一個web services要被其它應用調用,就必須告訴其它應用如何去調用web services中的webmethod,比如這個web services中包含哪些可以調用的方法,每個方法的方法簽名是怎樣的,方法是用的輸入輸出參數的類型又是什么等等,這些都是通過web services的WSDL來進行描述的。

要查看一個web services的WSDL可以向web services所在的asmx文件的URL發送http請求,并附帶?wsdl參數即可,比如:http://biztalkr2:81/WSTest/Service1.asmx?WSDL

來查看一下上面這個web services的WSDL中跟TwoWayMethod相關的部分:

WSDL中跟TwoWayMethod相關的部分

這個WSDL的結構需要按照從下面往上面的順序看。

portType

portType標簽用來描述整個的web services,portType的name屬性即為這個web services類的類名。這個標簽下包含了所有的可用方法,每個operation標簽表示一個方法。

operation

每一個operation標簽表示web services里的一個webmethod方法,operation標簽的name屬性是這個webmethod的方法名。

Input和output

Input和output標簽分別表示一個operation(webmethod方法)的輸入和輸出的參數集合,這里叫做消息,不管輸入參數有幾個,每個參數有多么復雜,只有一個表示這些輸入參數的消息,就是input標簽的message屬性表示的那個消息。對于輸出消息也一樣。

Message

方法的輸入輸出參數都用一個消息來表示,message標簽表示一個這樣的消息,message標簽按下面有個part標簽,用來具體指示這個消息在schema中的類型,類型以element形式表現出來,即part標簽的element屬性指定的那個element。

對于輸入參數消息,part標簽的element屬性命名同webmethod方法名。

對于輸出參數消息,part標簽的element屬性命名同webmethod方法名 + response。

表示類型的element都被集中放置在types標簽內。

types標簽

此標簽用來描述所有webmethod所要用到的類型,都以element來描述類型。比如:

public string[] TwoWayMethod(float a,Person person)

這個webmethod的輸入參數有兩個:float a,Person person,在WSDL的中的類型表現是這樣的:

<s:element name="TwoWayMethod">
    <s:complexType>
        <s:sequence>
            <s:element minOccurs="1" maxOccurs="1" name="a" type="s:float" />
            <s:element minOccurs="0" maxOccurs="1" name="person" type="tns:Person" />
        </s:sequence>
    </s:complexType>
</s:element>

其中a元素是簡單的float類型,不需要另加說明。

person元素是Person類型,Person類型又是個complex類型,在types標簽里還包括了這個Person類型的定義。只要是消息中引用到的非簡單類型,都需要在types中進行定義描述。

三、WSDL文檔示例

下例是一個提供股票報價的簡單Web服務的 WSDL 定義。該服務支持名為 GetLastTradePrice 的單一操作,這個操作是通過在 HTTP 上運行 SOAP 1.1 協議來實現的。該請求接受一個類型為字符串的 tickerSymbol,并返回類型為浮點數的價格。

<?xml version="1.0"?>
<definitions name="StockQuote" 
             targetNamespace="http://example.com/stockquote.wsdl"
             xmlns:tns="http://example.com/stockquote.wsdl"
             xmlns:xsd1="http://example.com/stockquote.xsd"
             xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
             xmlns="http://schemas.xmlsoap.org/wsdl/">
             
 
  <types>
    <schema targetNamespace="http://example.com/stockquote.xsd"
            xmlns="http://www.w3.org/1999/XMLSchema">
      <element name="TradePriceRequest">
        <complexType>
          <all>
            <element name="tickerSymbol" type="string"/>
          </all>
        </complexType>
      </element>
      <element name="TradePriceResult">
        <complexType>
          <all>
            <element name="price" type="float"/>
          </all>
        </complexType>
      </element>
    </schema>
  </types>

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

  • TradePriceRequest(交易價格請求): 將該元素定義為包含一個字符串元素(tickerSymbol)的復合類型元素。
  • TradePriceResult(交易價格): 將該元素定義為一個包含一個浮點數元素(price)的復合類型元素。
 <message name="GetLastTradePriceInput">
    <part name="body" element="xsd1:TradePriceRequest"/>
  </message>
 
  <message name="GetLastTradePriceOutput">
    <part name="body" element="xsd1:TradePriceResult"/>
  </message>

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

  • GetlastTradePriceInput(獲取最后交易價格的請求消息格式): 由一個消息片斷組成,該消息片斷的名字是body,包含的具體元素類型是TradePriceRequest。(前面已經定義過了)
  • GetLastTradePriceOutput(獲取最后交易價格的響應消息格式) : 由一個消息片斷組成,該消息片斷的名字是body,包含的具體元素類型是TradePriceResult。(前面已經定義過了)
 <portType name="StockQuotePortType">
    <operation name="GetLastTradePrice">
      <input message="tns:GetLastTradePriceInput"/>
      <output message="tns:GetLastTradePriceOutput"/>
    </operation>
  </portType>

這部分定義了服務訪問點的調用模式的類型,表明StockQuoteService的某個入口類型是請求/響應模式,請求消息是GetlastTradePriceInput,而響應消息是GetLastTradePriceOutput。

 <binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
      <operation name="GetLastTradePrice">
        <soap:operation soapAction="http://example.com/GetLastTradePrice"/>
          <input>
            <soap:body use="literal" namespace="http://example.com/stockquote.xsd"
                       encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
          </input>
          <output>
            <soap:body use="literal" namespace="http://example.com/stockquote.xsd"
                       encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
          </output>
        </soap:operation>
      </operation>
    </soap:binding>
  </binding>

這部分將服務訪問點的抽象定義與SOAP HTTP綁定,描述如何通過SOAP/HTTP來訪問按照前面描述的訪問入口點類型部署的訪問入口。其中規定了在具體SOAP調用時,應當使用的soapAction是"http://example.com/GetLastTradePrice",而請求/響應消息的編碼風格都應當采用SOAP規范默認定義的編碼風格" http://schemas.xmlsoap.org/soap/encoding/"。

 <service name="StockQuoteService">
    <documentation>股票查詢服務</documentation> 
    <port name="StockQuotePort" binding="tns:StockQuoteBinding">
    <soap:address location="http://example.com/stockquote"/>
    </port>
  </service>
 
</definitions>

這部分是具體的Web服務的定義,在這個名為StockQuoteService的Web服務中,提供了一個服務訪問入口,訪問地址是"http://example.com/stockquote",使用的消息模式是由前面的binding所定義的。

按照這個WSDL文檔的描述,在具體Web服務的使用中,具體發生的SOAP交互可能如下面所示:

SOAP消息請求:

POST /StockQuote HTTP/1.1
Host: example.com
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn
SOAPAction: "http://example.com/GetLastTradePrice"

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
                   SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body>
    <m:TradePriceRequest xmlns:m="http://example.com/stockquote.xsd">
      <tickerSymbol>MSFT</tickerSymbol >
    </m:TradePriceRequest>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

SOAP消息響應:

HTTP/1.1 200 OK
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
                   SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  <SOAP-ENV:Body>
    <m:TradePriceResult xmlns:m=" http://example.com/stockquote.xsd ">
      <price>74.5</price>
    </m:TradePriceResult >
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

掃碼二維碼 獲取免費視頻學習資料

Python編程學習

查 看2022高級編程視頻教程免費獲取