本文將展示如何利用 Castor XML 綁定使 Apache Axis 環(huán)境中的文檔方式 Web 服務(wù)更簡(jiǎn)單、更清晰、更直觀。本文首先討論了 Web 服務(wù)編碼方法,并且解釋了為什么 Castor 和 Axis 共同構(gòu)成了一個(gè)好的解決方案。本文為創(chuàng)建和運(yùn)行文檔方式 Web 服務(wù)的所有步驟——從設(shè)計(jì) schema 和服務(wù)到生成服務(wù)和客戶端代碼——提供了說明和解釋。本文講解了如何配置 Axis 來使用 Castor,并且介紹了開發(fā)人員在解決棘手的問題時(shí)可能遇到的“局限性(gotcha)”。
開發(fā)人員在開發(fā) Web 服務(wù)時(shí)遇到的一項(xiàng)挑戰(zhàn)是存在兩種調(diào)用模型:RPC 和文檔方式。有幾篇好文章詳細(xì)地論述了這兩種模型之間的區(qū)別,但是下面的部分將簡(jiǎn)要地介紹這些不同之處,以給本文的其余部分作一個(gè)鋪墊。
RPC 方式編碼之所以看起來有吸引力,是因?yàn)閺母拍钌现v,它與開發(fā)人員已經(jīng)使用了多年的其他實(shí)現(xiàn)架構(gòu)(如 CORBA 或 RMI)是相同的。文檔方式引起了人們的興趣,但是 RPC 比較容易并且顯示出技術(shù)相當(dāng)簡(jiǎn)單,正因如此,文檔方式經(jīng)常受到冷遇。然而,過去的經(jīng)驗(yàn)證明,快速開發(fā)是一項(xiàng)技術(shù)的關(guān)鍵,需要立即通過網(wǎng)絡(luò)發(fā)送真實(shí)復(fù)雜的對(duì) 象。為了進(jìn)行顯示,發(fā)送字符串、整數(shù)抑或數(shù)組就可以了,但是現(xiàn)實(shí)世界使用復(fù)雜的數(shù)據(jù)結(jié)構(gòu)和模型來編碼數(shù)據(jù)。為了處理這種情況,SOAP RPC 實(shí)現(xiàn)支持復(fù)雜對(duì)象序列化和反序列化。只要對(duì)象遵循 Java Bean 規(guī)范,就可以將對(duì)象轉(zhuǎn)換成 XML 文檔,并且采用對(duì)開發(fā)人員透明的方式進(jìn)行處理。這是非常有吸引力的——用幾行簡(jiǎn)單的代碼就可以通過網(wǎng)絡(luò)發(fā)送真實(shí)業(yè)務(wù)數(shù)據(jù)對(duì)象,而無需考慮基礎(chǔ)實(shí)現(xiàn)。
![]() |
|
但是反過來說,通過 RPC 使用復(fù)雜對(duì)象也有缺點(diǎn)。這種方法常常產(chǎn)生集成問題。一種實(shí)現(xiàn)的序列化可能與另一種實(shí)現(xiàn)的反序列化不相匹配,因?yàn)橛糜?XML SOAP 編碼過程的 Java Bean 的定義不明確。開放技術(shù)突然暴露出一個(gè)大的缺陷——Apache SOAP 在處理 .NET 時(shí)遇到麻煩,原因在于它們的實(shí)現(xiàn)之間的差異,因而迫切需要更加開放的服務(wù)。
文檔方式很好地融合了定義明確的結(jié)構(gòu)和互操作性。這是通過用于定義復(fù)雜對(duì)象的標(biāo)準(zhǔn) XML-Schema 實(shí)現(xiàn)的。與 SOAP 編碼比較起來,XML-Schema 是一種嚴(yán)格而容易理解的標(biāo)準(zhǔn),可以用于定義結(jié)構(gòu)。XML-Schema 在定義復(fù)雜結(jié)構(gòu)方面具有很大的靈活性,并且同時(shí)確保了Web服務(wù)的所有承諾——語言、平臺(tái)、環(huán)境和傳輸中立(在使用通用應(yīng)用程序編程接口的情況下)。
文檔方式獲得了 XML-Schema 的所有優(yōu)點(diǎn),看來似乎能夠解決所有的 Web 服務(wù)難題。然而,開發(fā)人員在選擇文檔方式時(shí)必須進(jìn)行權(quán)衡。文檔方式的一個(gè)不利的方面是增加了復(fù)雜性。開發(fā)人員會(huì)意外地發(fā)現(xiàn),需要進(jìn)行艱難的工作來解析 XML 文檔和執(zhí)行必要的轉(zhuǎn)換,以載入其他數(shù)據(jù) bean 和帶有輸入數(shù)據(jù)的方法請(qǐng)求。這對(duì)于服務(wù)器和客戶端來說都是適用的。它意味著編寫自定義 SAX 處理器,而使用和維護(hù) SAX 處理器都特別困難。
Apache Axis是最流行的Web服務(wù)工具包之一。Axis支持RPC和文檔方式服務(wù),因此,它看來似乎是文檔方式服務(wù)的真正開端。在使用文檔方式服務(wù)時(shí),您仍然 需要以某種方式處理輸入的XML數(shù)據(jù)。Axis提供了一個(gè)方便的工具來幫助完成此項(xiàng)艱苦的工作,這個(gè)工具名為WSDL2Java。WSDL2Java不僅 可以為您的方法生成客戶機(jī)和服務(wù)器的代碼存根,而且可以生成實(shí)際bean,來對(duì)用XML-Schema定義的模型中的數(shù)據(jù)進(jìn)行建模。然 后,WSDL2Java將從XML中自動(dòng)載入這些bean。通常這個(gè)過程稱為數(shù)據(jù)綁定,它是XML-Schema背后的運(yùn)動(dòng)的支柱。WSDL2Java顯 得有一些特異,但是往往它幫助事情的進(jìn)展。很明顯,這樣的一個(gè)工具是非常有用的,但不幸的是,它并不是客戶端存根生成的終結(jié)技術(shù)。它還面臨著一些實(shí)際的問 題:
- WSDL2Java 陷入了大多數(shù)技術(shù)所遭遇的陷阱,也就是 利用 schema 支持迎頭趕上(playing catch-up with schema suppor) 。編寫一個(gè)工具,讓它可以正確而完整地處理這些非常復(fù)雜的XML-Schema標(biāo)準(zhǔn)并不是一件小事情。就其本身而言,這代表了和 Axis 同樣困難的工作。WSDL2Java在這方面顯得不夠,有缺陷,并且沒有對(duì)許多 XML-Schem 特征提供完全的支持。例如對(duì)屬性組和選項(xiàng)組的支持。但是這些地方正在改變,因?yàn)閷?duì)WSDL2Java所做的工作也在繼續(xù)。然而,編寫和維護(hù)如此復(fù)雜的代碼并不是 Axis 所看重的,并且,WSDL2Java將繼續(xù)推進(jìn)迎頭趕上的策略,以滿足獨(dú)立數(shù)據(jù)綁定解決方案的功能。
- 另外一個(gè)問題和第一個(gè)問題有關(guān)。WSDL2Java 生成的代碼 缺少 XML 驗(yàn)證(lacks XML validation) 能力。當(dāng)您開始使用XML文檔的時(shí)候,驗(yàn)證是非常重要的,而且 XML-Schema 允許驗(yàn)證過程自動(dòng)發(fā)生。然而,WSDL2Java 還沒有一個(gè)機(jī)制來完成這一工作。
- 字符串的序列化和反序列化接口 不是直觀的(not intuitive) 。如果您的 XML 對(duì)象使用的是 WSDL2Java 的數(shù)據(jù)綁定代碼,選擇就是,您將需要在某個(gè)時(shí)候?qū)?duì)象編碼或者解碼為XML字符串。雖然這對(duì) WSDL2Java 的生成對(duì)象來說是可行的,但卻并不是一件容易的事情。需要安裝一個(gè)龐大的框架,并且有可能出現(xiàn)許多頭疼的事情,雖然它看起來好象是一項(xiàng)簡(jiǎn)單的任務(wù)。
開 發(fā)社區(qū)對(duì)使用Apache Axis有一些復(fù)雜的反映和困惑,還有另外一個(gè)原因:開發(fā)社區(qū)是從 Apache Axis 的 beta 測(cè)試階段開始伴隨它一起壯大的,經(jīng)歷了 Apache Axis 發(fā)展的整個(gè)過程。需要了解的莫名其妙的工作區(qū)和配置機(jī)制隨著版本的更新而不斷變化。這就是開發(fā)代碼主體的現(xiàn)實(shí)。最初,當(dāng) Axis一開始出現(xiàn),重點(diǎn)關(guān)注的是 RPC Web 服務(wù)。因?yàn)檫@個(gè)原因,對(duì)RPC服務(wù)的支持是最多的,并且它的接口對(duì)于開發(fā)人員來說更穩(wěn)定同時(shí)也更有名。直到現(xiàn)在,文檔方式的文檔、示例、Axis的樣本配 置都是有限的。隨著多種使用文檔方式的內(nèi)部配置選項(xiàng)(如包、文檔或者消息)的出現(xiàn),開發(fā)人員在建立它們自己的文檔方式的服務(wù)時(shí)要經(jīng)歷更多的決策和復(fù)雜性。 然而,這些配置方面的困難并未形成大的障礙,無論如何,使用 RPC 仍然是調(diào)用 Web 服務(wù)的一種快速而便利的方法。當(dāng)然,Axis還在不斷的發(fā)展,這個(gè)困難將自動(dòng)解決。不過,下面我們將一步一步地講解如何使用文檔方式的服務(wù),您將會(huì)發(fā)現(xiàn)這 并不很難。
Castor 是一個(gè)獨(dú)立的 XML 數(shù)據(jù)綁定包,提供了從 XML-Schema 到 Java 對(duì)象的映射。這些 Java 對(duì)象看起來很像bean,但是可以編組(marshal)或者解組(un-marshal)為XML字符或者流,更重要的是可以對(duì)原始的Shcema進(jìn)行 驗(yàn)證。Castor是一個(gè)開放源碼的工作,遵循了開放的Web服務(wù)技術(shù)。這得到了一個(gè)非常活躍的開發(fā)組織的支持,因此,產(chǎn)生了大量的信息和 Web 內(nèi)容,使得開發(fā)人員可以更有效的利用這些技術(shù)。
我們?cè)?Apache Axis 和 WSDL 不足的地方用 Castor 來構(gòu)建所有級(jí)別的最優(yōu)解決方案。我們將獲得諸多好處,直觀的數(shù)據(jù)綁定接口,更完全支持的 schema 實(shí)現(xiàn),同時(shí)還利用了 Axis 框架的所有 Web 服務(wù)能力。 圖1 顯示了 Axis 和 Castor 之間的關(guān)系。

![]() ![]() |
![]()
|
本文的讀者是熟悉 Web 服務(wù)和相關(guān)的創(chuàng)建和部署技術(shù)的媒介 Java 開發(fā)人員。如果您可以編寫基本的 WSDL 并使用 Axis 來部署一個(gè)服務(wù),那么您就具備了閱讀本文的預(yù)備知識(shí)。同樣,本文假定讀者掌握 XML 和 Schema 的知識(shí)。所有的代碼都是使用 WebSphere Studio Application Developer 和 WebSphere Application Server versions 4.0.4、4.0.6 來開發(fā)、測(cè)試和部署的。也可以很輕松地用其他的開發(fā)和部署環(huán)境、庫(kù)來進(jìn)行替換,并且能獲得同樣的效果,但是,在本文中我們集中于這些環(huán)境。
要構(gòu)建和運(yùn)行這個(gè)項(xiàng)目,您需要有 Apache Axis 和 Exolab 的 Castor。從
http://www.castor.org
可以很容易地得到 Castor 以及下載和安裝指南。要獲得 Apache Axis 相對(duì)來說難度更大一些,但也不難到哪兒去。在寫作本文時(shí),使 Axis 和 Castor 可以互操作的代碼還不在發(fā)布的 beta 版本中,只能在CVS中得到。到讀者閱讀本文時(shí),這一功能將很可能已經(jīng)在最新發(fā)布的JAR中了。然而,在此之前,要獲得最新版本的 Axis 以及這個(gè)項(xiàng)目所需的 org.apache.axis.ser.CastorSerializer 和 Deserializer 代碼,最好的方法是從 CVS 獲取,或者下載一個(gè)最新測(cè)試版(nightly build),這兩種方式在
http://ws.apache.org/axis/cvs.html
上都有。按照這里介紹的方法來下載和構(gòu)建一個(gè)Apache Axis的副本,比想象中的會(huì)更容易一些,這要感謝Apache Ant的構(gòu)建架構(gòu)。
這個(gè)項(xiàng)目的樣本環(huán)境是 WebSphere Application Server V4.0.4。在 WebSphere 或者其他 Java 容器安裝 Axis 不會(huì)太難,但是正確地執(zhí)行這些步驟仍然很重要。關(guān)于如何進(jìn)行操作的指南在 Apache Axis 文檔中(請(qǐng)參閱
參考信息
),您也可以在本地 CVS 檢驗(yàn)版(checkout)或最新測(cè)試版(nightly)中的
/xml-axis/java/docs/install.html
中找到。
如果您使用 WebSphere Application Studio V5.0,您可能會(huì)遇到一個(gè)“局限性”,這個(gè)局限性是關(guān)于 WebSphere Application Developer V5 上安裝的環(huán)境和您試圖與 Apache Axis 一起使用的環(huán)境之間的 JAR 沖突的。如果您遇到了這些問題,可以嘗試這個(gè)快速修復(fù)(quick fix):在測(cè)試服務(wù)器的服務(wù)器配置中,將環(huán)境選項(xiàng)面板(Environment Options)系統(tǒng)屬性(-D property)的“com.ibm.ws.classloader.warDelegationMode”設(shè)置為 false 。操作步驟如下: Server perspective > the server you are using for our example > Environment Options > System Properties > Add... .
![]() ![]() |
![]()
|
要開發(fā)Web服務(wù),您需要有一個(gè) Schema,它表示兩個(gè)部分,一個(gè)部分是您將要使用的數(shù)據(jù),另一個(gè)部分是描述您將要公開的方法的的服務(wù)描述。講解如何編寫一個(gè) XML-Schema 或者 WSDL 不在本文的討論范圍之內(nèi),不過在別的地方可以找到關(guān)于如何完成這一工作的文檔。
為了達(dá)到本文的目標(biāo),我們將創(chuàng)建一個(gè)示例服務(wù): StockQuote 服務(wù)。
為您的數(shù)據(jù)定義 Schema:StockQuote.xsd
您的服務(wù)所需要的第一件事情就是用 XML-Schema 描述您的數(shù)據(jù)模型。在
清單1
中展示了將用在 StockQuote 服務(wù)中的簡(jiǎn)單數(shù)據(jù)模型,它應(yīng)該是自解釋的。
<xsd:element name="quote"> |
除了定義元素和 complexTypes 來代表您的數(shù)據(jù)模型之外,您還必須定義接口的輸入/輸出。這些就是Web服務(wù)將公開的 方法 ,并且將在 WSDL(下一步講解如何創(chuàng)建 WSDL)中進(jìn)行指出,如 清單2 所示:
清單2. StockQuote.xsd的StockQuote服務(wù)的方法簽名
<xsd:element name="getStockQuote"> |
為您的服務(wù)定義 WSDL:StockQuote WSDL
接下來,您必須為您的 Web 服務(wù)創(chuàng)建一個(gè) WSDL 文件。您可以采用標(biāo)準(zhǔn)的方式來完成這一工作,但是這里有幾個(gè)地方需要重點(diǎn)關(guān)注。首先,注意
清單3
中用黑體突出顯示的部分。在標(biāo)準(zhǔn)方式中,您是用與您的數(shù)據(jù)模型相關(guān)聯(lián)的 URI 來定義“types”命名空間前綴。其次,您將所需的獨(dú)立 Schema 文件(StockQuote.xsd)導(dǎo)入 WSDL。最后,您在 WSDL 的消息聲明中使用了
“types”
命名空間。為什么做這些工作顯得很重要?因?yàn)?Castor 天生就不支持在文件中嵌入
<xsd:schema>
節(jié)點(diǎn),在本例中即為 WSDL 的
<types>
部分中的
<xsd:schema>
節(jié)點(diǎn)。我們發(fā)現(xiàn),像這樣使用外部文件來定義您的數(shù)據(jù)模型和方法,不僅清晰、易于維護(hù),而且更重要的是,它容許 Castor 和其他工具直接與您的文件形式的 Schema 進(jìn)行交互。
<definitions |
這里惟一要提請(qǐng)注意的事情就是將 WSDL 設(shè)置為使用文檔方式編碼。注意 清單4 中用粗體突出顯示的部分,它是 WSDL 的繼續(xù)。這些部分將告訴 WSDL 以及 WSDL2Java,您使用的是文檔方式的Web服務(wù),并且您將生成文檔方式(非 RPC)的服務(wù)請(qǐng)求。
清單4. StockQuote 服務(wù)的 WSDL 文件(續(xù))
<binding name="StockQuoteSOAPBinding" type="tns:StockQuotePortType"> |
![]() ![]() |
![]()
|
既然您已經(jīng)準(zhǔn)備好了您的服務(wù)定義和 Schema,這樣就可以著手于 Axis 和 Castor。Axis 和 Castor 都需要生成一些代碼,并且您可以把 Castor 生成的代碼放在 Axis 生成的代碼之上,這樣就就可以做到“兩全其美”了,既采用了 Axis 的 Web 服務(wù)客戶端和服務(wù)器代碼,有帶有 Castor 的數(shù)據(jù)綁定。這第一個(gè)部分,將顯示如何生成這些代碼,下一個(gè)步驟將演示如何重新配置生成的映射,這樣可以獲得所期望的互操作性。
使用 WSDL2Java 構(gòu)建客戶端和服務(wù)器端存根
WSDL2Java 生成 Java 類(用于數(shù)據(jù)模型中的對(duì)象的數(shù)據(jù)綁定)、客戶端和服務(wù)器存根代碼(用于連接您的方法)、以及服務(wù)綁定信息(用于 Axis 服務(wù)器)。我們將繼續(xù)使用后面的兩個(gè)部分:存根和服務(wù)綁定,而用 Castor 生成的代碼來替代數(shù)據(jù)模型代碼。但是要完成這一工作,首先必須運(yùn)行 WSDL2Java 來生成我們將需要的存根和服務(wù)綁定。
要使用 WSDL2Java 生成所需要的文件,可以運(yùn)行以下命令:
%java org.apache.axis.wsdl.WSDL2Java -s "Web Content/StockQuoteService.wsdl"
--NStoPkg http://w3.ibm.com/schemas/services/2002/11/15/stockquote/wsdl=com.ibm.w3.services.stockquote
--NStoPkg http://w3.ibm.com/schemas/services/2002/11/15/stockquote=com.ibm.w3.services.stockquote
-o "Java Source"
上面的命令將生成如 清單5 所示的文件。
清單5. WSDL2Java生成的文件
StockQuoteSOAPBindingImpl.java // a server-side service implementation template class, |
當(dāng)您在 WSDL2Java 中使用命令來生成文件時(shí),您提供了幾個(gè)參數(shù)。
NStoPkg
參數(shù)指定了 Java 包,用于您的 StockQuote.xsd 文件的不同的命名空間,這將被 WSDL2Java 自動(dòng)從 WSDL 文件加入進(jìn)來。下一步,當(dāng)您運(yùn)行 Castor 來生成數(shù)據(jù)模型類,您可以使用同樣的映射。對(duì)于 WSDL2Java 還有一些可選的額外參數(shù),在本文中沒有講述,那將不使用
wrapped
的方式。這一個(gè)選項(xiàng)可以通過添加“-W”命令行來指定。在 WSDL2Java 中,
wrapped
形式意味著什么呢?它控制了 WSDL2Java 是如何生成方法客戶端和存根。對(duì)于一個(gè)文檔形式的服務(wù),通過 -W 選項(xiàng)來指定不使用
wrapped
方式,這將映射到一個(gè)方法,類似于下面用 StockQuoteSOAPBindingStub 類生成的:
public GetStockQuoteResponse getStockQuote(GetStockQuote gsq)
換句話說,在 StockQuote.xsd 文件中定義的整個(gè)
<GetStockQuote>
元素,將作為一個(gè)單獨(dú)的 bean 傳遞給您的方法,在 bean 中有三個(gè)字段,如
清單2
所示。另一方面,對(duì)于一個(gè)標(biāo)準(zhǔn)的
wrapped
方式的服務(wù)(也就是在這個(gè)示例中生成的),它將映射到如下的一個(gè)方法:
public Quote getStockQuote(String symbol)
本文中將使用 wrapped 形式,這種形式讓我們覺得更易于閱讀,這樣也可以免于書寫額外的代碼。
目前,我們可以繼續(xù)我們的工作,使用 Castor 生成數(shù)據(jù)模型綁定,來替換 WSDL2Java 所創(chuàng)建的。因?yàn)?Castor不是特定于 Web 服務(wù)的,它是直接使用 XSD 文件,而不是 WSDL 文件。因此,可以使用下面的命令,將 XSD 文件傳遞給它:
%java org.exolab.castor.builder.SourceGenerator -i "Web Content/StockQuote.xsd"
-package com.ibm.w3.services.stockquote
-nomarshall
-dest "Java Source"
-f
您使用命令行,并傳遞參數(shù)給 Castor。參數(shù)
-package
是對(duì)應(yīng)于 WSDL2Java 的 NStoPkg 參數(shù)。參數(shù)
-nomarshall
告 訴 Castor 不要在所生成的 bean 中產(chǎn)生編組(marshall)方法(marshall、unmarshall、validate)。在您的示例中,這些方法是不必要的,因?yàn)?Castor Serializer and Deserializer for Axis 是直接使用 Castor Marshaller 和 Unmarshaller 類,這可以實(shí)現(xiàn)同樣的目的,所以,我們使用參數(shù)來關(guān)閉它。如果您計(jì)劃使用這些對(duì)象作為一個(gè)大系統(tǒng)的一部分,也可以打開這個(gè)參數(shù)。參數(shù)
-f
僅僅告訴 Castor,在沒有提示的前提下去覆蓋所有現(xiàn)有的文件。如果您注意到了這一點(diǎn),您將清楚,這將覆蓋那些在前面步驟中由 WSDL2Java 所生成的一些數(shù)據(jù)模型 bean。但是不用擔(dān)心,因?yàn)槟挥眠@些文件,所以這將不是一個(gè)問題。
Castor 其余的選項(xiàng)在 castorbuilder.properties 文件中指定。大部分屬性都不重要,但是,有一個(gè)很重要的設(shè)置:
javaclassmapping
設(shè)置。
# Java class mapping of <xsd:element>'s and <xsd:complexType>'s
#
org.exolab.castor.builder.javaclassmapping=element
這個(gè)設(shè)置決定了 Castor 如何從您的 Schema 中生成類。根據(jù)您如何編寫您的 Schema,您也許想使用
element
或者
type
。兩者的區(qū)別是
element
方法為所有的
complexType
類型的元素生成類。對(duì)于所有的頂級(jí)
<complexTypes>
會(huì)生成抽象類。頂級(jí)
<complexType>
類型的 Schema 中的元素都將為之生成一個(gè)類,這個(gè)類繼承了
<complexType's>
抽象類。對(duì)于
<simpleType>
類型的元素將不生成類。然而,可以直接使用基本Java類型。另外一個(gè)選項(xiàng),
type
方法的行為是不一樣的。并不為沒一個(gè)元素生成類,來擴(kuò)展為
<complexTypes>
創(chuàng)建的類,
type
選項(xiàng)將為所有的頂級(jí)
<complexTypes>
類型和所有的內(nèi)聯(lián)(inlined)
anonymous
<complexTypes>
創(chuàng)建類。元素將格式化為這些類的實(shí)例,而沒有它們本身的類。
這兩個(gè)選項(xiàng)解釋起來有一些復(fù)雜,但是,根據(jù)您的 Schema 是如何定義的,一個(gè)選項(xiàng)將是每一個(gè) Schema 的基本選項(xiàng)。因此,對(duì)您自己的 Schema,要先試驗(yàn)一下兩種方法,看您更傾向于那一個(gè)類。對(duì)于這個(gè) StockQuote.xsd 示例,我們發(fā)現(xiàn)
element
方式工作得更好,所以,在這里我們使用這個(gè)方法來生成實(shí)例數(shù)據(jù)模型bean。
![]() ![]() |
![]()
|
現(xiàn)在我們可以來了解事情的本質(zhì)了:讓 Axis 去使用 Castor 生成的類,而不是使用它自己生成的類。這個(gè)工作是本文的最關(guān)鍵之處,在本文中描述了如何完成這個(gè)“艱巨”的工作,在客戶端和服務(wù)器端代碼存根中 Axis 可以使用 Castor 的類。但是不要擔(dān)心這個(gè)難題——學(xué)習(xí)完本文的一步一步的詳細(xì)指導(dǎo),這個(gè)工作就不再困難了。要完成這一工作,需要修改 Axis 服務(wù)器端存根類、以及 Axis 生成的 .wsdd 文件。
要讓存根使用 Castor 類,您只需修改存根文件中的類名就可以了。正如前面我們提到的一樣,盡管通常 Castor 和 WSDL2Java 將生成同樣的類名,導(dǎo)致了同樣類名的存根,但是并不是所有情況都會(huì)如此。因此,檢查 WSDL 客戶端和服務(wù)器端存根代碼,確保已經(jīng)設(shè)置為返回和 Castor 生成對(duì)象同樣的正確類名。
請(qǐng)?jiān)倏?
清單5
,可以看到兩個(gè)文件,
StockQuotePortType.java
和
StockQuoteSOAPBindingStub.java
顯示為用于服務(wù)器。為了實(shí)現(xiàn)目的,我們必須修改這兩個(gè)文件。必要的惟一修改就是檢查所有的類名,確保它們已經(jīng)指向了 Castor 生成的類,而不是 WSDL2Java 生成的類。
在本實(shí)例中,只有一個(gè)類名發(fā)生了改變:
_quote
。這個(gè) WSDL2Java 生成的類
_quote
,在 Castor 中名稱改成了
Quote
。它們?nèi)匀辉谕粋€(gè)包中,正如我們生成這兩個(gè)類的情形一樣。但是我們必須在引用它們的地方修改類的名字。
然后,文件
StockQuotePortType.java
,的下面一行
public com.ibm.w3.services.stockquote.
_quote
getStockQuote(java.lang.String symbol) throws java.rmi.RemoteException;
改變成:
public com.ibm.w3.services.stockquote.
Quote
getStockQuote(java.lang.String symbol) throws java.rmi.RemoteException;
對(duì)于文件
StockQuoteSOAPBindingStub.java
,我們必須更改同一行,
public com.ibm.w3.services.stockquote.
_quote
getStockQuote(java.lang.String symbol) throws java.rmi.RemoteException {...
改變?yōu)?
public com.ibm.w3.services.stockquote.
Quote
getStockQuote(java.lang.String symbol) throws java.rmi.RemoteException {...
現(xiàn)在,所有的服務(wù)器端代碼引用都指向了 Castor 類。這意味著,我們就可以修改 deploy.wsdd 文件去使用這些類和 Castor 配置。
第二個(gè)任務(wù)是修改 deploy.wsdd 文件。下面先讓我們概覽一下這個(gè)文件,需要修改的部分已經(jīng)著重顯示,如
清單6
。
<service name="StockQuoteSOAPPort" provider="java:RPC" style="wrapped" use="literal"> |
對(duì)于這個(gè)文件我們要做兩種類型的更改,以及還需要警惕的“局限性”。所有的更改都是針對(duì)
<typeMapping>
元素。第一個(gè)更改是修改
type
屬性下面的類名,使用 Castor 生成的類名,而不是 WSDL2Java 所生成的類名,如果這兩個(gè)名字有差別的情況下就需要進(jìn)行這個(gè)更改。在我們的范例中,對(duì)于最開始的兩個(gè)映射,
ns:changeType
和
ns:lastTradeType
,和 Castor 中的類名是一樣的,所以沒有必要進(jìn)行更改。但是,對(duì)于
ns:quote
類,類名需要進(jìn)行更改,將 WSDL2Java 生成的
_quote
類名更改為 Castor 生成的
Quote
類名。
第二個(gè)進(jìn)行的更改是:在
<typeMappings>
中將所有的 serializers 和 deserializers 分別的更改為
org.apache.axis.encoding.ser.castor.CastorSerializerFactory
和
org.apache.axis.encoding.ser.castor.CastorDeserializerFactory
。這就告訴 Axis 使用 Castor 專有的類去序列化和反序列化這些類型的引入的 XML 文件,而不是缺省的
org.apache.axis.encoding.ser.BeanSerializerFactory
和
org.apache.axis.encoding.ser.BeanDeserializerFactory
類。這些類包含在最新版本 Axis 1.1 CVS 修訂中的類,也正是為什么我們需要在
“獲得最新的 Axis 和 Castor”步驟
中獲取Axis的CVS版本。
這里有一個(gè)需要提請(qǐng)注意的“局限性”,我們將著重強(qiáng)調(diào)一個(gè)地方也就是我們需要注意的。這個(gè)“局限性”必須處理 Axis 和 WSDL2Java 閱讀和編寫 XML 的方式。在我們的測(cè)試中,我們發(fā)現(xiàn) WSDL2Java 偶爾生成無效的 XML,原因是在輸出中錯(cuò)誤的防止了一些“<”和“>”。在最終的
<typeMapping>
元素
qname
屬性中就是這樣的一個(gè)地方。生成的
qname
屬性的值是“
ns:>quote
”,很明顯并不是有效的 XML ,因?yàn)椤?gt;”是受保護(hù)的字符。在這種情況下,刪除這個(gè)多余的“>”就能解決所有的問題,并且要盯住類似于上面情況的多余字符。
使用deploy.wsdd文件來部署服務(wù)
既然您已經(jīng)更改了您的 deploy.wsdd 文件,而且做好了充分的準(zhǔn)備,這時(shí)需要把它部署到服務(wù)器上。您可以通過從deploy.wsdd 文件中復(fù)制
<service>
元素到
WEB-INF/server-config.wsdd
文件,就可以完成這個(gè)工作。但是,您也可以使用 Axis 的便利部署工具來為您自己完成這一個(gè)工作。這個(gè)方法也確保了
server-config.wsdd
文件已經(jīng)存在,如果不存在的話就創(chuàng)建這個(gè)文件,然后進(jìn)行錯(cuò)誤檢查,確保這一方法的正確性。
為了運(yùn)行這個(gè)部署工具,確保您的工作目錄已經(jīng)設(shè)置為 Axis 的根目錄,在該實(shí)例中是
WEB-INF
,然后運(yùn)行下面的命令:
%java org.apache.axis.utils.Admin server classes/com/ibm/w3/services/stockquote/deploy.wsdd
如果這個(gè)命令得到了正確運(yùn)行,將不返回任何錯(cuò)誤,并且您的服務(wù)已經(jīng)得到了部署。現(xiàn)在,簡(jiǎn)單的啟動(dòng)您的服務(wù)器,然后可以進(jìn)行下一步工作。
同樣,如果您想在后面的某一個(gè)步驟卸載您的測(cè)試服務(wù),運(yùn)行下列命令:
%java org.apache.axis.utils.Admin server classes/com/ibm/w3/services/stockquote/undeploy.wsdd
現(xiàn)在您已經(jīng)構(gòu)建了所有的相關(guān)代碼,集成 Axis 和 Castor,然后在 .wsdd 文件中部署服務(wù)。這時(shí)候,就可以進(jìn)行測(cè)試了。通過指向您在 .wsdd 文件中定義的端點(diǎn),您可以測(cè)試您安裝的應(yīng)用,在本實(shí)例中,是指向
<context root>/services/StockQuoteSOAPPort
。您可以看到結(jié)果如
圖2
所示。

如果您不能得到這個(gè)顯示信息,這說明在 Axis 中安裝 StockQuote 服務(wù)出現(xiàn)了錯(cuò)誤,這時(shí)重新查看一下您的配置以及前面的步驟,看到底是什么地方出現(xiàn)了問題。
如果顯示了這個(gè)消息,這時(shí)候您就可以編寫一些代碼來讓
getStockQuote
方法做一些實(shí)際的工作。
![]() ![]() |
![]()
|
現(xiàn)在,什么都準(zhǔn)備好了,但是您的服務(wù)器仍然不能做任何事情——您還沒有實(shí)現(xiàn)
getStockQuote
方法。由于相應(yīng)的事情都已經(jīng)做好,要進(jìn)行著一個(gè)工作就非常簡(jiǎn)單了。您只需要在
StockQuoteSOAPBindingImpl
中填寫您的方法,該方法和在
清單2
中的方法一一對(duì)應(yīng)。
因?yàn)檫@是一個(gè)簡(jiǎn)單的 Web 服務(wù),在這一步驟中我們不用做太多的工作。但是該樣本代碼說明了使用 Castor 生成的數(shù)據(jù)綁定代碼以及由 Axis 來填充是非常容易的。下面是我們的
getStockQuote
方法的樣本代碼,見
清單7
。
public class StockQuoteSOAPBindingImpl implements |
這里需要著重注意的是:在這里使用的對(duì)象和在客戶端使用的對(duì)象是一樣的,并且已經(jīng)由 Castor 根據(jù)它的 Schema 進(jìn)行了驗(yàn)證,所以這些導(dǎo)入的數(shù)據(jù)可以安全的使用。如果導(dǎo)入的數(shù)據(jù)沒有得到驗(yàn)證,在調(diào)用您的方法之前 Castor 會(huì)拋出一個(gè)異常。同樣,對(duì)于驗(yàn)證您返回的數(shù)據(jù)這一機(jī)制將帶來一些益處,并且,如果您返回的數(shù)據(jù)沒有得到驗(yàn)證,當(dāng) Axis 試圖序列化輸出的 bean 的時(shí)候, Castor 將拋出一個(gè)異常。
另外,本例中盡管我們的 bean 非常簡(jiǎn)單——只有
Quote、Change
和
LastTrade
對(duì)象—— Castor 處理這些復(fù)雜的 XML-Schema 數(shù)據(jù)模型非常完美,但是 WSDL2Java 將會(huì)遇到問題。
![]() ![]() |
![]()
|
既然您已經(jīng)成功的在服務(wù)器端完成了運(yùn)行 Axis 和 Castor 的所有工作,現(xiàn)在就可以構(gòu)建一個(gè)客戶端了。
使用動(dòng)態(tài)的 Axis Web 服務(wù)客戶端以及我們的 Castor 知識(shí),我們將完成如下所示的一個(gè)初步工作,如 清單8 。
清單8. 構(gòu)建 StockQuote 服務(wù)的客戶端的初步工作
Service service = new Service(); |
這樣就可以了,但是并不是這么自動(dòng)化。然而,對(duì) Axis 生成的客戶端存根使用一些巧妙的辦法,我們可以做得更好,可以有一個(gè)客戶端可以自動(dòng)化的完成所有的安裝過程。
To make 為了讓存根使用 Castor 類,簡(jiǎn)單的修改存根文件中的類名,就象和服務(wù)器存根中一樣——雖然,通常 Castor 和 WSDL2Java 生成同樣的類名,導(dǎo)致存根也是有同樣的類名。但并不是所有情況都這樣,所以檢查和更正顯得很重要。
您需要修改的文件是
StockQuoteSOAPBindingStub.java
。在本實(shí)例中, WSDL2Java 生成了用于 Quote 元素的類,名為
_quote
,但是 Castor 生成的名字為
Quote
,所以您需要在所有的地方進(jìn)行更改。在這里并不列出所有的引用了這個(gè)類的地方,以及每一行需要更改,這是一個(gè)重復(fù)性的事情,并且對(duì)于閱讀沒有什么益處,我們將把這個(gè)工作交給您來做,僅僅需要瀏覽該文件,將所有對(duì)類
com.ibm.w3.services.stockquote._quote
的引用更改為
com.ibm.w3.services.stockquote.Quote
。
更改客戶端,使用 Castor serializers 代替 Axis serializers
目前,我們進(jìn)行關(guān)鍵的更改:修改客戶端去使用 Castor 專有的 serializer 以及 deserializer 類,來代替缺省情況下 WSDL 生成的 BeanSerializers 。在服務(wù)器端,我們可以修改配置文件,
deploy.wsdd
,設(shè)置使用哪個(gè)類來序列化和反序列化。不幸的是,客戶端并不使用這樣的一個(gè)配置文件,所以我們必須在代碼中修改。然而,這是一個(gè)非常簡(jiǎn)單的修改,并且可以很清楚地看出,它和在服務(wù)器端對(duì)
deploy.wsdd
的修改是一樣的。
要 Castor serializer 和 deserializer 類,您需要做的第一件事情就是將它們添加到可能的序列器(Serializer)類列表中(在
StockQuoteSOAPBindingStub.java
文件的構(gòu)造函數(shù)
public StockQuoteSOAPBindingStub(javax.xml.rpc.Service service)
中創(chuàng)建)。
public StockQuoteSOAPBindingStub(javax.xml.rpc.Service service) |
清單9
顯示了用粗體顯示的構(gòu)造函數(shù)的修改。這個(gè)修改是自描述的:它添加了
CastorSerializerFactory.class
和
CastorDeserializerFactory.class
作為后面代碼可能使用的選項(xiàng),定義了用于輸入和輸出對(duì)象的序列器(serializer)和反序列器(deserializers)。
更新客戶端的最后一個(gè)步驟是:在上面提到的構(gòu)造函數(shù)中,更改所有
cachedSerFactories.add(beansf)
和
cachedDeserFactories.add(beandf)
出現(xiàn)的地方,用 Castor 的 BeanSerializer 代替 Axis 的 BeanSerializer 。這等同于我們對(duì)
deploy.wsdd
的更改,這里我們列出了 Castor 序列化和反序列化類,而不是 Axis 的 BeanSerializer。在用到您的對(duì)象時(shí),將每一個(gè)
beansf
和
beandf
的地方更改為
castorsf
和
castordf
。在所有出現(xiàn)
beansf
和
beandf
的地方,您都需要將它們改為
castorsf
和
castordf
,在本例中,這兩者都出現(xiàn)了。
例如,如 清單10 所示的一個(gè)代碼塊的更改,其修改用粗體表示:
清單10. 在 StockQuoteSOAPBindingStub.java 中更改的代碼塊
qName = |
在構(gòu)造函數(shù)中更改每一個(gè)保留的代碼塊,然后您完成了這個(gè)任務(wù): Axis 生成的客戶端目前使用 Castor 序列化和數(shù)據(jù)綁定。
現(xiàn)在,您可以編寫客戶端代碼,如
清單11
。
StockQuoteService service = new StockQuoteServiceLocator(); |
這樣更安全,更加自動(dòng)化,而且更容易使用。并且,現(xiàn)在您獲得了一個(gè) Web 服務(wù),使用 Axis來進(jìn)行通信,使用 Castor 進(jìn)行驗(yàn)證和數(shù)據(jù)綁定,這是一個(gè)端到端的情形。
![]() ![]() |
![]()
|
正如您在本文中所看到的,整合文檔方式的服務(wù)、Castor 和 Axis 并不是想象的那么可怕,僅僅是安裝有點(diǎn)復(fù)雜。但是一旦您成功了,您的 Web 服務(wù)將具備文檔方式的靈活性和清晰度,對(duì) Axis 健壯的支持,以及 Castor 的驗(yàn)證和數(shù)據(jù)綁定優(yōu)勢(shì)。
一旦您掌握了本文所講的全部?jī)?nèi)容,還有許多有趣的方面有待您去鉆研。例如,使用 Castor JDO,您只需寫幾行代碼就可以讓您的服務(wù)器端 Castor 對(duì)象把自己編組到 SQL 數(shù)據(jù)庫(kù)中。您也可以使用 Castor 的標(biāo)準(zhǔn)表達(dá)式和驗(yàn)證支持來清理 Web 服務(wù)數(shù)據(jù),這樣您的服務(wù)和客戶端的數(shù)據(jù)中出現(xiàn)錯(cuò)誤的可能性就減少了。要了解關(guān)于這些主題的更進(jìn)一步的信息,請(qǐng)參閱關(guān)于整合 Castor 和 Axis 的后續(xù)文章。
-
Reap the benefits of document style Web services
逐步了解 Web 服務(wù)標(biāo)準(zhǔn)
Subscribe to the developerWorks newsletter
developerWorks Toolbox subscription
-
-
從
Castor web site
可以得到 Castor 的最新副本。
-
參閱 Apache Axis 文檔,它在 WebSphere 或者其他 Java 容器提供的
a guide for getting Axis set up
中。
-
Axis CVS page
包含了關(guān)于從 CVS 或者最新測(cè)試版本的文件中下載和構(gòu)建 Axis 的指導(dǎo)。
-
關(guān)于如何安裝和使用 Axis,請(qǐng)查看
Axis installation instructions
文檔頁。
-
“
Reap the benefits of Document-style Web services
” (
developerWorks
, 2002年4月)更加深入地解釋了 Castor 的數(shù)據(jù)綁定框架的益處。
-
系列文章:
逐步了解 Web 服務(wù)標(biāo)準(zhǔn)
(
developerWorks
, 2002年10月),解釋了 SOAP 的復(fù)雜性。
-
開發(fā) Web 服務(wù)
(
developerWorks
, 2001年11月),提供了一個(gè)關(guān)于如何為 Web 服務(wù)定義 WSDL 的介紹。
-
使用 XML-Schema 定義元素的基礎(chǔ)
(
developerWorks
, 2000年 8月)將幫助您為您的服務(wù)數(shù)據(jù)定義 XML-Schema。
-
從
Castor web site
可以得到 Castor 的最新副本。
![]() |
||
|
![]() |
Kevin Gibbs是一位軟件工程師,在英國(guó)劍橋大學(xué)學(xué)習(xí) IBM 的高級(jí) Internet 技術(shù),獲得了 MA 學(xué)位。他早先從事 SashXB for Linux 腳本環(huán)境研究,目前正研究多種 Internet 技術(shù),包括 Web 服務(wù)和 blogging 架構(gòu)。您可以通過 kagibbs at us.ibm.com 與 Kevin 聯(lián)系。 |
![]() |
||
|
![]() |
Brian Goodman 是一位 IT 架構(gòu)師,專門從事 IBM Intranet 的咨詢、交流和協(xié)作。您可以通過 bgoodman at us.ibm.com 與 Brian 聯(lián)系。 |
![]() |
||
|
![]() |
Elias Torres 是一位軟件工程師,在英國(guó)劍橋大學(xué)學(xué)習(xí) IBM 的高級(jí) Internet 技術(shù),獲得了 MA 學(xué)位。他從事 Sash 腳本環(huán)境研究,探索一些技術(shù),例如 blogging 和它們?cè)诠经h(huán)境的實(shí)際益處。您可以通過 eliast at us.ibm.com 與Elias聯(lián)系。 |
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
