當前位置:才華齋>設計>網頁設計>

Web Service的開發與應用基礎

網頁設計 閱讀(3.27W)

Web Service基於SOAP協議,而SOAP本身符合XML語法規範。雖然為Web Service提供了強大的支援,但瞭解其基本機制對於程式設計師來說仍然是必需的。

Web Service的開發與應用基礎

  1.1 神馬是SOAP協議?

SOAP協議的全稱是簡單物件訪問協議(Simple Object Access Protocol),SOAP致力於以XML形式提供一個簡單、輕量的用於在分散或分佈環境中交換結構化和型別資訊的機制。SOAP只規範物件訪問的方式,而不限制具體實現的技術環境,這意味著SOAP協議是一種跨平臺的協議:一個客戶端程式可以按照SOAP協議訪問一個基於JavaEE技術體系結構的Web Service。SOAP訪問仍然基於HTTP協議,同時其內容又以XML形式展現。

SOAP規範由四部分組成:

① SOAP信封(SOAP envelop)

② SOAP編碼規則(SOAP encoding rules)

③ SOAP RPC表示(SOAP RPC representation)

④ SOAP繫結(SOAP binding)

這裡不對這四部分展開介紹,通過下面的一個小例子來直觀地認識一下。

(1)在Web服務端,打算對外提供一個公共方法來供客戶端呼叫,而客戶端則需要提供這個方法需要的引數,並且最終得到返回值。假設這個方法被申明在檔案中:

[WebMethod]

public string GetSumString(int para1, int para2)

{

int result = para1 + para2;

return ring();

}

(2)當客戶端試圖使用這個Web Service方法時,就需要向伺服器端發出這樣的一個HTTP請求:

POST / HTTP/1.1

Host: localhost

Content-Type: text/xml; charset=utf-8

Content-Length: length

SOAPAction: ""

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="" xmlns:xsd="" xmlns:soap="">

<soap:Body>

<GetSumString xmlns="">

<para1>250</para1>

<para2>250</para2>

</GetSumString>

</soap:Body>

</soap:Envelope>

(3)等到Web Service伺服器端接收到上面的請求之後,就可以進行相應的邏輯處理,並且返回結果。根據SOAP協議,HTTP響應如下形式:

HTTP/1.1 200 OK

Content-Type: text/xml; charset=utf-8

Content-Length: length

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="" xmlns:xsd="" xmlns:soap="">

<soap:Body>

<GetSumStringResponse xmlns="">

<GetSumStringResult>500</GetSumStringResult>

</GetSumStringResponse>

</soap:Body>

</soap:Envelope>

如此一來,客戶端就得到了服務端的處理結果,換句話說,客戶端已經得到了Web Service提供的服務。

PS:最後,再說一下SOAP協議和HTTP協議,它們的關係非常類似於網路分層中的上下層協議,使用SOAP協議的雙方將SOAP資料包放入HTTP報文之中,並且通過HTTP協議完成實際的傳輸,換句話說,SOAP是對HTTP的一個封裝,下圖說明了這一過程:

  1.2 WSDL又是什麼鬼,它有啥作用?

(1)WSDL介紹

WSDL(Web Service Description Language)是Web服務描述語言,它是一種由微軟、IBM、Intel等大型供應商提出的語言規範,目的就是為了描述Web伺服器所提供的'服務,以供使用者參考。WSDL是一種複合XML語法規範的語言,它的設計完全基於SOAP協議,當一個Web Service伺服器期望為使用者提供服務說明時,WSDL是最好的選擇之一。

這裡仍以上面的例項來說明,在Web服務端提供了這樣一個方法:

string GetSumString(int para1, int para2)

當服務端檢視利用WSDL告訴客戶端如何使用該方法時,就會提供下面的這樣一個WSDL檔案(仍然是一個XML):

<?xml version="1.0" encoding="utf-8"?>

<wsdl:definitions xmlns:tm="" xmlns:soapenc="" xmlns:mime="" xmlns:tns="" xmlns:soap="" xmlns:s="" xmlns:soap12="" xmlns:http="" targetNamespace="" xmlns:wsdl="">

<wsdl:types>

<s:schema elementFormDefault="qualified" targetNamespace="">

<s:element name="GetSumString">

<s:complexType>

<s:sequence>

<s:element minOccurs="1" maxOccurs="1" name="para1" type="s:int" />

<s:element minOccurs="1" maxOccurs="1" name="para2" type="s:int" />

</s:sequence>

</s:complexType>

</s:element>

<s:element name="GetSumStringResponse">

<s:complexType>

<s:sequence>

<s:element minOccurs="0" maxOccurs="1" name="GetSumStringResult" type="s:string" />

</s:sequence>

</s:complexType>

</s:element>

</s:schema>

</wsdl:types>

<wsdl:message name="GetSumStringSoapIn">

<wsdl:part name="parameters" element="tns:GetSumString" />

</wsdl:message>

<wsdl:message name="GetSumStringSoapOut">

<wsdl:part name="parameters" element="tns:GetSumStringResponse" />

</wsdl:message>

<!-- 這裡省略其他定義 -->

</wsdl:definitions>

如上xml所示,在<wsdl:types>節點下,WSDL定義了GetSumString方法的名字:

<s:element name="GetSumString">

引數數量、每個引數的型別:

<s:complexType>

<s:sequence>

<s:element minOccurs="1" maxOccurs="1" name="para1" type="s:int" />

<s:element minOccurs="1" maxOccurs="1" name="para2" type="s:int" />

</s:sequence>

</s:complexType>

以及返回引數的型別:

<s:element name="GetSumStringResponse">

<s:complexType>

<s:sequence>

<s:element minOccurs="0" maxOccurs="1" name="GetSumStringResult" type="s:string" />

</s:sequence>

</s:complexType>

</s:element>

通過完整的描述,使用者就能夠了解如何使用該Web服務了。

(2)獲取和使用WSDL

當Web Service伺服器提供WSDL時,就可以通過特定的工具獲得WSDL檔案。最直接的方式就是在URL中直接新增WSDL引數,來發送得到WSDL檔案的請求,如下所示:

http://localhost:6105/

這時點選回車就可以得到如下圖所示的WSDL結果:

1.3 Web Service中如何處理附件?

儘管Web Service提供的方法的引數型別沒有任何限制,也就意味著所有的附件可以通過位元組陣列來進行傳遞,但是把位元組流直接內嵌在SOAP訊息的做法有很多問題,這也曾經成為XML語法和SOAP協議被詬病的原因。這裡主要介紹一下XOP的概念。

在XOP出現之前,SOAP處理二進位制資料的方式都很簡單,比如當一個Web Service服務端提供瞭如下的方法時:

void UploadSmallAttach(Byte[] attachment)

客戶端呼叫該Web Service,只需要發出下面這樣的SOAP請求即可:

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="" xmlns:xsd="" xmlns:soap="">

<soap:Body>

<UploadSmallAttach xmlns="">
  <attachment>D0CF11E0A1B11AE100000000000000000000000003E00003
00FEFF09000600000000000000000000000600000000000000000000
DE0200000000000000000000001000000000000000FEFFFFFFFF000
00000000000000000D80200000000000D9020000DA02000DB02000
000DC020000DD0200000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFF</attachment>

</UploadSmallAttach>

</soap:Body>

</soap:Envelope>

如上所示,其中<attachment>節點下的一大堆字元,就是某個檔案的位元組流。通過這種方式,確實是可以實現傳送二進位制附件的功能的,但這樣的處理過於粗略,且傳輸沒有任何優化。W3C為此特別指定了XOP規範。

XOP(XML-binary Optimized Packages)意為XML二進位制打包,它把二進位制資料流從SOAP訊息中分離出來,進行單獨打包。上述的客戶端請求如果使用XOP規範的話,將轉變為如下結果:

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:xsi="" xmlns:xsd="" xmlns:soap="">

<soap:Body>

<UploadSmallAttach xmlns="">

<attachment>

<xop:Include xmlns="" href="cid:http://www.book.com/attachment.png" />

</attachment>

</UploadSmallAttach>

</soap:Body>

</soap:Envelope>

可以看到,原本出現在二進位制位元組流的地方,被轉換成了一個引用:

<attachment>

<xop:Include xmlns="" href="cid:http://www.book.com/attachment.png" />

</attachment>

這樣整個SOAP信封節點下就不再包含任何二進位制直接,而福建則被安放在另一個MIME體中:

Content-Type: image/png

Content-Transfer-Encoding: binary

Content-ID: >
  D0CF11E0A1B11AE100000000000000000000000003E0000300FEFF090006
00000000000000000000000600000000000000000000DE0200000000000
000000000001000000000000000FEFFFFFFFF00000000000000000000D8
0200000000000D9020000DA02000DB02000000DC020000DD020000000
0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF