雖然發(fā)布的服務(wù)很簡(jiǎn)單,Axis幫我們生成的WSDL文檔看起來(lái)卻是比較復(fù)雜的,之所以這樣的主要原因是WSDL要考慮到兼容各種實(shí)現(xiàn)和具有可擴(kuò)展性,這就像我們使用一些框架做開(kāi)發(fā)會(huì)使代碼總量增加,而好處是使邏輯更加清晰。這篇帖子的上半部分介紹了WSDL里常用到的名稱(chēng)空間,現(xiàn)在就來(lái)說(shuō)說(shuō)WSDL里各元素的含義。
一個(gè)WSDL文檔里一般包含<types>、<message>、<portType>、<binding>和<service>這幾個(gè)元素,其中<types>、<message>和<portType>可以看作抽象的接口定義,而<binding>和<service>是具體的實(shí)現(xiàn),注:有些時(shí)候也把<binding>看作接口的一部分。你也許看過(guò)一些WSDL把這兩部分分開(kāi)寫(xiě)在兩個(gè)xml文件里,并在其中一個(gè)文件里引入(import)另一個(gè)的情況,這也是為什么要區(qū)分接口和實(shí)現(xiàn)的原因之一。在現(xiàn)實(shí)世界里,接口部分很可能是由某個(gè)組織(例如某行業(yè)協(xié)會(huì))制定好的,該組織的成員在發(fā)布自己的Web服務(wù)時(shí)都要引入它,從而達(dá)到統(tǒng)一標(biāo)準(zhǔn)的目的。
<types>標(biāo)簽用來(lái)定義Web服務(wù)里用到的,XML Schema定義的數(shù)據(jù)類(lèi)型以外的自定義數(shù)據(jù)類(lèi)型,對(duì)于我們自定義的類(lèi)(Book),會(huì)對(duì)應(yīng)到一個(gè)<complexType>,其中用<element>元素指定每個(gè)參數(shù)的類(lèi)型。JAX-RPC規(guī)范中規(guī)定了Java語(yǔ)言的數(shù)據(jù)類(lèi)型到XML Schema數(shù)據(jù)類(lèi)型的映射,例如int<->xsd:int、java.lang.String<->xsd:string等等,還有數(shù)組的映射方式。
<message>標(biāo)簽定義Web服務(wù)里的消息,最常見(jiàn)的就是請(qǐng)求和響應(yīng)消息。<message>中可以有<part>元素,它對(duì)應(yīng)Java類(lèi)中各個(gè)方法的參數(shù)或返回值,例如addBook()方法有一個(gè)Book類(lèi)型的參數(shù),則在WSDL中會(huì)有<part name="book" type="tns1:Book"/>的描述。
<portType>標(biāo)簽表示一個(gè)服務(wù)的類(lèi)型,就是接口的意思了。WSDL里有些概念很容易混淆,比如port和service的區(qū)別,我把service理解為有一個(gè)具體URL的服務(wù),而port代表某一地址,portType是service的抽象,不知道對(duì)不對(duì)。我們看一個(gè)WSDL文檔,一般就該先找<portType>元素,看看這個(gè)WSDL代表的Web服務(wù)里都有哪些方法,它們的參數(shù)和返回值是什么。這些方法是在<portType>里用<operation>元素表示的,<operation>可以有<input>和<output>子元素,表示方法的輸入和輸出。注意,方法可以是只有輸入或只有輸出的。
<binding>元素將portType與具體的傳輸協(xié)議綁定。現(xiàn)在,絕大多數(shù)都是與SOAP綁定的,對(duì)每一個(gè)方法的輸入和輸出,都要指定SOAP的表示方法。JAX-RPC規(guī)范規(guī)定,SOAP綁定可以有rpc和document兩種類(lèi)型,分別表示遠(yuǎn)程過(guò)程調(diào)用和基于消息的方式。use屬性可以是encoded或literal,對(duì)于前者要支持rpc的方式,對(duì)于后者要支持rpc和document的方式,它們使得SOAP消息的格式有所區(qū)別,但我還沒(méi)有仔細(xì)研究,你可以參考一下JAX-RPC 1.1版本的6.3-6.4節(jié)。又想起另外一個(gè)問(wèn)題,SOAP和HTTP的關(guān)系是怎樣的,綁定到SOAP就等于綁定到HTTP了嗎,應(yīng)該不是,那么在哪里指定Web服務(wù)綁定的應(yīng)用層協(xié)議(HTTP、SMTP等等)呢?(Update: 由transport屬性指定應(yīng)用層協(xié)議)
最后,<service>元素通過(guò)<port>子元素把服務(wù)聯(lián)系到一個(gè)具體的URL,更確切點(diǎn),應(yīng)該是把一個(gè)已綁定的portType聯(lián)系到某個(gè)URL,這樣就知道該把SOAP消息發(fā)給哪個(gè)服務(wù)器了。
我覺(jué)得之所以應(yīng)該花比較多的時(shí)間理解WSDL,因?yàn)閃SDL在整個(gè)Web服務(wù)中扮演了十分核心的角色,它是對(duì)Web服務(wù)的一個(gè)比較完整的語(yǔ)法上的描述,同時(shí),它還與XML、SOAP以及UDDI都有著非常密切的聯(lián)系,因此對(duì)于我們更好的認(rèn)識(shí)Web服務(wù)體系結(jié)構(gòu)是很重要的。雖然現(xiàn)在的Web服務(wù)開(kāi)發(fā)工具都能自動(dòng)進(jìn)行Java<->WSDL的轉(zhuǎn)換,但理解WSDL對(duì)于Web服務(wù)的不論是設(shè)計(jì)、開(kāi)發(fā)還是修改調(diào)試都是必要的。
參考資料: