WSDL 詳解
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"
其中,綠色部分是先前已經定義好的並且廣泛使用的傳輸層和網絡層的標準: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文檔的結構組織:
其中,Types是一個數據類型定義的容器,包含了所有在消息定義中需要的XML元素的類型定義.
Message具體定義了在通信中使用的消息的數據結構,Message元素包含了一組Part元素,每個Part元素都是最終消息的一個組成部分,每個Part都會引用一個DataType來表示它的結構。Part元素不支持嵌套(可以使用DataType來完成這方面的需要),都是並列出現。
PortType具體定義了一種服務訪問入口的類型,何謂訪問入口的類型呢?就是傳入/傳出消息的模式及其格式。一個PortType可以包含若干個Operation,而一個Operation則是指訪問入口支持的一種類型的調用。在WSDL裏面支持四種訪問入口調用的模式:
- 單請求;
- 單響應;
- 請求/響應;
- 響應/請求。
在這裏請求指的是從客戶端到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相關的部分:
Figue 1. WSDL中跟TwoWayMethod相關的部分
這個WSDL的結構需要按照從下面往上面的順序看。
2.1. portType標籤
portType標籤用來描述整個的web services,portType的name屬性即爲這個web services類的類名。這個標籤下包含了所有的可用方法,每個operation標籤表示一個方法。
2.2. operation標籤
每一個operation標籤表示web services裏的一個webmethod方法,operation標籤的name屬性是這個webmethod的方法名。
2.3. Input和output標籤
Input和output標籤分別表示一個operation(webmethod方法)的輸入和輸出的參數集合,這裏叫做消息,不管輸入參數有幾個,每個參數有多麼複雜,只有一個表示這些輸入參數的消息,就是input標籤的message屬性表示的那個消息。對於輸出消息也一樣。
2.4. Message標籤
方法的輸入輸出參數都用一個消息來表示,message標籤表示一個這樣的消息,message標籤按下面有個part標籤,用來具體指示這個消息在schema中的類型,類型以element形式表現出來,即part標籤的element屬性指定的那個element。
對於輸入參數消息,part標籤的element屬性命名同webmethod方法名。
對於輸出參數消息,part標籤的element屬性命名同webmethod方法名 + response。
表示類型的element都被集中放置在types標籤內。
2.5. 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即爲我上篇文章HelloWorld Webservice的描述文檔:
Web service中一個wsdl對應一個web service地址,可以想象成一個商店,商店裏面出售很多手機(portTypes),每個手機上有很多功能(opeations),每個功能對應很多輸入和輸出參數(message)
這裏沒有類,只有端口。。。沒有方法,只有端口裏面的操作,沒有參數,只有傳遞給端口中某個操作的消息
xml文檔第一句:
definitions--WSDL文檔的根元素,該元素的屬性指明瞭wsdl文檔的名稱,文檔的目標名字空間,以及WSDL文檔應用的名字空間的速記定義。它指明瞭此WebService的名稱爲:HelloWorldImplService
然後找到名爲“HelloWorldImplService”的service具體定義如下所示:
service---相關port元素的集合,用戶組織endpoint定義。
port--通過binding和物理地址定義的endpoint,這個元素將所有抽象定義聚集在一起
這部分是具體的Web服務的定義,在這個名爲 HelloWorldImplService的Web服務中,提供了一個服務訪問入口,訪問地址是"http://localhost:8080/helloWorld",使用的消息模式是由前面的binding
“HelloWorldImplServiceSoapBinding”所定義的。
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
portType---描述服務邏輯接口的operation元素的集合。HelloWorld只有一個操作sayHello.
這部分定義了服務訪問點的調用模式的類型,表明 HelloWorld Service的sayHello入口類型是請求/響應模式,請求消息是sayHello,而響應消息是sayHelloResponse。
這部分是消息格式的抽象定義,其中定義了兩個消息格式:
- sayHelloResponse( 響應消息格式 ): 由一個消息片斷組成,該消息片斷的名字是parameters,包含的具體元素類型是sayHelloResponse。
- sayHello( 請求消息格式 ) : 由一個消息片斷組成,該消息片斷的名字是 parameters ,包含的具體元素類型是sayHello。
上面這部分是數據類型的定義,其中爲定義了兩個元素的結構:
- sayHello(請求參數的類型): 將該元素定義爲包含一個字符串元素(arg0)的複合類型元素。
- sayHelloResponse(響應參數的類型): 將該元素定義爲包含一個字符串元素(return)的複合類型元素。
<xs:element minOccurs="0" name="return" type="xs:string" />
其中的name="arg0", name="return"中的“arg0”,“return”是可以指定的,因爲我前面一章的HelloWorld輸入輸出參數都是使用的默認的參數名,所以生成的xml是這樣子。
如果HelloWorld接口中的方法修改成
也就是給輸入參數與返回結果指定一個選定的名字,則生成的xml如下所示:
4.請求及響應的具體消息格式如下所示:
請求消息:
響應消息: