欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

使用 Apache Axis 和 Castor 創建 Web 服務

系統 1714 0

本文將展示如何利用 Castor XML 綁定使 Apache Axis 環境中的文檔方式 Web 服務更簡單、更清晰、更直觀。本文首先討論了 Web 服務編碼方法,并且解釋了為什么 Castor 和 Axis 共同構成了一個好的解決方案。本文為創建和運行文檔方式 Web 服務的所有步驟——從設計 schema 和服務到生成服務和客戶端代碼——提供了說明和解釋。本文講解了如何配置 Axis 來使用 Castor,并且介紹了開發人員在解決棘手的問題時可能遇到的“局限性(gotcha)”。


文檔方式的正反兩面

開發人員在開發 Web 服務時遇到的一項挑戰是存在兩種調用模型:RPC 和文檔方式。有幾篇好文章詳細地論述了這兩種模型之間的區別,但是下面的部分將簡要地介紹這些不同之處,以給本文的其余部分作一個鋪墊。

RPC 方式編碼之所以看起來有吸引力,是因為從概念上講,它與開發人員已經使用了多年的其他實現架構(如 CORBA 或 RMI)是相同的。文檔方式引起了人們的興趣,但是 RPC 比較容易并且顯示出技術相當簡單,正因如此,文檔方式經常受到冷遇。然而,過去的經驗證明,快速開發是一項技術的關鍵,需要立即通過網絡發送真實復雜的對 象。為了進行顯示,發送字符串、整數抑或數組就可以了,但是現實世界使用復雜的數據結構和模型來編碼數據。為了處理這種情況,SOAP RPC 實現支持復雜對象序列化和反序列化。只要對象遵循 Java Bean 規范,就可以將對象轉換成 XML 文檔,并且采用對開發人員透明的方式進行處理。這是非常有吸引力的——用幾行簡單的代碼就可以通過網絡發送真實業務數據對象,而無需考慮基礎實現。

RPC 的優點
  • 在一般的情況下,簡單的請求/響應
  • 更易于使用,比如代表開發人員執行從XML到方法簽名的映射

文檔方式的優點

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

共同的制止因素

  • 解析器開發(在 DOM 或 SAX 中) 
  • 從接收的文檔到Java值對象的自定義、冗長的內部映射

但是反過來說,通過 RPC 使用復雜對象也有缺點。這種方法常常產生集成問題。一種實現的序列化可能與另一種實現的反序列化不相匹配,因為用于 XML SOAP 編碼過程的 Java Bean 的定義不明確。開放技術突然暴露出一個大的缺陷——Apache SOAP 在處理 .NET 時遇到麻煩,原因在于它們的實現之間的差異,因而迫切需要更加開放的服務。

文檔方式很好地融合了定義明確的結構和互操作性。這是通過用于定義復雜對象的標準 XML-Schema 實現的。與 SOAP 編碼比較起來,XML-Schema 是一種嚴格而容易理解的標準,可以用于定義結構。XML-Schema 在定義復雜結構方面具有很大的靈活性,并且同時確保了Web服務的所有承諾——語言、平臺、環境和傳輸中立(在使用通用應用程序編程接口的情況下)。

文檔方式獲得了 XML-Schema 的所有優點,看來似乎能夠解決所有的 Web 服務難題。然而,開發人員在選擇文檔方式時必須進行權衡。文檔方式的一個不利的方面是增加了復雜性。開發人員會意外地發現,需要進行艱難的工作來解析 XML 文檔和執行必要的轉換,以載入其他數據 bean 和帶有輸入數據的方法請求。這對于服務器和客戶端來說都是適用的。它意味著編寫自定義 SAX 處理器,而使用和維護 SAX 處理器都特別困難。

正在發展的解決方案:Apache Axis


Apache Axis是最流行的Web服務工具包之一。Axis支持RPC和文檔方式服務,因此,它看來似乎是文檔方式服務的真正開端。在使用文檔方式服務時,您仍然 需要以某種方式處理輸入的XML數據。Axis提供了一個方便的工具來幫助完成此項艱苦的工作,這個工具名為WSDL2Java。WSDL2Java不僅 可以為您的方法生成客戶機和服務器的代碼存根,而且可以生成實際bean,來對用XML-Schema定義的模型中的數據進行建模。然 后,WSDL2Java將從XML中自動載入這些bean。通常這個過程稱為數據綁定,它是XML-Schema背后的運動的支柱。WSDL2Java顯 得有一些特異,但是往往它幫助事情的進展。很明顯,這樣的一個工具是非常有用的,但不幸的是,它并不是客戶端存根生成的終結技術。它還面臨著一些實際的問 題:

  • WSDL2Java 陷入了大多數技術所遭遇的陷阱,也就是 利用 schema 支持迎頭趕上(playing catch-up with schema suppor) 。編寫一個工具,讓它可以正確而完整地處理這些非常復雜的XML-Schema標準并不是一件小事情。就其本身而言,這代表了和 Axis 同樣困難的工作。WSDL2Java在這方面顯得不夠,有缺陷,并且沒有對許多 XML-Schem 特征提供完全的支持。例如對屬性組和選項組的支持。但是這些地方正在改變,因為對WSDL2Java所做的工作也在繼續。然而,編寫和維護如此復雜的代碼并不是 Axis 所看重的,并且,WSDL2Java將繼續推進迎頭趕上的策略,以滿足獨立數據綁定解決方案的功能。
  • 另外一個問題和第一個問題有關。WSDL2Java 生成的代碼 缺少 XML 驗證(lacks XML validation) 能力。當您開始使用XML文檔的時候,驗證是非常重要的,而且 XML-Schema 允許驗證過程自動發生。然而,WSDL2Java 還沒有一個機制來完成這一工作。
  • 字符串的序列化和反序列化接口 不是直觀的(not intuitive) 。如果您的 XML 對象使用的是 WSDL2Java 的數據綁定代碼,選擇就是,您將需要在某個時候將對象編碼或者解碼為XML字符串。雖然這對 WSDL2Java 的生成對象來說是可行的,但卻并不是一件容易的事情。需要安裝一個龐大的框架,并且有可能出現許多頭疼的事情,雖然它看起來好象是一項簡單的任務。

開 發社區對使用Apache Axis有一些復雜的反映和困惑,還有另外一個原因:開發社區是從 Apache Axis 的 beta 測試階段開始伴隨它一起壯大的,經歷了 Apache Axis 發展的整個過程。需要了解的莫名其妙的工作區和配置機制隨著版本的更新而不斷變化。這就是開發代碼主體的現實。最初,當 Axis一開始出現,重點關注的是 RPC Web 服務。因為這個原因,對RPC服務的支持是最多的,并且它的接口對于開發人員來說更穩定同時也更有名。直到現在,文檔方式的文檔、示例、Axis的樣本配 置都是有限的。隨著多種使用文檔方式的內部配置選項(如包、文檔或者消息)的出現,開發人員在建立它們自己的文檔方式的服務時要經歷更多的決策和復雜性。 然而,這些配置方面的困難并未形成大的障礙,無論如何,使用 RPC 仍然是調用 Web 服務的一種快速而便利的方法。當然,Axis還在不斷的發展,這個困難將自動解決。不過,下面我們將一步一步地講解如何使用文檔方式的服務,您將會發現這 并不很難。

Axis 和 Castor:皆為最優


Castor 是一個獨立的 XML 數據綁定包,提供了從 XML-Schema 到 Java 對象的映射。這些 Java 對象看起來很像bean,但是可以編組(marshal)或者解組(un-marshal)為XML字符或者流,更重要的是可以對原始的Shcema進行 驗證。Castor是一個開放源碼的工作,遵循了開放的Web服務技術。這得到了一個非?;钴S的開發組織的支持,因此,產生了大量的信息和 Web 內容,使得開發人員可以更有效的利用這些技術。

我們在 Apache Axis 和 WSDL 不足的地方用 Castor 來構建所有級別的最優解決方案。我們將獲得諸多好處,直觀的數據綁定接口,更完全支持的 schema 實現,同時還利用了 Axis 框架的所有 Web 服務能力。 圖1 顯示了 Axis 和 Castor 之間的關系。


在我們的解決方案中 Axis 和 Castor 之間的關系圖







必備知識

本文的讀者是熟悉 Web 服務和相關的創建和部署技術的媒介 Java 開發人員。如果您可以編寫基本的 WSDL 并使用 Axis 來部署一個服務,那么您就具備了閱讀本文的預備知識。同樣,本文假定讀者掌握 XML 和 Schema 的知識。所有的代碼都是使用 WebSphere Studio Application Developer 和 WebSphere Application Server versions 4.0.4、4.0.6 來開發、測試和部署的。也可以很輕松地用其他的開發和部署環境、庫來進行替換,并且能獲得同樣的效果,但是,在本文中我們集中于這些環境。

獲得最新的 Axis 和 Castor


要構建和運行這個項目,您需要有 Apache Axis 和 Exolab 的 Castor。從 http://www.castor.org 可以很容易地得到 Castor 以及下載和安裝指南。要獲得 Apache Axis 相對來說難度更大一些,但也不難到哪兒去。在寫作本文時,使 Axis 和 Castor 可以互操作的代碼還不在發布的 beta 版本中,只能在CVS中得到。到讀者閱讀本文時,這一功能將很可能已經在最新發布的JAR中了。然而,在此之前,要獲得最新版本的 Axis 以及這個項目所需的 org.apache.axis.ser.CastorSerializer 和 Deserializer 代碼,最好的方法是從 CVS 獲取,或者下載一個最新測試版(nightly build),這兩種方式在 http://ws.apache.org/axis/cvs.html 上都有。按照這里介紹的方法來下載和構建一個Apache Axis的副本,比想象中的會更容易一些,這要感謝Apache Ant的構建架構。

在 WebSphere 中啟用 Axis


這個項目的樣本環境是 WebSphere Application Server V4.0.4。在 WebSphere 或者其他 Java 容器安裝 Axis 不會太難,但是正確地執行這些步驟仍然很重要。關于如何進行操作的指南在 Apache Axis 文檔中(請參閱 參考信息 ),您也可以在本地 CVS 檢驗版(checkout)或最新測試版(nightly)中的 /xml-axis/java/docs/install.html 中找到。

如果您使用 WebSphere Application Studio V5.0,您可能會遇到一個“局限性”,這個局限性是關于 WebSphere Application Developer V5 上安裝的環境和您試圖與 Apache Axis 一起使用的環境之間的 JAR 沖突的。如果您遇到了這些問題,可以嘗試這個快速修復(quick fix):在測試服務器的服務器配置中,將環境選項面板(Environment Options)系統屬性(-D property)的“com.ibm.ws.classloader.warDelegationMode”設置為 false 。操作步驟如下: Server perspective > the server you are using for our example > Environment Options > System Properties > Add... .








定義 Schema 和服務

要開發Web服務,您需要有一個 Schema,它表示兩個部分,一個部分是您將要使用的數據,另一個部分是描述您將要公開的方法的的服務描述。講解如何編寫一個 XML-Schema 或者 WSDL 不在本文的討論范圍之內,不過在別的地方可以找到關于如何完成這一工作的文檔。

為了達到本文的目標,我們將創建一個示例服務: StockQuote 服務。

為您的數據定義 Schema:StockQuote.xsd


您的服務所需要的第一件事情就是用 XML-Schema 描述您的數據模型。在 清單1 中展示了將用在 StockQuote 服務中的簡單數據模型,它應該是自解釋的。

清單1. StockQuote服務的數據模型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 來代表您的數據模型之外,您還必須定義接口的輸入/輸出。這些就是Web服務將公開的 方法 ,并且將在 WSDL(下一步講解如何創建 WSDL)中進行指出,如 清單2 所示:

清單2. StockQuote.xsd的StockQuote服務的方法簽名
            <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>

為您的服務定義 WSDL:StockQuote WSDL


接下來,您必須為您的 Web 服務創建一個 WSDL 文件。您可以采用標準的方式來完成這一工作,但是這里有幾個地方需要重點關注。首先,注意 清單3 中用黑體突出顯示的部分。在標準方式中,您是用與您的數據模型相關聯的 URI 來定義“types”命名空間前綴。其次,您將所需的獨立 Schema 文件(StockQuote.xsd)導入 WSDL。最后,您在 WSDL 的消息聲明中使用了 “types” 命名空間。為什么做這些工作顯得很重要?因為 Castor 天生就不支持在文件中嵌入 <xsd:schema> 節點,在本例中即為 WSDL 的 <types> 部分中的 <xsd:schema>  節點。我們發現,像這樣使用外部文件來定義您的數據模型和方法,不僅清晰、易于維護,而且更重要的是,它容許 Castor 和其他工具直接與您的文件形式的 Schema 進行交互。

清單3. StockQuote 服務的 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>
. . .

這里惟一要提請注意的事情就是將 WSDL 設置為使用文檔方式編碼。注意 清單4 中用粗體突出顯示的部分,它是 WSDL 的繼續。這些部分將告訴 WSDL 以及 WSDL2Java,您使用的是文檔方式的Web服務,并且您將生成文檔方式(非 RPC)的服務請求。

清單4. StockQuote 服務的 WSDL 文件(續)
                  <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>








生成所需的代碼和存根

既然您已經準備好了您的服務定義和 Schema,這樣就可以著手于 Axis 和 Castor。Axis 和 Castor 都需要生成一些代碼,并且您可以把 Castor 生成的代碼放在 Axis 生成的代碼之上,這樣就就可以做到“兩全其美”了,既采用了 Axis 的 Web 服務客戶端和服務器代碼,有帶有 Castor 的數據綁定。這第一個部分,將顯示如何生成這些代碼,下一個步驟將演示如何重新配置生成的映射,這樣可以獲得所期望的互操作性。

使用 WSDL2Java 構建客戶端和服務器端存根


WSDL2Java 生成 Java 類(用于數據模型中的對象的數據綁定)、客戶端和服務器存根代碼(用于連接您的方法)、以及服務綁定信息(用于 Axis 服務器)。我們將繼續使用后面的兩個部分:存根和服務綁定,而用 Castor 生成的代碼來替代數據模型代碼。但是要完成這一工作,首先必須運行 WSDL2Java 來生成我們將需要的存根和服務綁定。

要使用 WSDL2Java 生成所需要的文件,可以運行以下命令:

%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.
. . .

當您在 WSDL2Java 中使用命令來生成文件時,您提供了幾個參數。 NStoPkg 參數指定了 Java 包,用于您的 StockQuote.xsd 文件的不同的命名空間,這將被 WSDL2Java 自動從 WSDL 文件加入進來。下一步,當您運行 Castor 來生成數據模型類,您可以使用同樣的映射。對于 WSDL2Java 還有一些可選的額外參數,在本文中沒有講述,那將不使用 wrapped 的方式。這一個選項可以通過添加“-W”命令行來指定。在 WSDL2Java 中, wrapped 形式意味著什么呢?它控制了 WSDL2Java 是如何生成方法客戶端和存根。對于一個文檔形式的服務,通過 -W 選項來指定不使用 wrapped 方式,這將映射到一個方法,類似于下面用 StockQuoteSOAPBindingStub 類生成的:

public GetStockQuoteResponse getStockQuote(GetStockQuote gsq)

換句話說,在 StockQuote.xsd 文件中定義的整個 <GetStockQuote> 元素,將作為一個單獨的 bean 傳遞給您的方法,在 bean 中有三個字段,如 清單2 所示。另一方面,對于一個標準的 wrapped 方式的服務(也就是在這個示例中生成的),它將映射到如下的一個方法:

public Quote getStockQuote(String symbol)

本文中將使用 wrapped 形式,這種形式讓我們覺得更易于閱讀,這樣也可以免于書寫額外的代碼。

使用 Castor 生成數據綁定


目前,我們可以繼續我們的工作,使用 Castor 生成數據模型綁定,來替換 WSDL2Java 所創建的。因為 Castor不是特定于 Web 服務的,它是直接使用 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

您使用命令行,并傳遞參數給 Castor。參數 -package 是對應于 WSDL2Java 的 NStoPkg 參數。參數 -nomarshall 告 訴 Castor 不要在所生成的 bean 中產生編組(marshall)方法(marshall、unmarshall、validate)。在您的示例中,這些方法是不必要的,因為 Castor Serializer and Deserializer for Axis 是直接使用 Castor Marshaller 和 Unmarshaller 類,這可以實現同樣的目的,所以,我們使用參數來關閉它。如果您計劃使用這些對象作為一個大系統的一部分,也可以打開這個參數。參數 -f 僅僅告訴 Castor,在沒有提示的前提下去覆蓋所有現有的文件。如果您注意到了這一點,您將清楚,這將覆蓋那些在前面步驟中由 WSDL2Java 所生成的一些數據模型 bean。但是不用擔心,因為您不用這些文件,所以這將不是一個問題。

Castor 其余的選項在 castorbuilder.properties 文件中指定。大部分屬性都不重要,但是,有一個很重要的設置: javaclassmapping 設置。

# Java class mapping of <xsd:element>'s and <xsd:complexType>'s
#
org.exolab.castor.builder.javaclassmapping=element

這個設置決定了 Castor 如何從您的 Schema 中生成類。根據您如何編寫您的 Schema,您也許想使用 element 或者 type 。兩者的區別是 element 方法為所有的 complexType 類型的元素生成類。對于所有的頂級 <complexTypes> 會生成抽象類。頂級 <complexType> 類型的 Schema 中的元素都將為之生成一個類,這個類繼承了 <complexType's> 抽象類。對于 <simpleType> 類型的元素將不生成類。然而,可以直接使用基本Java類型。另外一個選項, type 方法的行為是不一樣的。并不為沒一個元素生成類,來擴展為 <complexTypes> 創建的類, type 選項將為所有的頂級 <complexTypes> 類型和所有的內聯(inlined) anonymous <complexTypes> 創建類。元素將格式化為這些類的實例,而沒有它們本身的類。

這兩個選項解釋起來有一些復雜,但是,根據您的 Schema 是如何定義的,一個選項將是每一個 Schema 的基本選項。因此,對您自己的 Schema,要先試驗一下兩種方法,看您更傾向于那一個類。對于這個 StockQuote.xsd 示例,我們發現 element 方式工作得更好,所以,在這里我們使用這個方法來生成實例數據模型bean。







配置 Axis 和 Castor 來一起工作

現在我們可以來了解事情的本質了:讓 Axis 去使用 Castor 生成的類,而不是使用它自己生成的類。這個工作是本文的最關鍵之處,在本文中描述了如何完成這個“艱巨”的工作,在客戶端和服務器端代碼存根中 Axis 可以使用 Castor 的類。但是不要擔心這個難題——學習完本文的一步一步的詳細指導,這個工作就不再困難了。要完成這一工作,需要修改 Axis 服務器端存根類、以及 Axis 生成的 .wsdd 文件。

修改服務器端存根去使用 Castor 類


要讓存根使用 Castor 類,您只需修改存根文件中的類名就可以了。正如前面我們提到的一樣,盡管通常 Castor 和 WSDL2Java 將生成同樣的類名,導致了同樣類名的存根,但是并不是所有情況都會如此。因此,檢查 WSDL 客戶端和服務器端存根代碼,確保已經設置為返回和 Castor 生成對象同樣的正確類名。

請再看 清單5 ,可以看到兩個文件, StockQuotePortType.java StockQuoteSOAPBindingStub.java 顯示為用于服務器。為了實現目的,我們必須修改這兩個文件。必要的惟一修改就是檢查所有的類名,確保它們已經指向了 Castor 生成的類,而不是 WSDL2Java 生成的類。

在本實例中,只有一個類名發生了改變: _quote 。這個 WSDL2Java 生成的類 _quote ,在 Castor 中名稱改成了 Quote 。它們仍然在同一個包中,正如我們生成這兩個類的情形一樣。但是我們必須在引用它們的地方修改類的名字。

然后,文件 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;

對于文件 StockQuoteSOAPBindingStub.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 {...

現在,所有的服務器端代碼引用都指向了 Castor 類。這意味著,我們就可以修改 deploy.wsdd 文件去使用這些類和 Castor 配置。

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


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

清單6. 修改StockQuote服務的 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>

對于這個文件我們要做兩種類型的更改,以及還需要警惕的“局限性”。所有的更改都是針對 <typeMapping> 元素。第一個更改是修改 type 屬性下面的類名,使用 Castor 生成的類名,而不是 WSDL2Java 所生成的類名,如果這兩個名字有差別的情況下就需要進行這個更改。在我們的范例中,對于最開始的兩個映射, ns:changeType ns:lastTradeType ,和 Castor 中的類名是一樣的,所以沒有必要進行更改。但是,對于 ns:quote 類,類名需要進行更改,將 WSDL2Java 生成的 _quote 類名更改為 Castor 生成的 Quote 類名。

第二個進行的更改是:在 <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版本。

這里有一個需要提請注意的“局限性”,我們將著重強調一個地方也就是我們需要注意的。這個“局限性”必須處理 Axis 和 WSDL2Java 閱讀和編寫 XML 的方式。在我們的測試中,我們發現 WSDL2Java 偶爾生成無效的 XML,原因是在輸出中錯誤的防止了一些“<”和“>”。在最終的 <typeMapping> 元素 qname 屬性中就是這樣的一個地方。生成的 qname 屬性的值是“ ns:>quote ”,很明顯并不是有效的 XML ,因為“>”是受保護的字符。在這種情況下,刪除這個多余的“>”就能解決所有的問題,并且要盯住類似于上面情況的多余字符。

使用deploy.wsdd文件來部署服務
既然您已經更改了您的 deploy.wsdd 文件,而且做好了充分的準備,這時需要把它部署到服務器上。您可以通過從deploy.wsdd 文件中復制 <service> 元素到 WEB-INF/server-config.wsdd 文件,就可以完成這個工作。但是,您也可以使用 Axis 的便利部署工具來為您自己完成這一個工作。這個方法也確保了 server-config.wsdd 文件已經存在,如果不存在的話就創建這個文件,然后進行錯誤檢查,確保這一方法的正確性。

為了運行這個部署工具,確保您的工作目錄已經設置為 Axis 的根目錄,在該實例中是 WEB-INF ,然后運行下面的命令:
%java org.apache.axis.utils.Admin server classes/com/ibm/w3/services/stockquote/deploy.wsdd

如果這個命令得到了正確運行,將不返回任何錯誤,并且您的服務已經得到了部署?,F在,簡單的啟動您的服務器,然后可以進行下一步工作。

同樣,如果您想在后面的某一個步驟卸載您的測試服務,運行下列命令:
%java org.apache.axis.utils.Admin server classes/com/ibm/w3/services/stockquote/undeploy.wsdd

在 Axis 上測試您的服務


現在您已經構建了所有的相關代碼,集成 Axis 和 Castor,然后在 .wsdd 文件中部署服務。這時候,就可以進行測試了。通過指向您在 .wsdd 文件中定義的端點,您可以測試您安裝的應用,在本實例中,是指向 <context root>/services/StockQuoteSOAPPort 。您可以看到結果如 圖2 所示。



Axis 運行我們的 StockQuote 服務的結果

如果您不能得到這個顯示信息,這說明在 Axis 中安裝 StockQuote 服務出現了錯誤,這時重新查看一下您的配置以及前面的步驟,看到底是什么地方出現了問題。

如果顯示了這個消息,這時候您就可以編寫一些代碼來讓 getStockQuote 方法做一些實際的工作。







編寫方法

現在,什么都準備好了,但是您的服務器仍然不能做任何事情——您還沒有實現 getStockQuote 方法。由于相應的事情都已經做好,要進行著一個工作就非常簡單了。您只需要在 StockQuoteSOAPBindingImpl 中填寫您的方法,該方法和在 清單2 中的方法一一對應。

編寫 getStockQuote 方法


因為這是一個簡單的 Web 服務,在這一步驟中我們不用做太多的工作。但是該樣本代碼說明了使用 Castor 生成的數據綁定代碼以及由 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;
}
}

這里需要著重注意的是:在這里使用的對象和在客戶端使用的對象是一樣的,并且已經由 Castor 根據它的 Schema 進行了驗證,所以這些導入的數據可以安全的使用。如果導入的數據沒有得到驗證,在調用您的方法之前 Castor 會拋出一個異常。同樣,對于驗證您返回的數據這一機制將帶來一些益處,并且,如果您返回的數據沒有得到驗證,當 Axis 試圖序列化輸出的 bean 的時候, Castor 將拋出一個異常。

另外,本例中盡管我們的 bean 非常簡單——只有 Quote、Change LastTrade 對象—— Castor 處理這些復雜的 XML-Schema 數據模型非常完美,但是 WSDL2Java 將會遇到問題。








構建客戶端

既然您已經成功的在服務器端完成了運行 Axis 和 Castor 的所有工作,現在就可以構建一個客戶端了。

使用動態的 Axis Web 服務客戶端以及我們的 Castor 知識,我們將完成如下所示的一個初步工作,如 清單8

清單8. 構建 StockQuote 服務的客戶端的初步工作
                 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);

這樣就可以了,但是并不是這么自動化。然而,對 Axis 生成的客戶端存根使用一些巧妙的辦法,我們可以做得更好,可以有一個客戶端可以自動化的完成所有的安裝過程。


To make 為了讓存根使用 Castor 類,簡單的修改存根文件中的類名,就象和服務器存根中一樣——雖然,通常 Castor 和 WSDL2Java 生成同樣的類名,導致存根也是有同樣的類名。但并不是所有情況都這樣,所以檢查和更正顯得很重要。

您需要修改的文件是 StockQuoteSOAPBindingStub.java 。在本實例中, WSDL2Java 生成了用于 Quote 元素的類,名為 _quote ,但是 Castor 生成的名字為 Quote ,所以您需要在所有的地方進行更改。在這里并不列出所有的引用了這個類的地方,以及每一行需要更改,這是一個重復性的事情,并且對于閱讀沒有什么益處,我們將把這個工作交給您來做,僅僅需要瀏覽該文件,將所有對類 com.ibm.w3.services.stockquote._quote 的引用更改為 com.ibm.w3.services.stockquote.Quote 。

更改客戶端,使用 Castor serializers 代替 Axis serializers


目前,我們進行關鍵的更改:修改客戶端去使用 Castor 專有的 serializer 以及 deserializer 類,來代替缺省情況下 WSDL 生成的 BeanSerializers 。在服務器端,我們可以修改配置文件, deploy.wsdd ,設置使用哪個類來序列化和反序列化。不幸的是,客戶端并不使用這樣的一個配置文件,所以我們必須在代碼中修改。然而,這是一個非常簡單的修改,并且可以很清楚地看出,它和在服務器端對 deploy.wsdd 的修改是一樣的。

要 Castor serializer 和 deserializer 類,您需要做的第一件事情就是將它們添加到可能的序列器(Serializer)類列表中(在 StockQuoteSOAPBindingStub.java 文件的構造函數 public StockQuoteSOAPBindingStub(javax.xml.rpc.Service service) 中創建)。

清單 9. 更改 StockQuoteSOAPBindingStub.java 中的構造函數
            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 顯示了用粗體顯示的構造函數的修改。這個修改是自描述的:它添加了 CastorSerializerFactory.class CastorDeserializerFactory.class 作為后面代碼可能使用的選項,定義了用于輸入和輸出對象的序列器(serializer)和反序列器(deserializers)。

更新客戶端的最后一個步驟是:在上面提到的構造函數中,更改所有 cachedSerFactories.add(beansf) cachedDeserFactories.add(beandf) 出現的地方,用 Castor 的 BeanSerializer  代替 Axis 的 BeanSerializer 。這等同于我們對 deploy.wsdd 的更改,這里我們列出了 Castor 序列化和反序列化類,而不是 Axis 的 BeanSerializer。在用到您的對象時,將每一個 beansf beandf 的地方更改為 castorsf castordf 。在所有出現 beansf beandf 的地方,您都需要將它們改為 castorsf castordf ,在本例中,這兩者都出現了。

例如,如 清單10 所示的一個代碼塊的更改,其修改用粗體表示:

清單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 );

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

試用生成的客戶端


現在,您可以編寫客戶端代碼,如 清單11 。

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

StockQuotePortType port = service.getStockQuoteSOAPPort();

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

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

這樣更安全,更加自動化,而且更容易使用。并且,現在您獲得了一個 Web 服務,使用 Axis來進行通信,使用 Castor 進行驗證和數據綁定,這是一個端到端的情形。







Axis 和 Castor:文檔方式

正如您在本文中所看到的,整合文檔方式的服務、Castor 和 Axis 并不是想象的那么可怕,僅僅是安裝有點復雜。但是一旦您成功了,您的 Web 服務將具備文檔方式的靈活性和清晰度,對 Axis 健壯的支持,以及 Castor 的驗證和數據綁定優勢。

一旦您掌握了本文所講的全部內容,還有許多有趣的方面有待您去鉆研。例如,使用 Castor JDO,您只需寫幾行代碼就可以讓您的服務器端 Castor 對象把自己編組到 SQL 數據庫中。您也可以使用 Castor 的標準表達式和驗證支持來清理 Web 服務數據,這樣您的服務和客戶端的數據中出現錯誤的可能性就減少了。要了解關于這些主題的更進一步的信息,請參閱關于整合 Castor 和 Axis 的后續文章。



參考資料



作者簡介


Kevin Gibbs是一位軟件工程師,在英國劍橋大學學習 IBM 的高級 Internet 技術,獲得了 MA 學位。他早先從事 SashXB for Linux 腳本環境研究,目前正研究多種 Internet 技術,包括 Web 服務和 blogging 架構。您可以通過 kagibbs at us.ibm.com 與 Kevin 聯系。



Brian Goodman 是一位 IT 架構師,專門從事 IBM Intranet 的咨詢、交流和協作。您可以通過 bgoodman at us.ibm.com 與 Brian 聯系。



Elias Torres 是一位軟件工程師,在英國劍橋大學學習 IBM 的高級 Internet 技術,獲得了 MA 學位。他從事 Sash 腳本環境研究,探索一些技術,例如 blogging 和它們在公司環境的實際益處。您可以通過 eliast at us.ibm.com 與Elias聯系。

使用 Apache Axis 和 Castor 創建 Web 服務


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

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

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 色婷婷成人做爰A片免费看网站 | 国产精品小黄鸭一区二区三区 | 丝袜捆绑调教视频免费区 | 日韩色小说 | 伊人伊人| 精品一区二区三区18 | 久草电影天堂 | 555夜色666夜色精品站 | 国产精品美女久久久久久久久久久 | 成人情趣视频 | 成人激情综合网 | 一区二区三区 日韩 | 日本黄色三级网站 | 天天射天天干天天插 | 亚洲精品电影在线观看 | 国产大学生真实在线播放 | 亚洲午夜精品国产电影在线观看 | 加勒比久久综合 | 欧美色性视频 | 成人特级毛片 | 日韩在线短视频 | 亚洲成人观看 | 国产午夜亚洲精品国产 | 婷婷六月在线 | 呦呦在线视频 | 五月综合激情在线 | 日韩欧美中文字幕在线观看 | 国产乱色精品成人免费视频 | 国产精品久久av | 婷婷免费视频 | 噜噜色网 | 久久亚洲精品国产精品黑人 | 成人亚洲一区二区三区 | 亚洲六月丁香色婷婷综合久久 | 精品欧美一区视频在线观看 | 特级做a爰片毛片免费看一区 | 一区二区亚洲 | 欧美久久久久久久一区二区三区 | 国产精品成人在线 | 黄片一级毛片 | 精品国产影院 |