详解Axis2实现Web Services之AXIOM篇
生活随笔
收集整理的這篇文章主要介紹了
详解Axis2实现Web Services之AXIOM篇
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
AXIOM——AXis 對象模型(AXis Object Model,AXIOM)是 Apache Axis 2 的 XML 對象模型,Axiom采用pull解析方式,基于StAX(JSR173),其目標是提供強大的特性組合徹底改變 XML 處理技術(Axiom和StAX緊密相關,要使用Axiom,StAX相關的jar包也必須在classpath下)。
?AXIOM 還不僅僅是另一種對象模型。它有著明確的設計目標:大幅提升 Apache 下一代 SOAP 協議棧 Axis 2 的性能。因為它突出了構造的輕型,并且僅當需要的時候才建立,結果造就了不同于其他對象模型的 AXIOM(也稱為 OM)。由于是輕型的,它盡可能地減輕對系統資源的壓力,特別是 CPU 和內存。同時,延遲構造又允許在其他部分還沒有完成的時候使用樹的一部分。AXIOM 強大的延遲構建能力源于底層的 Streaming API for XML (StAX) 解析器。AXIOM 提供了所有這些特性,同時幕后的復雜性對用戶是透明的。
使用 XMLBench Document Model Benchmark 測試的結果表明,AXIOM 的性能和現有的高性能對象模型相當。但是 AXIOM 的內存占用要好于現有多數依靠 SAX 和/或 DOM 輸入輸出的對象模型。因此對于 Web 服務引擎或內存受限制設備這樣的 XML 處理器,AXIOM 是一種理想的選擇,它可用于一般的 XML 處理,但是有一個對 SOAP 優化了的可選層。
AXIOM 超越了現有的 XML 處理技術,它把延遲構建和一種快速、輕型的可定制對象模型結合了起來, 提供了一種可以按需擴展的虛擬文檔模型,僅構建客戶端應用程序所請求的樹結構文檔模型表示。這種虛擬的文檔模型工作于 XML 文檔的元素級。當解析器報告元素開始標記時創建元素表示,但是該元素的初始形式僅僅只是一個殼,其中保存了對解析器的引用。
如果應用程序需要獲取元素內容 的細節信息,它只需要通過調用接口(如 org.apache.axiom.om.OMContainer.getChildren() 方法)的方法,就可以請求相應的信息。然后,在對這個方法調用的響應中,解析器將構建該元素的子內容。
解析器按照文檔順序(與 XML 文檔文本中項目的出現順序相同)傳遞數據,所以 AXIOM 所實現的按需構造需要某種靈活的處理方法。 Axiom的一些特性:
??? 1、Lightweight(輕量),更少的內存需要。
??? 2、Deferred building(延遲構建),可以說是最重要的OM特性,
??? 3、Pull based(pull模式),OM基于StAX--標準的pull parser API。
開始構建:Axiom在服務構建上看起來會比POJOs復雜些。
1.創建服務類: java 代碼package?org.danlley.util.service; ?? public?class?HelloWorldAxiom{ ?? ????public?OMElement?getHelloMessage(OMElement?element)?throws?XMLStreamException{ ?? ????????element.build(); ?? ????????element.detach(); ?? ????????return?element; ?? ????} ?? }?? 我們在創建過程中順便也就將我們例子中所要用到的幾個關鍵類引入: java 代碼 import?javax.xml.stream.XMLStreamException; ?? import?org.apache.axiom.om.OMAbstractFactory; ?? import?org.apache.axiom.om.OMElement; ?? import?org.apache.axiom.om.OMFactory; ?? import?org.apache.axiom.om.OMNamespace;??
這樣,我們已經有一個基本的服務類框架結構了,在該結構中我們定義了一個服務提供者getHelloMessage。他在獲取了一些特定的客戶端信息時為客戶端返回一些特定信息。
2.定義Ant腳本:與POJOs的實現方式比較來看,這個Ant腳本看上去要比他復雜了些 xml 代碼<project?basedir="."?default="generate.service">?? ?<property?environment="env"?/>?? ?<property?name="AXIS2_HOME"?value="${env.AXIS2_HOME}"?/>?? ?<property?name="build.dir"?value="build"?/>?? ?<path?id="axis2.classpath">?? ??<fileset?dir="${AXIS2_HOME}/lib">?? ???<include?name="*.jar"?/>?? ??</fileset>?? ?</path>?? ?<path?id="client.class.path">?? ??<fileset?dir="${AXIS2_HOME}/lib">?? ???<include?name="*.jar"?/>?? ??</fileset>?? ??<pathelement?location="${build.dir}/classes"?/>?? ?</path>?? ?<target?name="compile">?? ??<mkdir?dir="${build.dir}"?/>?? ??<mkdir?dir="${build.dir}/classes"?/>?? ??<javac?debug="on"?fork="true"?destdir="${build.dir}/classes"?srcdir="${basedir}/src"?classpathref="axis2.classpath">?? ??</javac>?? ?</target>?? ?<target?name="generate.service"?depends="compile">?? ??<copy?toDir="${build.dir}/classes"?failonerror="false">?? ???<fileset?dir="${basedir}/resources">?? ????<include?name="**/*.xml"?/>?? ????<include?name="**/*.wsdl"?/>?? ???</fileset>?? ??</copy>?? ??<jar?destfile="${build.dir}/HelloWorldAxiom.aar">?? ???<fileset?excludes="**/Test.class"?dir="${build.dir}/classes"?/>?? ??</jar>?? ?</target>?? ?<target?name="run.client"?depends="compile">?? ??<java?classname="samples.quickstart.clients.AXIOMClient">?? ???<classpath?refid="client.class.path"?/>?? ??</java>?? ?</target>?? ?<target?name="clean">?? ??<delete?dir="${build.dir}"?/>?? ?</target>?? </project>?? ? Target依賴關系如下:
generate.service→compile
run.client→compile
clean是一個單獨的獨立target,當然如果你希望在程序被build之前自動進行clean操作可以修改target間的依賴關系。
接下來我們要根據我們定義的接口來生成我們所要的WSDL,關于WSDL的相關話題我以前已經在我的一片關于Web Services的專題中進行了較為詳細的闡述,大家如果有興趣可以訪問:
3.根據類框架生成服務所需的WSDL:
在我們定義服務類的時候確定了我們將來要生成的服務aar包為 HelloWorldAxiom.aar,因此也就決定了WSDL的名字一定是HelloWorldAxiom.wsdl,在命令行切換到工程編譯路徑下:D:\eclipse\workspace\axis2axiomlab\build\classes>
運行如下命令:java2wsdl -cp . -cn org.danlley.util.service.HelloWorldAxiom -of HelloWorldAxiom.wsdl
說明:其中-cp是指classpath -cn是指classname 如果你運行后得到的運行結果如下,則說明運行成功,否則就需要查看 AXIS2_HOME是否正確配置了:
D:\eclipse\workspace\axis2axiomlab\build\classes>java2wsdl -cp . -cn org.danlley
.util.service.HelloWorldAxiom -of HelloWorldAxiom.wsdl
Using AXIS2_HOME:?? D:\axis2-1.1.1
Using JAVA_HOME:??? C:\Program Files\Java\jdk1.5.0_06
D:\eclipse\workspace\axis2axiomlab\build\classes>
得到HelloWorldAxiom.wsdl后我們將其放入resources/META-INF目錄下。對程序員來說,比較有價值的部分如下: xml 代碼<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>?? 在getHelloMessage節點中,我們可以知道接口所需傳入的參數,這里我們可以注意到,其實用自動生成工具生成的WSDL中,參數通常都是anyType類型的。getHelloMessageResponse節點則是提供了服務類在處理完相關業務后最后給我們返回出來的數據。
接下來就是 xml 代碼<wsdl:port?name="HelloWorldAxiomSOAP11port"?binding="axis2:HelloWorldAxiomSOAP11Binding">?? ?<soap:address?location="http://localhost:8080/axis2/services/HelloWorldAxiom"?/>?? </wsdl:port>?? 這段代碼對編寫客戶端以及通過IE訪問服務都非常有用。至于其他的,我在以前的專題中都或多或少有過一定的介紹,為了保證我們主題的完整性,我這里就不用在一一展開了。
4.在resources/META-INF目錄下編寫services.xml xml 代碼<service?name="HelloWorldAxiom"?scope="application">?? ?<description>Stock?Quote?Service</description>?? ?<operation?name="getHelloMessage">?? ??<messageReceiver?class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"?/>?? ?</operation>?? ?<parameter?name="ServiceClass">org.danlley.util.service.HelloWorldAxiom</parameter>?? </service>?? Axis2提供了兩種主要的信息收發方式(MEP,Message Exchange Pattern):In-Out、In-Only。
由于我們定義的服務類不僅需要輸入參數而且還需要將執行的結果返回到客戶端,因此,我們在這里使用In-Out Pattern。Axis2為支持這種方式提供了一個org.apache.axis2.receivers.RawXMLINOutMessageReceiver類。文件中定義的ServiceClass由于在POJOs專題中我已經做過了說明,因此我這里就不再詳述。
現在我們工程的整體框架已經構建完畢。 5.實現服務提供接口getHelloMessage java 代碼public?OMElement?getHelloMessage(OMElement?element)?throws?XMLStreamException{ ?? ????element.build(); ?? ????element.detach(); ?? ????OMElement?symbolElement=element.getFirstElement(); ?? ????String?helloworld=symbolElement.getText(); ?? ????System.out.println("We?got?the?messages?:"+(helloworld!=null?helloworld:"No?Msg!")); ?? ????//build?return?msg ?? ????String?returnText="You?are?Perfect,?Danlley!"; ?? ????OMFactory?fac=OMAbstractFactory.getOMFactory(); ?? ????OMNamespace?omNs=fac.createOMNamespace("http://service.util.danlley.org/xsd","ns"); ?? ????OMElement?method=fac.createOMElement("getHelloMessageResponse",omNs); ?? ????OMElement?value=fac.createOMElement("return",omNs); ?? ????value.addChild(fac.createOMText(value,returnText)); ?? ????method.addChild(value); ?? ????return?element; ?? }?? ?
6.編寫客戶端: java 代碼package?samples.quickstart.clients; ?? import?org.apache.axiom.om.OMAbstractFactory; ?? import?org.apache.axiom.om.OMElement; ?? import?org.apache.axiom.om.OMFactory; ?? import?org.apache.axiom.om.OMNamespace; ?? import?org.apache.axis2.Constants; ?? import?org.apache.axis2.addressing.EndpointReference; ?? import?org.apache.axis2.client.Options; ?? import?org.apache.axis2.client.ServiceClient; ?? public?class?AXIOMClient{ ?? ????private?static?EndpointReference?targetEPR=new?EndpointReference("http://localhost:8080/axis2/services/HelloWorldAxiom"); ?? ????public?static?OMElement?getPricePayload(String?msg){ ?? ????????OMFactory?fac=OMAbstractFactory.getOMFactory(); ?? ????????OMNamespace?omNs=fac.createOMNamespace("http://service.util.danlley.org/xsd","tns"); ?? ????????OMElement?method=fac.createOMElement("getHelloMessage",omNs); ?? ????????OMElement?value=fac.createOMElement("msg",omNs); ?? ????????value.addChild(fac.createOMText(value,msg)); ?? ????????method.addChild(value); ?? ????????return?method; ?? ????} ?? ????public?static?void?main(String[]?args){ ?? ????????try{ ?? ????????????OMElement?getPricePayload=getPricePayload("Hello?Danlley!"); ?? ????????????Options?options=new?Options(); ?? ????????????options.setTo(targetEPR); ?? ????????????options.setTransportInProtocol(Constants.TRANSPORT_HTTP); ?? ????????????//Optionally:TRANSPORT_JMS;TRANSPORT_LOCAL;TRANSPORT_MAIL;TRANSPORT_TCP; ?? ????????????ServiceClient?sender=new?ServiceClient(); ?? ????????????sender.setOptions(options); ?? ????????????System.out.println("done"); ?? ????????????Thread.sleep(3000); ?? ????????????OMElement?result=sender.sendReceive(getPricePayload); ?? ????????????String?response=result.getFirstElement().getText(); ?? ????????????System.out.println("Current?msg?of?danlley:?"+response); ?? ????????}catch(Exception?e){ ?? ????????????e.printStackTrace(); ?? ????????} ?? ????} ?? }??
運行ant腳本運行結果如下:
服務器端:
信息: Server startup in 6922 ms
We got the messages :Hello Danlley!
客戶端:
done
Current msg of danlley: You are Perfect, Danlley! 7.更加復雜點的例子 單條消息的解析過程過于簡單,在我們的實際工程應用中事實上是沒有任何實用價值的,那么如果是在一個節點中壓入多條信息那么我們應該怎么來處理呢,作為一個Axis2的新手如果你要是自己親自動手試一下就會發現,好像Axiom提供的接口在面對這種問題的時候似乎讓人牙癢。
現在我們在服務類中再增加一個getMoreMessage方法,其接收的參數約定如下: xml 代碼<tns:getMoreMessage?xmlns:tns="http://service.util.danlley.org/xsd">?? ????<tns:msg>Hello?Danlley</tns:msg>?? ????<tns:userPWD>Danlley@126.com</tns:userPWD>?? ????<tns:transactionKey>234545435464562</tns:transactionKey>?? </tns:getMoreMessage>?? 也就是說消息中存在3個節點的信息需要服務器端解析。一個比較笨的辦法如下: java 代碼 for(Iterator?it=element.getChildElements();it.hasNext();){ ?? ????OMElement?temp=(OMElement)it.next(); ?? ????if(temp.getLocalName().equalsIgnoreCase("msg")){ ?? ????????symbol=temp.getText(); ?? ????} ?? ????if(temp.getLocalName().equalsIgnoreCase("userPWD")){ ?? ????????userPWD=temp.getText(); ?? ????} ?? ????if(temp.getLocalName().equalsIgnoreCase("transactionKey")){ ?? ????????transactionKey=temp.getText(); ?? ????} ?? }??
在該算法中,同一個分支中的3個同級節點在解析過程中就需要循環3次,那么可以試想一下,如果我們這里需要傳送1000個節點,然后在同一時間有成千上萬的人同時請求訪問該服務。那么這個循環的代價就已經不可小視了。也就是說,對于小數據量在小訪問量的情況下這種方式還可以勉強應付,但是對于在大數據流大訪問量的情況下,這種處理方式就顯得有些力不從心了。那么有什么好的辦法沒有,答案當然是肯定的。 基本思路就是拿到了客戶端發送過來的數據后不直接使用Axiom的接口,而是使用DOM4J去處理。具體做法如下: java 代碼Document?doc=DocumentHelper.parseText(element.toString()); ?? String?msg=doc.selectSingleNode("//tns:msg").getText();?? 其中的element類型就是OMElement。 實現getMoreMessage方法: java 代碼 public?OMElement?getMoreMessage(OMElement?element)?throws?XMLStreamException{ ?? ????try{ ?? ????????element.build(); ?? ????????element.detach(); ?? ????????DocumentFactory?dom=new?DocumentFactory(); ?? ????????dom.createDocument(element.toString()); ?? ????????System.out.println(element.toString()); ?? ????????Document?doc=DocumentHelper.parseText(element.toString()); ?? ????????String?msg=doc.selectSingleNode("//tns:msg").getText(); ?? ????????String?userPWD=doc.selectSingleNode("//tns:userPWD").getText(); ?? ????????String?transactionKey=doc.selectSingleNode("//tns:transactionKey").getText(); ?? ????????System.out.println("\n?msg="+msg+"\n?userPWD="+userPWD+"\n?transactionKey="+transactionKey); ?? ???????? ?? ???????? ?? ????????OMFactory?fac=OMAbstractFactory.getOMFactory(); ?? ????????OMNamespace?omNs=fac.createOMNamespace("http://service.util.danlley.org/xsd","ns"); ?? ????????OMElement?method=fac.createOMElement("getHelloMessageResponse",omNs); ?? ????????OMElement?value=fac.createOMElement("return",omNs); ?? ????????String?returnText="MultiMessage?for?U,?Danlley!"; ?? ????????returnText=returnText+"\n?msg="+msg+"\t?userPWD="+userPWD+"\t?transactionKey="+transactionKey; ?? ????????value.addChild(fac.createOMText(value,returnText)); ?? ????????method.addChild(value); ?? ????????return?method; ?? ????}catch(OMException?e){ ?? ????????e.printStackTrace(); ?? ????????return?null; ?? ????}catch(DocumentException?e){ ?? ????????e.printStackTrace(); ?? ????????return?null; ?? ????} ?? }??
重新生成WSDL文件(過程省略--前面有^_^)并用改寫后的生成的WSDL文件覆蓋之前生成的文件
改寫services.xml文件 xml 代碼<service?name="HelloWorldAxiom"?scope="application">?? ?<description>Stock?Quote?Service</description>?? ?<operation?name="getHelloMessage">?? ??<messageReceiver?class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"?/>?? ?</operation>?? ?<operation?name="getMoreMessage">?? ??<messageReceiver?class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"?/>?? ?</operation>?? ?<parameter?name="ServiceClass">org.danlley.util.service.HelloWorldAxiom</parameter>?? </service>?? ? 運行ant打包 執行客戶端查看執行情況:
服務器端:
<tns:getMoreMessage xmlns:tns="http://service.util.danlley.org/xsd"><tns:msg>Hel
lo Danlley</tns:msg><tns:userPWD>Danlley@126.com</tns:userPWD><tns:transactionKe
y>234545435464562</tns:transactionKey></tns:getMoreMessage> msg=Hello Danlley
?userPWD=Danlley@126.com
?transactionKey=234545435464562
客戶端:
done
Current msg of danlley: MultiMessage for U, Danlley!
?msg=Hello Danlley? userPWD=Danlley@126.com? transactionKey=234545435464562
8.查缺補漏 說了半天我們都是在以一種方式介紹Axiom的使用,但是對于In-Only模式,卻沒有給予特殊照顧,那么我就在這里在多說幾句。僅僅就In-Out、In-Only兩種模式之間的差異說明一下:
第一: 服務類接口,In-Out模式有返回值,但是In-Only沒有(void類型) 第二:services.xml中messageReceiver在In-Only模式中使用org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver類,而In-Out模式中使用org.apache.axis2.receivers.RawXMLINOutMessageReceiver類 第三:客戶端程序的編寫。In-Out模式需要收發消息(sender.sendReceive(element)),而In-Only只能發送消息(sender.fireAndForget(updatePayload))。 第四:WSDL。雖然會有差異,但是由于是自動生成的,因此可以看懂就OK了。
9.關于StAX J2EE/XML開發者通常都是使用文檔對象模型(DOM)API或簡單的API for XML(SAX) API來分析XML文檔。然而,這些API都有其缺點。其中,DOM API的缺點之一是消耗大量的內存,因為在該XML文檔可以被導航之前,必須創建一個完整的XML文檔的內存結構。而SAX API的缺點在于,它實例了一種推分析模型API,其中分析事件是由分析器生成的。比較之下,StAX則是基于一種拉分析模型。
比較于推分析,拉分析具有如下一些優點:
1. 在拉分析中,事件是由分析應用程序生成的,因此把分析規則提供到客戶端而不是分析器。
2. 拉分析的代碼更簡單并且它比推分析有更少的庫。
3. 拉分析客戶端能同時讀多個XML文檔。
4. 拉分析允許你過濾XML文檔并且跳過分析事件。
針對于XML的流式API(StAX),是在2004年3月的JSR 173規范中引入,這是一種針對XML的流式拉分析API。StAX是JDK 6.0提供的一種新特征,你可以從此處下載它的測試版本試用。https://mustang.dev.java.net/
一個推模型分析器不斷地生成事件,直到XML文檔被完全分析結束。但是,拉分析由應用程序進行調整;因此,分析事件是由應用程序生成的。這意味著,使用StaX,你可以推遲分析-在分析時跳過元素并且分析多個文檔。在使用DOM API的時候,你必須把整個的XML文檔分析成一棵DOM結構,這樣也就降低了分析效率。而借助于StAX,在分析XML文檔時生成分析事件。
StAX API的實現是使用了Java Web服務開發(JWSDP)1.6,并結合了Sun Java流式XML分析器(SJSXP)-它位于javax.xml.stream包中。其實,StaX僅僅是JDK 6.0所提供的XML新特征之一。新的JDK 6.0還提供了對針對于XML-Web服務的Java架構(JAX-WS)2.0,針對于XML綁定的Java API(JAXB) 2.0,XML數字簽名API的支持,甚至還支持SQL:2003 'XML'數據類型。 有關于StAX分析器與其它分析器的比較在此不多介紹。以后準備單另開一個專題來專門研究。關于StAX的更多話題請查看以下地址: http://today.java.net/pub/a/today/2006/07/20/introduction-to-stax.html 注:此文檔在8月之前將一直處于維護狀態 參考資料: http://blog.csdn.net/ckangtai/archive/2007/04/03/1550374.aspx
http://www.ibm.com/developerworks/cn/xml/x-axiom/
http://ws.apache.org/axis2/1_2/index.html
http://ws.apache.org/commons/axiom/OMTutorial.html
http://www.blogjava.net/juleven/archive/2006/12/08/86458.html
http://searchwebservices.techtarget.com.cn/tips/434/2164934.shtml?S_TACT=105AGX52&S_CMP=tag-csdn
http://tech.sina.com.cn/s/2006-06-13/1653988332.shtml
https://mustang.dev.java.net/
https://jdk6.dev.java.net/
?AXIOM 還不僅僅是另一種對象模型。它有著明確的設計目標:大幅提升 Apache 下一代 SOAP 協議棧 Axis 2 的性能。因為它突出了構造的輕型,并且僅當需要的時候才建立,結果造就了不同于其他對象模型的 AXIOM(也稱為 OM)。由于是輕型的,它盡可能地減輕對系統資源的壓力,特別是 CPU 和內存。同時,延遲構造又允許在其他部分還沒有完成的時候使用樹的一部分。AXIOM 強大的延遲構建能力源于底層的 Streaming API for XML (StAX) 解析器。AXIOM 提供了所有這些特性,同時幕后的復雜性對用戶是透明的。
使用 XMLBench Document Model Benchmark 測試的結果表明,AXIOM 的性能和現有的高性能對象模型相當。但是 AXIOM 的內存占用要好于現有多數依靠 SAX 和/或 DOM 輸入輸出的對象模型。因此對于 Web 服務引擎或內存受限制設備這樣的 XML 處理器,AXIOM 是一種理想的選擇,它可用于一般的 XML 處理,但是有一個對 SOAP 優化了的可選層。
AXIOM 超越了現有的 XML 處理技術,它把延遲構建和一種快速、輕型的可定制對象模型結合了起來, 提供了一種可以按需擴展的虛擬文檔模型,僅構建客戶端應用程序所請求的樹結構文檔模型表示。這種虛擬的文檔模型工作于 XML 文檔的元素級。當解析器報告元素開始標記時創建元素表示,但是該元素的初始形式僅僅只是一個殼,其中保存了對解析器的引用。
如果應用程序需要獲取元素內容 的細節信息,它只需要通過調用接口(如 org.apache.axiom.om.OMContainer.getChildren() 方法)的方法,就可以請求相應的信息。然后,在對這個方法調用的響應中,解析器將構建該元素的子內容。
解析器按照文檔順序(與 XML 文檔文本中項目的出現順序相同)傳遞數據,所以 AXIOM 所實現的按需構造需要某種靈活的處理方法。 Axiom的一些特性:
??? 1、Lightweight(輕量),更少的內存需要。
??? 2、Deferred building(延遲構建),可以說是最重要的OM特性,
??? 3、Pull based(pull模式),OM基于StAX--標準的pull parser API。
開始構建:Axiom在服務構建上看起來會比POJOs復雜些。
1.創建服務類: java 代碼
這樣,我們已經有一個基本的服務類框架結構了,在該結構中我們定義了一個服務提供者getHelloMessage。他在獲取了一些特定的客戶端信息時為客戶端返回一些特定信息。
2.定義Ant腳本:與POJOs的實現方式比較來看,這個Ant腳本看上去要比他復雜了些 xml 代碼
generate.service→compile
run.client→compile
clean是一個單獨的獨立target,當然如果你希望在程序被build之前自動進行clean操作可以修改target間的依賴關系。
接下來我們要根據我們定義的接口來生成我們所要的WSDL,關于WSDL的相關話題我以前已經在我的一片關于Web Services的專題中進行了較為詳細的闡述,大家如果有興趣可以訪問:
3.根據類框架生成服務所需的WSDL:
在我們定義服務類的時候確定了我們將來要生成的服務aar包為 HelloWorldAxiom.aar,因此也就決定了WSDL的名字一定是HelloWorldAxiom.wsdl,在命令行切換到工程編譯路徑下:D:\eclipse\workspace\axis2axiomlab\build\classes>
運行如下命令:java2wsdl -cp . -cn org.danlley.util.service.HelloWorldAxiom -of HelloWorldAxiom.wsdl
說明:其中-cp是指classpath -cn是指classname 如果你運行后得到的運行結果如下,則說明運行成功,否則就需要查看 AXIS2_HOME是否正確配置了:
D:\eclipse\workspace\axis2axiomlab\build\classes>java2wsdl -cp . -cn org.danlley
.util.service.HelloWorldAxiom -of HelloWorldAxiom.wsdl
Using AXIS2_HOME:?? D:\axis2-1.1.1
Using JAVA_HOME:??? C:\Program Files\Java\jdk1.5.0_06
D:\eclipse\workspace\axis2axiomlab\build\classes>
得到HelloWorldAxiom.wsdl后我們將其放入resources/META-INF目錄下。對程序員來說,比較有價值的部分如下: xml 代碼
接下來就是 xml 代碼
4.在resources/META-INF目錄下編寫services.xml xml 代碼
由于我們定義的服務類不僅需要輸入參數而且還需要將執行的結果返回到客戶端,因此,我們在這里使用In-Out Pattern。Axis2為支持這種方式提供了一個org.apache.axis2.receivers.RawXMLINOutMessageReceiver類。文件中定義的ServiceClass由于在POJOs專題中我已經做過了說明,因此我這里就不再詳述。
現在我們工程的整體框架已經構建完畢。 5.實現服務提供接口getHelloMessage java 代碼
6.編寫客戶端: java 代碼
運行ant腳本運行結果如下:
服務器端:
信息: Server startup in 6922 ms
We got the messages :Hello Danlley!
客戶端:
done
Current msg of danlley: You are Perfect, Danlley! 7.更加復雜點的例子 單條消息的解析過程過于簡單,在我們的實際工程應用中事實上是沒有任何實用價值的,那么如果是在一個節點中壓入多條信息那么我們應該怎么來處理呢,作為一個Axis2的新手如果你要是自己親自動手試一下就會發現,好像Axiom提供的接口在面對這種問題的時候似乎讓人牙癢。
現在我們在服務類中再增加一個getMoreMessage方法,其接收的參數約定如下: xml 代碼
在該算法中,同一個分支中的3個同級節點在解析過程中就需要循環3次,那么可以試想一下,如果我們這里需要傳送1000個節點,然后在同一時間有成千上萬的人同時請求訪問該服務。那么這個循環的代價就已經不可小視了。也就是說,對于小數據量在小訪問量的情況下這種方式還可以勉強應付,但是對于在大數據流大訪問量的情況下,這種處理方式就顯得有些力不從心了。那么有什么好的辦法沒有,答案當然是肯定的。 基本思路就是拿到了客戶端發送過來的數據后不直接使用Axiom的接口,而是使用DOM4J去處理。具體做法如下: java 代碼
重新生成WSDL文件(過程省略--前面有^_^)并用改寫后的生成的WSDL文件覆蓋之前生成的文件
改寫services.xml文件 xml 代碼
服務器端:
<tns:getMoreMessage xmlns:tns="http://service.util.danlley.org/xsd"><tns:msg>Hel
lo Danlley</tns:msg><tns:userPWD>Danlley@126.com</tns:userPWD><tns:transactionKe
y>234545435464562</tns:transactionKey></tns:getMoreMessage> msg=Hello Danlley
?userPWD=Danlley@126.com
?transactionKey=234545435464562
客戶端:
done
Current msg of danlley: MultiMessage for U, Danlley!
?msg=Hello Danlley? userPWD=Danlley@126.com? transactionKey=234545435464562
8.查缺補漏 說了半天我們都是在以一種方式介紹Axiom的使用,但是對于In-Only模式,卻沒有給予特殊照顧,那么我就在這里在多說幾句。僅僅就In-Out、In-Only兩種模式之間的差異說明一下:
第一: 服務類接口,In-Out模式有返回值,但是In-Only沒有(void類型) 第二:services.xml中messageReceiver在In-Only模式中使用org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver類,而In-Out模式中使用org.apache.axis2.receivers.RawXMLINOutMessageReceiver類 第三:客戶端程序的編寫。In-Out模式需要收發消息(sender.sendReceive(element)),而In-Only只能發送消息(sender.fireAndForget(updatePayload))。 第四:WSDL。雖然會有差異,但是由于是自動生成的,因此可以看懂就OK了。
9.關于StAX J2EE/XML開發者通常都是使用文檔對象模型(DOM)API或簡單的API for XML(SAX) API來分析XML文檔。然而,這些API都有其缺點。其中,DOM API的缺點之一是消耗大量的內存,因為在該XML文檔可以被導航之前,必須創建一個完整的XML文檔的內存結構。而SAX API的缺點在于,它實例了一種推分析模型API,其中分析事件是由分析器生成的。比較之下,StAX則是基于一種拉分析模型。
比較于推分析,拉分析具有如下一些優點:
1. 在拉分析中,事件是由分析應用程序生成的,因此把分析規則提供到客戶端而不是分析器。
2. 拉分析的代碼更簡單并且它比推分析有更少的庫。
3. 拉分析客戶端能同時讀多個XML文檔。
4. 拉分析允許你過濾XML文檔并且跳過分析事件。
針對于XML的流式API(StAX),是在2004年3月的JSR 173規范中引入,這是一種針對XML的流式拉分析API。StAX是JDK 6.0提供的一種新特征,你可以從此處下載它的測試版本試用。https://mustang.dev.java.net/
一個推模型分析器不斷地生成事件,直到XML文檔被完全分析結束。但是,拉分析由應用程序進行調整;因此,分析事件是由應用程序生成的。這意味著,使用StaX,你可以推遲分析-在分析時跳過元素并且分析多個文檔。在使用DOM API的時候,你必須把整個的XML文檔分析成一棵DOM結構,這樣也就降低了分析效率。而借助于StAX,在分析XML文檔時生成分析事件。
StAX API的實現是使用了Java Web服務開發(JWSDP)1.6,并結合了Sun Java流式XML分析器(SJSXP)-它位于javax.xml.stream包中。其實,StaX僅僅是JDK 6.0所提供的XML新特征之一。新的JDK 6.0還提供了對針對于XML-Web服務的Java架構(JAX-WS)2.0,針對于XML綁定的Java API(JAXB) 2.0,XML數字簽名API的支持,甚至還支持SQL:2003 'XML'數據類型。 有關于StAX分析器與其它分析器的比較在此不多介紹。以后準備單另開一個專題來專門研究。關于StAX的更多話題請查看以下地址: http://today.java.net/pub/a/today/2006/07/20/introduction-to-stax.html 注:此文檔在8月之前將一直處于維護狀態 參考資料: http://blog.csdn.net/ckangtai/archive/2007/04/03/1550374.aspx
http://www.ibm.com/developerworks/cn/xml/x-axiom/
http://ws.apache.org/axis2/1_2/index.html
http://ws.apache.org/commons/axiom/OMTutorial.html
http://www.blogjava.net/juleven/archive/2006/12/08/86458.html
http://searchwebservices.techtarget.com.cn/tips/434/2164934.shtml?S_TACT=105AGX52&S_CMP=tag-csdn
http://tech.sina.com.cn/s/2006-06-13/1653988332.shtml
https://mustang.dev.java.net/
https://jdk6.dev.java.net/
總結
以上是生活随笔為你收集整理的详解Axis2实现Web Services之AXIOM篇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信引流软件哪里找?哪个引流软件比较可靠
- 下一篇: php mcrypt_decrypt用法