XFire 最新生火指南(上)
作者: 江南白衣,作者保留版權(quán),轉(zhuǎn)載請(qǐng)注明出處。
1. 概述
XFire 是全球眾多牛人在與axis系列對(duì)比后一致投票的選擇。我比較欣賞的特性有:
- 與Spring整合
,無須生成一堆文件,無須打包獨(dú)立war,直接將應(yīng)用中的Pojo導(dǎo)出為Web服務(wù)。
- Aegis
--超簡(jiǎn)約的默認(rèn)Java XML 綁定機(jī)制,且可以Plugin其他綁定機(jī)制。
- JSR181--annotatiton驅(qū)動(dòng)
的POJO WebService配置。
- 基于Stax的高性能框架
。
- 脫離Web服務(wù)器的單元測(cè)試能力。
網(wǎng)上的文檔與例子總是不新,請(qǐng)大家拋開所有的文檔,所有的Axis習(xí)慣,單看這份代表XFire1.2.2最簡(jiǎn)約做法的指南。
1.1 SpringSide的封裝與演示
- 封裝代碼:core/src/java/org/springside/components/xfire
封裝了XFireClientFactory工廠類(封裝了返回Client的API)與XFireTestCase(加入Open Session In View的TestCase基類)兩個(gè)簡(jiǎn)便類。 - Bookstore 示例代碼: /examples/bookstore/src/java/org.springside/components/xfire
(Java)與:/examples/bookstore/webapp/webservices
(頁(yè)面)
演示了XFire結(jié)合Spring的XFireExporter, JSR181及WS-Security。
2. 生火指南
2.1 修改web.xml,在Web應(yīng)用中增加XFire的入口
注意XFire已有了自己的Servlet,不再依賴Spring MVC的DispatchServlet,也就遠(yuǎn)離了大家不熟悉的Spring MVC URL Mapping,與Spring達(dá)致完美的整合。
這里指定了路徑為/service/* ,即WebService的URL會(huì)被默認(rèn)生成為http://www.xxx.com/yyy/service/ServiceName,其中ServiceName默認(rèn)為下面的接口名。
<servlet> <servlet-name>xfire</servlet-name> <servlet-class>org.codehaus.xfire.spring.XFireSpringServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>xfire</servlet-name> <url-pattern>/service/*</url-pattern> </servlet-mapping>
如果應(yīng)用使用了Hibernate,使用了OpenSessionInView Filter,注意配置OSIV filter覆蓋 xfire servlet的路徑,即本例中的/service/*。
2.2 編寫窄接口,抽取POJO中要導(dǎo)出的服務(wù)
從已有的BookManager.java中,抽取出一個(gè)窄接口,僅暴露需要導(dǎo)出為Web Service的方法。注意BookManger.java是POJO,不需要任何WebService相關(guān)代碼。
窄接口一方面滿足了安全要求,不用整個(gè)BookManager所有方法導(dǎo)出為Web Service;另一方面,XFire暫時(shí)也只支持基于接口的Proxy。
public interface BookService { List<Book> findBooksByCategory(String cateoryId); }
2.3 配置Java-XML Binding
XFire默認(rèn)的Aegis Binding語(yǔ)法非常簡(jiǎn)單,在SpringSide的例子里幾乎一行配置都不用寫,是我見過最簡(jiǎn)單的binding定義,大大優(yōu)于其他以設(shè)計(jì)復(fù)雜為終極目標(biāo)的方案。
對(duì)象的屬性、函數(shù)的參數(shù)和返回值如果為int、String、Date等普通類型以及由普通類型組成的復(fù)雜對(duì)象都無需定義。我見到只有兩種情況需要定義:
- 無法使用泛型定義Collection中元素的類型時(shí)--如List findBooks()。如果能寫成List<Book> findBooks()就也不需要了。
- 需要為屬性定義不同的名字,或者定義復(fù)雜對(duì)象里的某些屬性不要輸出。
如果實(shí)在需要aegis配置, XFire以約定俗成代替配置,所有Service和Entity Bean的binding文件要求命名為xxx.aegis.xml,而且要和原來的類sit together在同一目錄里。
<mapping> <!--配置findBooksByName服務(wù)的返回值,List內(nèi)對(duì)象為Book--> <method name="findBooksByName"> <return-type componentType="org.springside.bookstore.domain.Book"/> </method> <!--配置Category類,忽略內(nèi)嵌的products屬性不要輸出XML--> <property name="products" ignore="true"/> </mapping>
其他語(yǔ)法詳見Aegis 參考。
2.4 配置Spring導(dǎo)出
為了節(jié)約配置代碼,先配置一個(gè)基類。注意導(dǎo)出Web服務(wù)的Bean不能lazy-init:
<!-- 導(dǎo)入XFire基本配置文件 --> <import resource="classpath:org/codehaus/xfire/spring/xfire.xml"/> <bean id="baseWebService" class="org.codehaus.xfire.spring.remoting.XFireExporter" lazy-init="false" abstract="true"> <property name="serviceFactory" ref="xfire.serviceFactory"/> <property name="xfire" ref="xfire"/> </bean>
每個(gè)Web服務(wù)的定義:parent為前面定義的基類,serviceClass 為Web Service的接口,serviceBean為Web Service的接口實(shí)現(xiàn)類。
<bean id="bookService" parent="baseWebService"> <property name="serviceBean" ref="bookManager"/> <property name="serviceClass" value="org.springside.bookstore.components.xfire.server.simple.BookService"/> </bean>
Web服務(wù)導(dǎo)出完畢,用戶可在http://localhost/service/BookService?WSDL查看自動(dòng)生成的WSDL。