wsdl 与 soap协议详解
一、WSDL語言:(web service definition language - web service定義語言)
(一)簡介:
1、wsdl 是全完基于xml 的,特別是xml schema。詳見:?XML學習筆記(三):XML規范:Schema詳解。
2、wsdl 文檔描述了 ws 主要的3個方面:
1)WHATA:該 ws 包含”什么“操作,即有幾個方法。
2)HOW:該 ws 的操作應該”怎樣“調用?
3)WHERE:該 ws 的服務地址。
3、詳細的 wsdl 文件如下,給予Web Service筆記(二):利用CXF開發Web Service?的服務和客戶端。
1)實現類的 wsdl 地址為:http://localhost:8080/helloWorld?wsdl?。內容如下:
This XML file does not appear to have any style information associated with it. The document tree is shown below. <wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://impl.ws.com/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns2="http://schemas.xmlsoap.org/soap/http" xmlns:ns1="http://ws.com/" name="HelloSAM" targetNamespace="http://impl.ws.com/"> <wsdl:import location="http://localhost:8080/helloWorld?wsdl=HelloWorld.wsdl" namespace="http://ws.com/"></wsdl:import> <wsdl:binding name="HelloSAMSoapBinding" type="ns1:HelloWorld"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="sayHi"> <soap:operation soapAction="" style="document"/> <wsdl:input name="sayHi"> <soap:body use="literal"/> </wsdl:input> <wsdl:output name="sayHiResponse"> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="getCatsByUser"> <soap:operation soapAction="" style="document"/> <wsdl:input name="getCatsByUser"> <soap:body use="literal"/> </wsdl:input> <wsdl:output name="getCatsByUserResponse"> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="HelloSAM"> <wsdl:port binding="tns:HelloSAMSoapBinding" name="HelloWorldImplPort"> <soap:address location="http://localhost:8080/helloWorld"/> </wsdl:port> </wsdl:service> </wsdl:definitions>? 2)接口的 wsdl 地址為: http://localhost:8080/helloWorld?wsdl=HelloWorld.wsdl ? 。內容如下:?
This XML file does not appear to have any style information associated with it. The document tree is shown below. <wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ns1="http://ws.com/" name="HelloWorld" targetNamespace="http://ws.com/"> <wsdl:types> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://ws.com/" elementFormDefault="unqualified" targetNamespace="http://ws.com/" version="1.0"> <xs:element name="getCatsByUser" type="tns:getCatsByUser"/> <xs:element name="getCatsByUserResponse" type="tns:getCatsByUserResponse"/> <xs:element name="sayHi" type="tns:sayHi"/> <xs:element name="sayHiResponse" type="tns:sayHiResponse"/> <xs:complexType name="sayHi"> <xs:sequence> <xs:element minOccurs="0" name="arg0" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:complexType name="sayHiResponse"> <xs:sequence> <xs:element minOccurs="0" name="return" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:complexType name="getCatsByUser"> <xs:sequence> <xs:element minOccurs="0" name="arg0" type="tns:user"/> </xs:sequence> </xs:complexType> <xs:complexType name="user"> <xs:sequence> <xs:element minOccurs="0" name="address" type="xs:string"/> <xs:element minOccurs="0" name="id" type="xs:int"/> <xs:element minOccurs="0" name="name" type="xs:string"/> <xs:element minOccurs="0" name="pass" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:complexType name="getCatsByUserResponse"> <xs:sequence> <xs:element maxOccurs="unbounded" minOccurs="0" name="return" type="tns:cat"/> </xs:sequence> </xs:complexType> <xs:complexType name="cat"> <xs:sequence> <xs:element minOccurs="0" name="color" type="xs:string"/> <xs:element minOccurs="0" name="id" type="xs:int"/> <xs:element minOccurs="0" name="name" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:schema> </wsdl:types> <wsdl:message name="getCatsByUserResponse"> <wsdl:part element="ns1:getCatsByUserResponse" name="parameters"></wsdl:part> </wsdl:message> <wsdl:message name="sayHiResponse"> <wsdl:part element="ns1:sayHiResponse" name="parameters"></wsdl:part> </wsdl:message> <wsdl:message name="getCatsByUser"> <wsdl:part element="ns1:getCatsByUser" name="parameters"></wsdl:part> </wsdl:message> <wsdl:message name="sayHi"> <wsdl:part element="ns1:sayHi" name="parameters"></wsdl:part> </wsdl:message> <wsdl:portType name="HelloWorld"> <wsdl:operation name="sayHi"> <wsdl:input message="ns1:sayHi" name="sayHi"></wsdl:input> <wsdl:output message="ns1:sayHiResponse" name="sayHiResponse"></wsdl:output> </wsdl:operation> <wsdl:operation name="getCatsByUser"> <wsdl:input message="ns1:getCatsByUser" name="getCatsByUser"></wsdl:input> <wsdl:output message="ns1:getCatsByUserResponse" name="getCatsByUserResponse"></wsdl:output> </wsdl:operation> </wsdl:portType> </wsdl:definitions>
(二)語法詳解:
1、根元素:definitions?
1)targetNamespace :相當于java的?package 。
如 服務端實現類與 wsdl 文件的?targetNamespace?為 如下,應該是一致的。
package com.ws.impl;//實現類的包 targetNamespace="http://impl.ws.com/"//wsdl的targetNamespace
2)xmlns :遵守的命名空間的schema 文件,相當于java的?import 。即本文檔引進了這個schema規范,需要遵守它的語法。可以有別名,用來區分引進不同的schema規范。
xmlns:xsd="http://www.w3.org/2001/XMLSchema"//xsd為別名
3)import :導入的接口文件。通過 namespase的路徑也可以看出。
<wsdl:import location="http://localhost:8080/helloWorld?wsdl=HelloWorld.wsdl" namespace="http://ws.com/"></wsdl:import>
2、WS接口的wsdl語法。wsdl 顯示的服務端內容都在此。
1)types元素 :該元素內容是標準的xml Schema文檔 。
<wsdl:types> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://ws.com/" elementFormDefault="unqualified" targetNamespace="http://ws.com/" version="1.0"> <xs:element name="getCatsByUser" type="tns:getCatsByUser"/> <xs:element name="getCatsByUserResponse" type="tns:getCatsByUserResponse"/> <xs:element name="sayHi" type="tns:sayHi"/> <xs:element name="sayHiResponse" type="tns:sayHiResponse"/> <xs:complexType name="sayHi"> <xs:sequence> <xs:element minOccurs="0" name="arg0" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:complexType name="sayHiResponse"> <xs:sequence> <xs:element minOccurs="0" name="return" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:complexType name="getCatsByUser"> <xs:sequence> <xs:element minOccurs="0" name="arg0" type="tns:user"/> </xs:sequence> </xs:complexType> <xs:complexType name="user"> <xs:sequence> <xs:element minOccurs="0" name="address" type="xs:string"/> <xs:element minOccurs="0" name="id" type="xs:int"/> <xs:element minOccurs="0" name="name" type="xs:string"/> <xs:element minOccurs="0" name="pass" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:complexType name="getCatsByUserResponse"> <xs:sequence> <xs:element maxOccurs="unbounded" minOccurs="0" name="return" type="tns:cat"/> </xs:sequence> </xs:complexType> <xs:complexType name="cat"> <xs:sequence> <xs:element minOccurs="0" name="color" type="xs:string"/> <xs:element minOccurs="0" name="id" type="xs:int"/> <xs:element minOccurs="0" name="name" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:schema> </wsdl:types>
? ??
2)message元素:有2N個message元素,需要有傳入傳出消息。如服務端方法public String sayHi(String name){}方法:
<wsdl:message name="getCatsByUserResponse"> <wsdl:part element="ns1:getCatsByUserResponse" name="parameters"></wsdl:part> </wsdl:message> <wsdl:message name="sayHiResponse"> <wsdl:part element="ns1:sayHiResponse" name="parameters"></wsdl:part> </wsdl:message> <wsdl:message name="getCatsByUser"> <wsdl:part element="ns1:getCatsByUser" name="parameters"></wsdl:part> </wsdl:message> <span style="color:#ff0000;"><wsdl:message name="sayHi"> <wsdl:part element="ns1:sayHi" name="parameters"></wsdl:part> </wsdl:message></span>
①、message 元素中有name等于?sayHi 的屬性。可以理解為 一個?sayHi 的消息。
②、子元素 part中有element屬性為?sayHi 。理解為?sayHi的消息需要一個?sayHi 的元素(element)。這個元素在上面的 type 中會有定義。
3)portType元素: N個operation子元素,每個operation代表一個ws操作(即方法),包含請求與回復2次。
<wsdl:portType name="HelloWorld"> <wsdl:operation name="sayHi"> <wsdl:input message="ns1:sayHi" name="sayHi"></wsdl:input> <wsdl:output message="ns1:sayHiResponse" name="sayHiResponse"></wsdl:output> </wsdl:operation> <wsdl:operation name="getCatsByUser"> <wsdl:input message="ns1:getCatsByUser" name="getCatsByUser"></wsdl:input> <wsdl:output message="ns1:getCatsByUserResponse" name="getCatsByUserResponse"></wsdl:output> </wsdl:operation> </wsdl:portType>
①、服務端有兩個操作的方法?sayHi() 和?getCatsByUser() ,在?portType 元素中就會有 2個?operation ,分別為?sayHi 和?getCatsByUser 。
②、每個?operation元素中有input 和 output 子元素,定義了這次操作需要的 message元素信息,在上面定義。
4)顯而易見,這邊有一定的依賴關系存在:一個 WS 服務端實現類,定義了多個方法(operation元素),方法的調用需要明確傳入傳出參數,被定義在message元素中,稱為消息。每個定義的消息有依賴于element元素,定義在 types 中,是一份標準的 schema。
5)整個接口的?wsdl 由于上述依賴的關系,可以倒過來分析:如方法public List<Cat> getCatsByUser(User user) {},其實其本質規定了調用該方法傳入參數的類型與規范。
①、一個接口,定義方法為?getCatsByUser。wsdl 定義為:一個?portType 為?HelloWorld 的接口,有名為?getCatsByUser?的?operation,即有這個方法可調用。這個方法需要name為?getCatsByUser? 和 getCatsByUserResponse?的 message 元素(input 和 output ),代表了這個方法的傳入與傳出消息(即方法的參數)。
②、方法的傳入傳出參數。message 元素中規定這個?getCatsByUser? 的傳入消息實際內容在名為?getCatsByUser?的element元素中,element元素定義在types元素中。
③、element元素中規定?getCatsByUser? 遵守名字為getCatsByUser? 的schema語法定義,使用type關鍵字實現sechema語法的復用。
④、名字為?getCatsByUser? 的?schema定義為:complex為復雜類型,0-1個,sequesce指要有順序,type指向名字為 user 的schema定義。
⑤、名字為?user?的?schema定義為: 有順利的四個元素,分別為address、id、name、pass,出現0-1次。
4、本質:一個ws,其實并不是方法的調用,而是發送soap消息(即xml文檔片段)
1)客戶端把調用的方法參數,轉換生成xml文檔片段(soap消息)??必須符合wsdl規定的格式
2)客戶端通過網絡,把xml文檔片段傳給服務器。
3)服務器接收到xml文檔片段。
4)服務器解析xml文檔片段,提取其中的數據。返回xml文檔。
如getCatsByUser(User user) 方法,傳入傳出的是這樣的xml片段:
<!--傳入的參數--> <getCatsByUser><arg0><address></address><id></id><name></name><pass></pass></arg0> </getCatsByUser><!--返回的參數--> <getCatsByUserResponse><return><color></color><id></id><name></name></return><return><color></color><id></id><name></name></return> </getCatsByUserResponse>
3、WS實現類:
1)、binding:指定ws的函數風格,并詳細的定義了接口中的操作即?operation?。函數風格,現在一般為 document 文檔風格。
<wsdl:binding name="HelloSAMSoapBinding" type="ns1:HelloWorld"> <soap:binding <span style="color:#ff0000;">style="document" </span>transport="http://schemas.xmlsoap.org/soap/http"/> <<span style="color:#ff0000;">wsdl:operation </span>name="sayHi"> <soap:operation soapAction="" style="document"/> <wsdl:input name="sayHi"> <soap:body use="literal"/> </wsdl:input> <wsdl:output name="sayHiResponse"> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="getCatsByUser"> <soap:operation soapAction="" style="document"/> <wsdl:input name="getCatsByUser"> <soap:body use="literal"/> </wsdl:input> <wsdl:output name="getCatsByUserResponse"> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding>
2)、service:name-定義了ws的名稱,即代碼中使用?serviceName 指定的名稱,port【address】-定義ws綁定的地址。
<wsdl:service name="HelloSAM"> <wsdl:port binding="tns:HelloSAMSoapBinding" name="HelloWorldImplPort"> <soap:address location="http://localhost:8080/helloWorld"/> </wsdl:port> </wsdl:service>
二、SOAP語言(簡單訪問對象協議)
(一)通過使用CXF的日志攔截器,我們可以在控制臺輸出攔截器的soap消息。服務端攔截如下:
1、sayHi()操作的soap消息:
傳入:Headers: {Accept=[text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2], connection=[keep-alive], Content-Length=[186], content-type=[text/xml; charset=UTF-8], Host=[localhost:8080], SOAPAction=[""], User-Agent=[Java/1.6.0_10-rc2]}Payload: <?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:sayHi xmlns:ns2="http://ws.com/"><arg0>SAM-SHO</arg0></ns2:sayHi></S:Body></S:Envelope>傳出:Headers: {}Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHiResponse xmlns:ns2="http://ws.com/"><return>SAM-SHO,您好!您現在訪問的是簡單的WS服務端,時間為:14-11-20 下午1:28</return></ns2:sayHiResponse></soap:Body></soap:Envelope>
2、getCatsByUser()操作的soap消息:與上面wsdl分析的消息應該是一致的。
傳入:<?xml version="1.0" ?> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:getCatsByUser xmlns:ns2="http://ws.com/"><arg0><address>soochow</address><id>1</id><name>Sam-Sho</name><pass>1234</pass></arg0></ns2:getCatsByUser></S:Body> </S:Envelope>傳出: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:getCatsByUserResponse xmlns:ns2="http://ws.com/"><return><color>黃色</color><id>1</id><name>加菲貓</name></return><return><color>藍色</color><id>2</id><name>藍胖子</name></return><return><color>粉色</color><id>3</id><name>hello kitty</name></return><return><color>黑白色</color><id>4</id><name>熊貓</name></return></ns2:getCatsByUserResponse></soap:Body> </soap:Envelope>
(二)soap語法
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header><!--可能會有Header元素--></soap:Header><soap:Body><ns2:sayHiResponse xmlns:ns2="http://ws.com/"><return>SAM-SHO,您好!您現在訪問的是簡單的WS服務端,時間為:14-11-20 下午1:28</return></ns2:sayHiResponse></soap:Body></soap:Envelope>
1、根元素:Envelope。
2、Header元素::不是強制出現,由程序員控制,主要用于攜帶一些額外的信息,比如用戶名、密碼
3、Body:
1)調用正確,body元素內容應該遵守WSDL要求的格式。
2)調用錯誤,body元素內容顯示Faulty元素。
<soap:Fault> <faultcode>soap:Server</faultcode> <faultstring> No binding operation info while invoking unknown method with params unknown. </faultstring> </soap:Fault> </soap:Body>
4、return:返回信息。
三、UDDI(可以省略)
總結
以上是生活随笔為你收集整理的wsdl 与 soap协议详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BASISI系统中如何配置web ser
- 下一篇: 同步系统和北京时间