前言java
今天主要講解下WebService的兩個流行的框架Axis和CXF。web
正題apache
1、服務端發佈WebService瀏覽器
在講解以前,咱們先來看一下這篇博客主要講解的內容:tomcat
每一種框架都有本身的特色,有本身的側重,可是他們的共同之處在於對發佈WebService進行了封裝,因此咱們只需編寫一個配置文件或者使用@WebService 註解就能夠發佈WebService,咱們這裏着重說一下他們各自的特色:服務器
1.Axis1網絡
Axis1有兩種發佈方式:app
1)JWS方式框架
a.這種方式很簡單,只須要將源碼java文件放到AXIS_HOME下面,而後將後綴改成.jws,這樣,Axis 會自動編譯.jws文件,並把它自動加入到Java WebServie的服務中。webapp
b.可是這種方式的缺點是:只能是java源代碼,同時類中不能含有包名。
2)WSDD方式
1.寫一個java類(須要引入axis的jar包)
2.配置web.xml文件(配置AxisServlet,AdminServlet,SOAPMonitorService和AxisHTTPSessionListener)
3.寫一個deloy.wsdd文件,部署項目(tomcat啓動就能夠部署項目)
安裝axis1到tomcat:
1.Axis官方網站:http://ws.apache.org/axis/,能夠在官網下載最新1.4的包:axis-bin-1_4.zip
2.將解壓後的axis-1_4\webapps\下的axis目錄考到%TOMCAT_HOME%/Webapps/目錄下
3.啓動tomcat後在瀏覽器裏輸入http://localhost:port/axis
4.點擊上圖中的Validataion連接,頁面上會提示已經有的包和缺乏的包的信息,根據提示將必須的包下載全,
將這些類包複製到%tomcathome%/webapps/axis/WEB-INF/lib/目錄下
從新啓動tomcat,直到Validation頁面中看不到有Error與Warning的提示信息。
2.Axis2
客戶端對於數據類型的不一樣有兩種調用方式:RPCServiceClient和OMAbstractFactory方式
1)RPC方式:
處理基本的數據類型,如String,int等
2)OM方式:
可處理基本數據類型和自定義數據類型(好比java實體對象):經過xml的參數形式進行傳遞(傳遞的參數須要轉換爲OMElement)
注:若是參數或返回值是List類型則須要進行手動處理轉換(手動編寫一個服務端對傳遞過來的參數進行處理,將傳過來的OMElement手動轉換爲List類型,調用執行方法,而後將返回的List類型再轉換爲OMElement傳回客戶端)
Axis2發佈文件(編寫services.xml)
1.將官網下載的axis2.war包拷貝到tomcat_home/webapps下,運行即會解壓
2.將其conf,modules和services文件夾拷貝到項目的WEB-INF下面,並將lib下的jar包拷貝到web-inf/lib下面
3.配置Web.xml(配置AxisServlet和AxisAdminServlet)
4.編寫services下面的services.xml文件,指定要發佈的類
3.CXF
CXF發佈WebService有三種方式:main方式,基於和不基於Spring發佈到容器
1)main方式
引入jar包,在接口和實現類上使用@WebService 便可,發佈完成後便可在瀏覽器中訪問url,不須要啓動tomcat等服務。
2)不基於Spring方式發佈到容器
a)引入cxf的jar包,編寫web.xml(配置自定義的CXFServlet,該CXFServlet須要繼承CXFNonSpringServlet)
b)編寫實體類,業務類和服務類(實體類須要和服務類在同一包下,不然報錯)
c)啓動Tomcat,便可發佈服務
3)基於Spring方式發佈到容器
a)web.xml配置(Spring配置,cxf封裝的CXFServlet配置)
b)applicationContext-server.xml配置
<!--Import apache CXF bean definition 固定-->
<importresource="classpath:META-INF/cxf/cxf.xml" />
<importresource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<importresource="classpath:META-INF/cxf/cxf-servlet.xml" />
<!--services接口配置 -->
<beanid="helloServicesBean"class="com.ms.services.impl.HelloServicesImpl" />
<!--CXF 配置WebServices的服務名及訪問地址 -->
<jaxws:serverid="helloServices" address="/HelloServices"
serviceClass="com.ms.services.IHelloServices">
<!--要暴露的webservice服務 -->
<jaxws:serviceBean>
<refbean="helloServicesBean"/>
</jaxws:serviceBean>
</jaxws:server>
c)編寫類
實體類
服務接口(類頭使用@WebService)
服務實現(類頭使用@WebService(endpointInterface="com.ms.services.IHelloServices"))
以上是關於Axis和CXF發佈特色及其須要注意的地方,是我作例子時的總結,有興趣的同窗能夠下載源碼。
2、客戶端調用WebService
服務端將接口發佈成功後,就等着客戶端來進行調用了,客戶端如何並經過什麼方式來調用咱們服務端發佈的wsdl文件呢?
1.調用一次WebService的本質:
1.客戶端把調用方法參數,轉換生成XML文檔片斷(SOAP消息,input消息,該文檔片斷必須符合WSDL定義的格式),經過網絡,把XML文檔片斷傳給服務器
2.服務器接收到XML文檔片斷,解析XML文檔片斷,提取其中的數據,並把數據轉換調用WebService所須要的參數值。
3.服務器執行方法。
4.把執行方法獲得的返回值,再次轉換生成爲XML文檔片斷(SOAP消息,output消息)——該文檔片斷必須符合WSDL定義的格式,經過網絡,把XML文檔片斷傳給客戶端。
5.客戶端接收到XML文檔片斷,解析XML文檔片斷,提取其中數據,並把數據轉換調用WebService的返回值。
從上面調用本質來看,要一個語言支持WebService,惟一的要求是:該語言支持XML文檔解析、生成、支持網絡傳輸。
2.客戶端調用方式:
客戶端調用服務端方法整體來講有三種方式:
1)DII(Dynamic Invocation Interface)
採用直接調用方式,能夠在程序中設置諸多的調用屬性,使用較爲靈活,可是調用過程卻相對繁瑣複雜,易形成代碼膨脹且可重用性低,每次調用不一樣的Web Service都要重複進行大量編碼。
這也是咱們比較經常使用的一種方法,就是調用invoke方法,傳入方法名和方法參數便可。
2)Stubs
JAX-RPC使用靜態的Stub方式包裝對底層接口的調用,從而提供一種更爲簡便的調用方式。使用該方式須要利用支持環境(好比Axis)所提供的工具根據WSDL預生成WebService客戶端的實現代碼。所以若是服務的WSDL發生變化,就必須從新生成新的客戶端代碼並進行從新部署。
該方法須要使用wsdl2java命令來預生成WebService客戶端代碼,爲了支持該命令,須要安裝一些環境。
3)Dynamic Proxy
動態代理(Dynamic Proxy)的方法實現對Web Service的動態調用,能夠在運行時根據用戶定義的Client端接口建立適配對象。從而避免了直接操做底層的接口,減小了客戶端的冗餘,屏蔽了調用相關的複雜性。
該方法主要在於客戶端接口,該客戶端接口須要繼承java.rmi.Remote接口,而後將服務端的接口中的方法copy過來。
小結:
從發展歷史角度來看,很容易理解他們的側重點,Axis1最先,因此注重的只是簡單的發佈接口便可,以後隨之Axis2對其進行了優化,能夠支持自定義參數,但並不完善,因此CXF的出現對這一功能進行了完善而且適應了潮流,實現了與Spring的集成,跟這些比起來,EJB3中對於WebService的支持只須要使用一個@WebService 便可完成,因此軟件的開發是讓使用者變傻,而咱們學習這些是爲了理解其原理和本質。