構建一個新的Web Services服務,會有很多種不同的方法,你即可以用pojo結合rpc模式來寫,也可以用axis2自己的axiom api從底層寫,也可以從wsdl生成相應框架,然後填寫相應邏輯。
對於wsdl生成框架代碼這種形式,又有不同的數據綁定可以使用。axis2 1.1 可以使用adb(axis2自己的data binding)、xmlbeans、jibx、jaxme、jaxbri。其中常用的還是前兩種,axis2官方是極力推薦自己的data binding的,因爲速度快,架構相對簡單,而且有一些獨有的特性。xmlbeans,是對模式支持最好的data binding,一些特別複雜的模式只能在xmlbeans下才能正確生成框架代碼。其他幾種代碼wsdl2java目前都不是支持得很好,都還在實驗改進階段。
面對這麼多數據綁定模式,很多人都無從選擇。官方maillist上也有好多人問該用哪個。查了一些資料,據說,adb很好用,而且速度快,如果只是簡單的模式,那麼使用這種數據綁定就可以了。xmlbeans的強力模式支持,可以支持足夠負責的模式,但是速度上也只是比adb低5%左右。
axis2的wsdl2java工具對於adb以及xmlbeans支持都已經很好了,可以直接從wsdl2java生成相應的綁定類
Axis2 還提供自己的簡單數據綁定框架,稱爲 Axis2 Data Binding (ADB)。這就允許用戶下載 Axis2 並使用它,而不用太多考慮數據綁定框架。由於 ADB 和 Axis2 內部元素之間實現了緊密的集成,可以預見,與其他框架相比,此框架的性能和生成代碼維護方面都更具優勢。
爲了充分利用資源,我們用上一個有關AXIOM專題的例子中生成的WSDL文件來爲這個例子服務
1.生成ADB服務框架。使用的WSDL文件如下:
- <wsdl:definitions xmlns:axis2="http://service.util.danlley.org" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
- xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
- xmlns:ns="http://service.util.danlley.org/xsd" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
- targetNamespace="http://service.util.danlley.org">
- <wsdl:types>
- <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" attributeFormDefault="qualified" elementFormDefault="qualified"
- targetNamespace="http://service.util.danlley.org/xsd">
- <xs:element name="getHelloMessageFault">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="getHelloMessageFault" type="xs:anyType" />
- xs:sequence>
- xs:complexType>
- xs:element>
- <xs:element name="getHelloMessage">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="element" nillable="true" type="xs:anyType" />
- xs:sequence>
- xs:complexType>
- xs:element>
- <xs:element name="getHelloMessageResponse">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="return" nillable="true" type="xs:anyType" />
- xs:sequence>
- xs:complexType>
- xs:element>
- <xs:element name="getMoreMessageFault">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="getMoreMessageFault" type="xs:anyType" />
- xs:sequence>
- xs:complexType>
- xs:element>
- <xs:element name="getMoreMessage">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="element" nillable="true" type="xs:anyType" />
- xs:sequence>
- xs:complexType>
- xs:element>
- <xs:element name="getMoreMessageResponse">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="return" nillable="true" type="xs:anyType" />
- xs:sequence>
- xs:complexType>
- xs:element>
- xs:schema>
- wsdl:types>
- <wsdl:message name="getHelloMessageMessage">
- <wsdl:part name="part1" element="ns:getHelloMessage" />
- wsdl:message>
- <wsdl:message name="getHelloMessageResponseMessage">
- <wsdl:part name="part1" element="ns:getHelloMessageResponse" />
- wsdl:message>
- <wsdl:message name="getHelloMessageFault">
- <wsdl:part name="part1" element="ns:getHelloMessageFault" />
- wsdl:message>
- <wsdl:message name="getMoreMessageMessage">
- <wsdl:part name="part1" element="ns:getMoreMessage" />
- wsdl:message>
- <wsdl:message name="getMoreMessageResponseMessage">
- <wsdl:part name="part1" element="ns:getMoreMessageResponse" />
- wsdl:message>
- <wsdl:message name="getMoreMessageFault">
- <wsdl:part name="part1" element="ns:getMoreMessageFault" />
- wsdl:message>
- <wsdl:portType name="HelloWorldAxiomPortType">
- <wsdl:operation name="getHelloMessage">
- <wsdl:input message="axis2:getHelloMessageMessage" />
- <wsdl:output message="axis2:getHelloMessageResponseMessage" />
- <wsdl:fault message="axis2:getHelloMessageFault" name="getHelloMessageFault" />
- wsdl:operation>
- <wsdl:operation name="getMoreMessage">
- <wsdl:input message="axis2:getMoreMessageMessage" />
- <wsdl:output message="axis2:getMoreMessageResponseMessage" />
- <wsdl:fault message="axis2:getMoreMessageFault" name="getMoreMessageFault" />
- wsdl:operation>
- wsdl:portType>
- <wsdl:binding name="HelloWorldAxiomSOAP11Binding" type="axis2:HelloWorldAxiomPortType">
- <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
- <wsdl:operation name="getHelloMessage">
- <soap:operation soapAction="urn:getHelloMessage" style="document" />
- <wsdl:input>
- <soap:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:input>
- <wsdl:output>
- <soap:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:output>
- <wsdl:fault name="getHelloMessageFault">
- <soap:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:fault>
- wsdl:operation>
- <wsdl:operation name="getMoreMessage">
- <soap:operation soapAction="urn:getMoreMessage" style="document" />
- <wsdl:input>
- <soap:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:input>
- <wsdl:output>
- <soap:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:output>
- <wsdl:fault name="getMoreMessageFault">
- <soap:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:fault>
- wsdl:operation>
- wsdl:binding>
- <wsdl:binding name="HelloWorldAxiomSOAP12Binding" type="axis2:HelloWorldAxiomPortType">
- <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
- <wsdl:operation name="getHelloMessage">
- <soap12:operation soapAction="urn:getHelloMessage" style="document" />
- <wsdl:input>
- <soap12:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:input>
- <wsdl:output>
- <soap12:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:output>
- <wsdl:fault name="getHelloMessageFault">
- <soap12:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:fault>
- wsdl:operation>
- <wsdl:operation name="getMoreMessage">
- <soap12:operation soapAction="urn:getMoreMessage" style="document" />
- <wsdl:input>
- <soap12:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:input>
- <wsdl:output>
- <soap12:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:output>
- <wsdl:fault name="getMoreMessageFault">
- <soap12:body use="literal" namespace="http://service.util.danlley.org" />
- wsdl:fault>
- wsdl:operation>
- wsdl:binding>
- <wsdl:service name="HelloWorldAxiom">
- <wsdl:port name="HelloWorldAxiomSOAP11port" binding="axis2:HelloWorldAxiomSOAP11Binding">
- <soap:address location="http://localhost:8080/axis2/services/HelloWorldAxiom" />
- wsdl:port>
- <wsdl:port name="HelloWorldAxiomSOAP12port" binding="axis2:HelloWorldAxiomSOAP12Binding">
- <soap12:address location="http://localhost:8080/axis2/services/HelloWorldAxiom" />
- wsdl:port>
- wsdl:service>
- wsdl:definitions>
2.生成工程框架
運行命令如下:WSDL2Java -uri resources/META-INF/HelloWorldAxiom.wsdl -p org.danlley.service.adb -d adb -s -ss -sd -ssi -o build/service
如果得到以下結果則說明執行成功:
--------------------------------------------------------------------------------
D:\eclipse\workspace\axis2adblab>WSDL2Java -uri resources/META-INF/HelloWorldAxi
om.wsdl -p org.danlley.service.adb -d adb -s -ss -sd -ssi -o build/service
Using AXIS2_HOME: D:\axis2-1.1.1
Using JAVA_HOME: C:\Program Files\Java\jdk1.5.0_06
D:\eclipse\workspace\axis2adblab>
--------------------------------------------------------------------------------
執行成功後在工程中出現的路徑如下:
--------------------------------------------------------------------------------
./build/service/build.xml
./build/service/resources/HelloWorldAxiom.wsdl
services.xml
./build/service/src/org/danlley/service/adb/GetHelloMessageFaultException.java
GetMoreMessageFaultException.java
HelloWorldAxiomMessageReceiverInOut.java
HelloWorldAxiomSkeleton.java
HelloWorldAxiomSkeletonInterface.java
./build/service/src/org/danlley/util/service/xsd/ExtensionMapper.java
GetHelloMessage.java
GetHelloMessageFault.java
GetHelloMessageResponse.java
GetMoreMessage.java
GetMoreMessageFault.java
GetMoreMessageResponse.java
--------------------------------------------------------------------------------
3.分析框架結構
Axis·2的服務確實夠周到的,不僅僅給我們把整個服務的框架都搭建好了,而且,還給我們順便連編譯工程所需用的Ant腳本都生成好了。真是不得不讓人感嘆一句"Apache辦事,我放心!"呵呵呵。
讓我們先大體看看生成的這些Java代碼的作用,GetHelloMessageFaultException和GetMoreMessageFaultException是用來做異常處理的。關於這個話題我以紀在以前的專題中已經有過提及(也就是跟Fault相關的話題)。
說到Fault就不得不再提提SOAP 處理模型,Axis2 體系結構定義了兩個管道(或流),分別稱爲 InPipe (InFlow) 和 OutPipe (OutFlow),用於處理服務器端的請求消息和響應消息。在客戶端,這兩個管道是反向的——換句話說,SOAP 請求消息流經 OutPipe,而響應消息流經 InPipe。管道或流包含一系列分爲階段的處理程序。除預先定義的階段和處理程序集外,用戶還可以在操作級別、服務級別或全局級別配置用戶階段和相關處理程序。處理程序充當 SOAP 消息的攔截器,可以處理 SOAP 消息的 Header 或 Body。InPipe 是通過以下階段進行配置的:
--------------------------------------------------------------------------------
TransportIn
PreDispatch
Dispatch
PostDispatch
PolicyDetermination
User phases
Message validation
--------------------------------------------------------------------------------
請求消息在通過 Inpipe 中配置的所有階段後,到達 MessageReceiver,然後由 MessageReceiver 調用實際服務實現。服務器的 OutPipe 包含以下階段:
--------------------------------------------------------------------------------
Message initialization
Policy determination
User phases
MessageOut
--------------------------------------------------------------------------------
用戶配置的階段位於這兩個管道的用戶階段(User phases) 部分。如果在執行這些管道的過程中發生錯誤,則這些錯誤將通過 InFaultPipe 或 OutFaultPipe 管道。收到 Fault 消息後,在客戶端調用 InFaultPipe;如果某個調用導致將錯誤發送到客戶端,則在服務器端調用 OutFaultPipe。用戶可以將處理程序添加到預先定義的階段,並且按照這些處理程序運行的順序進行配置。
那麼既然ADB pattern爲我們提供了GetHelloMessageFaultException、GetMoreMessageFaultException、GetHelloMessageFault和GetMoreMessageFault類。那也就意味着我們可以對這些類進行擴充,以滿足我們在實際當中的應用需求。由於我們Axiom的專題中舉例時,兩個實例均採用了in-Out模式,因此通過此工程的WSDL生成的ADB框架也就只有HelloWorldAxiomMessageReceiverInOut類來處理In-Out模式。GetHelloMessage和GetMoreMessage用來對接口HelloWorldAxiomSkeletonInterface的收取的數據進行封裝,而GetHelloMessageResponse和GetMoreMessageResponse類則用於封裝由HelloWorldAxiomSkeleton類處理後的結果。也就是說,真正的服務提供者就是HelloWorldAxiomSkeleton類。現在思路已經整理清楚,ADB生成的框架也基本上相當清楚了。那麼剩下就是爲我們新生成的框架動點小外科手術的時候了。
4.構建工程
根據我個人喜好,我的工程目錄結構整理後如下:
--------------------------------------------------------------------------------
./build.xml
./resources/HelloWorldAxiom.wsdl
services.xml
./src/main/java/org/danlley/service/adb/GetHelloMessageFaultException.java
GetMoreMessageFaultException.java
HelloWorldAxiomMessageReceiverInOut.java
HelloWorldAxiomSkeleton.java
HelloWorldAxiomSkeletonInterface.java
./src/main/java/org/danlley/util/service/xsd/ExtensionMapper.java
GetHelloMessage.java
GetHelloMessageFault.java
GetHelloMessageResponse.java
GetMoreMessage.java
GetMoreMessageFault.java
GetMoreMessageResponse.java
--------------------------------------------------------------------------------
工程目錄改變也就意味着我們需要修改Ant腳本,修改後的腳步如下: