轉自:http://blog.csdn.net/etttttss/article/details/17303315
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"
其中,綠色部分是先前已經定義好的并且廣泛使用的傳輸層和網絡層的標準: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的結構需要按照從下面往上面的順序看。
portType標簽用來描述整個的web services,portType的name屬性即為這個web services類的類名。這個標簽下包含了所有的可用方法,每個operation標簽表示一個方法。
每一個operation標簽表示web services里的一個webmethod方法,operation標簽的name屬性是這個webmethod的方法名。
Input和output標簽分別表示一個operation(webmethod方法)的輸入和輸出的參數集合,這里叫做消息,不管輸入參數有幾個,每個參數有多么復雜,只有一個表示這些輸入參數的消息,就是input標簽的message屬性表示的那個消息。對于輸出消息也一樣。
方法的輸入輸出參數都用一個消息來表示,message標簽表示一個這樣的消息,message標簽按下面有個part標簽,用來具體指示這個消息在schema中的類型,類型以element形式表現出來,即part標簽的element屬性指定的那個element。
對于輸入參數消息,part標簽的element屬性命名同webmethod方法名。
對于輸出參數消息,part標簽的element屬性命名同webmethod方法名 + response。
表示類型的element都被集中放置在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中進行定義描述。
3.WSDL文檔示例
下面的WSDL即為我上篇文章HelloWorld Webservice的描述文檔:
Xml代碼
<?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具體定義如下所示:
Xml代碼
<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”所定義的。
Xml代碼
<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
Xml代碼
<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。
Xml代碼
<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。
Xml代碼
<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)的復合類型元素。Xml代碼
<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接口中的方法修改成
java代碼
public @WebResult(name="responseResult")String sayHello(@WebParam(name="name")String name) ; 也就是給輸入參數與返回結果指定一個選定的名字,則生成的xml如下所示:
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.請求及響應的具體消息格式如下所示:
請求消息:
Xml代碼
- <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> 響應消息:
Xml代碼
- <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> 新聞熱點
疑難解答