亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

使用 Apache Axis 和 Castor 創(chuàng)建 Web 服務(wù)

系統(tǒng) 1648 0

本文將展示如何利用 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 的優(yōu)點(diǎn)
  • 在一般的情況下,簡(jiǎn)單的請(qǐng)求/響應(yīng)
  • 更易于使用,比如代表開發(fā)人員執(zhí)行從XML到方法簽名的映射

文檔方式的優(yōu)點(diǎn)

  • 更豐富、更完整的數(shù)據(jù)描述
  • 更大的靈活性
  • 更好地適合工作流和異步處理
  • 通常更快速
  • 與現(xiàn)有的XML表示的互操作

共同的制止因素

  • 解析器開發(fā)(在 DOM 或 SAX 中) 
  • 從接收的文檔到Java值對(duì)象的自定義、冗長(zhǎng)的內(nèi)部映射

但是反過來說,通過 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 處理器都特別困難。

正在發(fā)展的解決方案:Apache Axis


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)這 并不很難。

Axis 和 Castor:皆為最優(yōu)


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)系。


在我們的解決方案中 Axis 和 Castor 之間的關(guān)系圖







必備知識(shí)

本文的讀者是熟悉 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)境。

獲得最新的 Axis 和 Castor


要構(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)。

在 WebSphere 中啟用 Axis


這個(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... .








定義 Schema 和服務(wù)

要開發(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)該是自解釋的。

清單1. StockQuote服務(wù)的數(shù)據(jù)模型StockQuote.xsd
            <xsd:element name="quote">
            
<xsd:complexType>
<xsd:sequence>
<xsd:element name="symbol" type="xsd:string"/>
<xsd:element name="volume" type="xsd:integer"/>
<xsd:element name="lastTrade" type="lastTradeType"/>
<xsd:element name="change" type="changeType"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>

<xsd:complexType name="changeType">
<xsd:sequence>
<xsd:element name="dollar" type="xsd:float"/>
<xsd:element name="percent" type="xsd:float"/>
<xsd:element name="positive" type="xsd:boolean"/>
</xsd:sequence>
</xsd:complexType>

<xsd:complexType name="lastTradeType">
<xsd:sequence>
<xsd:element name="price" type="xsd:float"/>
<xsd:element name="date" type="xsd:long"/>
</xsd:sequence>
</xsd:complexType>

除了定義元素和 complexTypes 來代表您的數(shù)據(jù)模型之外,您還必須定義接口的輸入/輸出。這些就是Web服務(wù)將公開的 方法 ,并且將在 WSDL(下一步講解如何創(chuàng)建 WSDL)中進(jìn)行指出,如 清單2 所示:

清單2. StockQuote.xsd的StockQuote服務(wù)的方法簽名
            <xsd:element name="getStockQuote">
            
<xsd:complexType>
<xsd:sequence>
<xsd:element name="symbol" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="getStockQuoteResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="quote" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>

為您的服務(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)行交互。

清單3. StockQuote 服務(wù)的 WSDL 文件
             <definitions
            
targetNamespace="http://w3.ibm.com/schemas/services/2002/11/15/stockquote/wsdl"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://w3.ibm.com/schemas/services/2002/11/15/stockquote/wsdl"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:types="http://w3.ibm.com/schemas/services/2002/11/15/stockquote" >
<types>
<xsd:schema elementFormDefault="qualified"
targetNamespace=
"http://w3.ibm.com/schemas/services/2002/11/15/stockquote/wsdl/importtypes">
<import namespace=
"http://w3.ibm.com/schemas/services/2002/11/15/stockquote"
location="StockQuote.xsd" />

</xsd:schema>
</types>
<message name="getStockQuoteReq">
<part name="parameters" element= "types:getStockQuote" />
</message>
<message name="getStockQuoteResp">
<part name="parameters" element= "types:getStockQuoteResponse" />
</message>
<portType name="StockQuotePortType">
<operation name="getStockQuote">
<input message="tns:getStockQuoteReq" />
<output message="tns:getStockQuoteResp" />
</operation>
</portType>
. . .

這里惟一要提請(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">
            
<soap:binding style= "document"
transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="getStockQuote">
<soap:operation style= "document" soapAction="getStockQuote" />
<input>
<soap:body use= "literal" />
</input>
<output>
<soap:body use= "literal" />
</output>
</operation>
</binding>
<service name="StockQuoteService">
<port name="StockQuoteSOAPPort" binding="tns:StockQuoteSOAPBinding">
<soap:address
location=
"http://localhost:9081/AxisWeb/services/StockQuoteSOAPPort" />
</port>
</service>
</definitions>








生成所需的代碼和存根

既然您已經(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,
            

StockQuotePortType.java // a server portType interface,
StockQuoteSOAPBindingStub.java // a server stub class,
where we'll write the getStockQuote method,
StockQuoteService.java // a client-side service interface,
StockQuoteServiceLocator.java // a client-side service implementation (the locator),

deploy.wsdd // the service bindings for the Axis server,
undeploy.wsdd

_quote.java // plus the classes to represent the data model,
ChangeType.java // which we will be replacing with the ones generated
LastTradeType.java // by Castor.
. . .

當(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 形式,這種形式讓我們覺得更易于閱讀,這樣也可以免于書寫額外的代碼。

使用 Castor 生成數(shù)據(jù)綁定


目前,我們可以繼續(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。







配置 Axis 和 Castor 來一起工作

現(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 文件。

修改服務(wù)器端存根去使用 Castor 類


要讓存根使用 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 配置。

修改和部署 server-config.wsdd 文件


第二個(gè)任務(wù)是修改 deploy.wsdd 文件。下面先讓我們概覽一下這個(gè)文件,需要修改的部分已經(jīng)著重顯示,如 清單6

清單6. 修改StockQuote服務(wù)的 deploy.wsdd 文件
            <service name="StockQuoteSOAPPort" provider="java:RPC" style="wrapped" use="literal">
            
<parameter name="wsdlTargetNamespace"
value="http://w3.ibm.com/schemas/services/2002/11/15/stockquote/wsdl"/>
. . .

<typeMapping
xmlns:ns="http://w3.ibm.com/schemas/services/2002/11/15/stockquote"
qname="ns:changeType"
type="java:com.ibm.w3.services.stockquote. ChangeType "
serializer="org.apache.axis.encoding.ser. castor.CastorSerializerFactory "
deserializer="org.apache.axis.encoding.ser. castor.CastorDeserializerFactory "
encodingStyle=""
/>
<typeMapping
xmlns:ns="http://w3.ibm.com/schemas/services/2002/11/15/stockquote"
qname="ns:lastTradeType"
type="java:com.ibm.w3.services.stockquote. LastTradeType "
serializer="org.apache.axis.encoding.ser. castor.CastorSerializerFactory "
deserializer="org.apache.axis.encoding.ser. castor.CastorDeserializerFactory "
encodingStyle=""
/>
<typeMapping
xmlns:ns="http://w3.ibm.com/schemas/services/2002/11/15/stockquote"
qname=" ns:quote "
type="java:com.ibm.w3.services.stockquote. Quote "
serializer="org.apache.axis.encoding.ser. castor.CastorSerializerFactory "
deserializer="org.apache.axis.encoding.ser. castor.CastorDeserializerFactory "
encodingStyle=""
/>
</service>

對(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

在 Axis 上測(cè)試您的服務(wù)


現(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 所示。



Axis 運(yùn)行我們的 StockQuote 服務(wù)的結(jié)果

如果您不能得到這個(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)。

編寫 getStockQuote 方法


因?yàn)檫@是一個(gè)簡(jiǎn)單的 Web 服務(wù),在這一步驟中我們不用做太多的工作。但是該樣本代碼說明了使用 Castor 生成的數(shù)據(jù)綁定代碼以及由 Axis 來填充是非常容易的。下面是我們的 getStockQuote 方法的樣本代碼,見 清單7

清單7. StockQuoteSOAPBindingImpl.java 中的樣本 getStockQuote 方法
            public class StockQuoteSOAPBindingImpl implements
            
com.ibm.w3.services.stockquote.StockQuotePortType {

public com.ibm.w3.services.stockquote.Quote getStockQuote(java.lang.String symbol)
throws java.rmi.RemoteException {
Quote quote = new Quote();
quote.setVolume(979012312);
quote.setSymbol(symbol);

Change change = new Change();
change.setDollar(678F);
change.setPercent(300F);
change.setPositive(true);
quote.setChange(change);

LastTrade lastTrade = new LastTrade();
lastTrade.setDate(new java.util.Date().getTime());
lastTrade.setPrice(678F);
quote.setLastTrade(lastTrade);

return quote;
}
}

這里需要著重注意的是:在這里使用的對(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ì)遇到問題。








構(gòu)建客戶端

既然您已經(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();
            
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(new URL(ENDPOINT));

GetStockQuote request = new GetStockQuote();
request.setSymbol("IBM");

StringWriter sw = new StringWriter();

Marshaller mar = new Marshaller(sw);
mar.marshal(request);

String xml = sw.getBuffer().toString();
Document doc = XMLUtils.newDocument(new ByteArrayInputStream(xml.getBytes()));
SOAPBodyElement[] input = new SOAPBodyElement[1];
input[0] = new SOAPBodyElement(doc.getDocumentElement());

Vector elems = (Vector) call.invoke(input);

這樣就可以了,但是并不是這么自動(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)建)。

清單 9. 更改 StockQuoteSOAPBindingStub.java 中的構(gòu)造函數(shù)
            public StockQuoteSOAPBindingStub(javax.xml.rpc.Service service)
            
throws org.apache.axis.AxisFault {
if (service == null) {
super.service = new org.apache.axis.client.Service();
} else {
super.service = service;
}
java.lang.Class cls;
javax.xml.namespace.QName qName;
java.lang.Class castorsf =
org.apache.axis.encoding.ser.castor.CastorSerializerFactory.class;
java.lang.Class castordf =
org.apache.axis.encoding.ser.castor.CastorDeserializerFactory.class;

java.lang.Class beansf =
org.apache.axis.encoding.ser.BeanSerializerFactory.class;
java.lang.Class beandf =
org.apache.axis.encoding.ser.BeanDeserializerFactory.class;
java.lang.Class enumsf =
org.apache.axis.encoding.ser.EnumSerializerFactory.class;
java.lang.Class enumdf =
org.apache.axis.encoding.ser.EnumDeserializerFactory.class;
java.lang.Class arraysf =
org.apache.axis.encoding.ser.ArraySerializerFactory.class;
java.lang.Class arraydf =
org.apache.axis.encoding.ser.ArrayDeserializerFactory.class;
java.lang.Class simplesf =
org.apache.axis.encoding.ser.SimpleSerializerFactory.class;
java.lang.Class simpledf =
org.apache.axis.encoding.ser.SimpleDeserializerFactory.class;

. . .

清單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 = 
            
new javax.xml.namespace.QName(
"http://w3.ibm.com/schemas/services/2002/11/15/stockquote", "lastTradeType");
cachedSerQNames.add(qName);
cls = com.ibm.w3.services.stockquote.LastTradeType.class;
cachedSerClasses.add(cls);
cachedSerFactories.add( castorsf );
cachedDeserFactories.add( castordf );

在構(gòu)造函數(shù)中更改每一個(gè)保留的代碼塊,然后您完成了這個(gè)任務(wù): Axis 生成的客戶端目前使用 Castor 序列化和數(shù)據(jù)綁定。

試用生成的客戶端


現(xiàn)在,您可以編寫客戶端代碼,如 清單11

清單11. 最終的 StockQuote 客戶端
                 StockQuoteService service = new StockQuoteServiceLocator();
            

StockQuotePortType port = service.getStockQuoteSOAPPort();

Quote quote = port.getStockQuote("IBM");

System.out.println(quote.getVolume());

這樣更安全,更加自動(dòng)化,而且更容易使用。并且,現(xiàn)在您獲得了一個(gè) Web 服務(wù),使用 Axis來進(jìn)行通信,使用 Castor 進(jìn)行驗(yàn)證和數(shù)據(jù)綁定,這是一個(gè)端到端的情形。







Axis 和 Castor:文檔方式

正如您在本文中所看到的,整合文檔方式的服務(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ù)文章。



參考資料



作者簡(jiǎn)介


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)系。

使用 Apache Axis 和 Castor 創(chuàng)建 Web 服務(wù)


更多文章、技術(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ì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 国产亚洲精品激情都市 | 亚洲悠悠色综合中文字幕 | 日本高清毛片视频在线看 | 欧美 日韩 国产在线 | www.黄色片 | 久久精品在 | 国产手机在线国内精品 | 看全色黄大色大片免费久久久 | 亚洲久久草 | 精品一区二区三区免费视频 | 色一情 | 国产成人精品视频一区二区不卡 | 97看看| 久久免费观看国产99精品 | 欧美99热| 亚洲自拍第二页 | 亚洲va久久久久综合 | 天天干夜夜夜操 | 亚洲 国产 日韩 欧美 | 综合另类小说色区色噜噜 | 免费的性生活视频 | 亚洲国产欧美在线 | 久爱www成人网免费视频 | 亚洲视频日韩视频 | 曰本一区 | 妖精www视频在线观看高清 | 精品伊人久久久99热这里只 | 欧美人与动人物a级网站 | 欧美精品久久一区二区三区 | 国内精品自在自线视频香蕉 | 久久午夜综合久久 | 免费视频精品 | 性生活免费网站 | 91麻精品国产91久久久久 | 伊人久久综合影院首页 | 一级特黄aaa大片大全 | 日本高清不卡码 | 天天拍天天操 | 国产精品女在线观看 | 五月天婷婷在线播放 | 国产精品嘿咻嘿咻在线播放 |