太陽雨

          痛并快樂著

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            67 Posts :: 3 Stories :: 33 Comments :: 0 Trackbacks

          XFire生火指南(下)

          請先閱讀:XFire生火指南(上)

          1. JSR181

               JSR181式通過annotated POJO ,零配置文件的導出Web服務,是BEA倡導的,JavaEE5里的正規方式, XFire作了良好的支持。

               但是,XFire關于JSR181方式的文檔還不夠清晰,請完整閱讀本節以避免其中的陷阱。

          1.1 參考文章

          1.2 ApplicationContext.xml

              因為Web服務配置都寫在了annotation,applicationContext.xml文件的內容變得比較固定。需要注意JSR181WebAnnotations與HandlerMapping不能lazy init。

          <beans default-autowire="byName">
            <!--引入XFire的預配置文件-->
           <import resource="classpath:org/codehaus/xfire/spring/xfire.xml"/> 
          <!-- 獲得applicationContext中所有bean的JSR181 annotation -->
           <bean id="webAnnotations" class="org.codehaus.xfire.annotations.jsr181.Jsr181WebAnnotations"  lazy-init="false"/>
           <!-- 定義handler mapping,將所有JSR181定義的bean導出為web service -->
          <bean id="jsr181HandlerMapping" class="org.codehaus.xfire.spring.remoting.Jsr181HandlerMapping"  lazy-init="false">
            <property name="xfire" ref="xfire"/>
            <property name="webAnnotations" ref="webAnnotations"/>
           </bean>
          </beans>

          1.3 Interface+Impl模式

             不同于XFire傳統模式,窄接口不是必須的,只是考慮到有個接口,配置都在接口上做,對原來的Manager類侵入較少。

             如果采用Interface,Interface將擔任主要的配置工作。

             首先定義@WebService,可定義自己的NameSpace,如果不定義將采用默認的生成算法。

             接口中的函數將默認全部導出,不需要再用@WebMethod注釋,也可以如下例般進行關于Param,Result的更進一步配置:

          @WebService(targetNamespace = "http://www.springside.org.cn")
          public interface BookService {
          @WebResult(name = "SearchResult")
          List<Book> findBooksByCategory(@WebParam(name = "category", header = true)String cateoryId);
          }

                 Manager不是純粹的POJO,需要帶上@WebService注釋,指明接口。

          @WebService(serviceName = "BookService", endpointInterface = "org.springside.bookstore.components.xfire.server.jsr181.BookService")
          public class BookManager implements BookService {
          ...
          }

                陷阱一:XFire JSR181參考文檔 中在Interface中以@WebService(name="BookService")來定義ServiceName,這個做法看起來也比較合理,但實際上需要在Manager中以@WebService(serviceName ="BookService") 來定義,比較古怪。

          1.4 純POJO模式

              參考文檔中的例子,需要配置@WebMethod 指定需要導出的函數。

          @WebService(name = "EchoService", targetNamespace = "http://www.openuri.org/2004/04/HelloWorld")
                  public class Jsr181EchoService
          {
              @WebMethod(operationName = "echoString", action = "urn:EchoString")
              @WebResult(name = "echoResult")
              public String echo(@WebParam(name = "echoParam", header = true) String input)
              {
                  return input;
              }
          }

          1.5 Client注意事項

              陷阱二:和傳統模式的client有一點最大的區別,serviceModel需要實際的Manager類而不是接口類來做參數:

          Service serviceModel = new AnnotationServiceFactory().create(BookManager.class);

          2. Client

          XFire的Client并不算強項,一共有三種模式:

          2.1 Client開發者擁有Web服務端的class

            Client與Server是同一個開發團隊也好,Server端團隊以jar形式提供開發包也好,反正如果能拿到服務端的接口Class和Entity類及aegis 配置文件的話。

            傳統POJO模式:

          Service serviceModel = new ObjectServiceFactory().create(BookService.class);
          BookService service = (BookService) new XFireProxyFactory().create(serviceModel, serviceURL);
          service.findBooksByCategory(cateoryId);

            JSR181模式,注意這里Server端開發組需要向Client提供BookService的實現類BookManager,而不止于接口,有點危險: 

          Service serviceModel = new AnnotationServiceFactory().create(BookManager.class);
          BookService = (BookService) new XFireProxyFactory().create(serviceModel, serviceURL);
          service.findBooksByCategory(cateoryId);

            SpringSide 用泛型封裝了一個XFireClientFactory,調用代碼如下:

          BookService service = XFireClientFactory.getClient(serviceURL, BookService.class);
          BookService service = XFireClientFactory.getJSR181Client(serviceURL, BookService.class, BookManager.class);
           

          2.2 動態模式

              動態模式不需要服務端的class,不過性能和復雜對象映射等估計做得不會太好。

          Client client = new Client(new URL("http://www.webservicex.net/CurrencyConvertor.asmx?WSDL"));
          
          Object[] results = client.invoke("ConversionRate", new Object[] {"BRL", "UGX"});

          2.3 根據WSDL生成Client Stub

              這才是Web Service Client的王道,可以訪問任意語言編寫的Web Service,將在下一個版本中演示。

              可以用XFire的Ant Task來生成,但使用MyEclipse的XFire集成會更加方便。生成的代碼必須是JDK5.0的版本。

          3. 測試

          XFiire很重要的一個特性是提供了無須啟動Web容器也能進行單元測試的能力。

          原理就是利用XFire的JVM模式,以xfire.local://BookService channel而不是http://localhost/service/BookService來訪問服務。

          測試的方式分兩種:

          一種是純服務器角度,不編寫客戶端代碼,以SOAP XML形式發送請求,返回的也是SOAP XML字串,直接對XML進行測試。

          一種是編寫2.1 中Client代碼來進行測試。

          前一種的測試的隔離度較高,而后一種比較簡便。

          3.1 測試基類 

          無論那種方式,都使用Xfire的AbstractXFireSpringTest基類,實現createContext()回調函數。

          protected ApplicationContext createContext() {      return ClassPathXmlApplicationContext(new String[]{"classpath*:applicationContext*.xml"});
          }

          另外測試基類還要完成一個很重要的工作就是要解決Hibernate的LazyLoad問題,做到OpenSession In Test。因此,SpringSide專門封裝了一個XFireTestCase的基類。

          3.2 用Client代碼直接測試

               下文直接用client代碼調用findBooksByCategory方法,得到返回值后進行各種Assert判斷。

               注意和普通client code的兩處區別:servericeURL換成local,factory須加入getXFire()作參數。

          Service serviceModel = new ObjectServiceFactory().create(BookService.class);
            XFireProxyFactory factory = new XFireProxyFactory(getXFire());
            BookService service = (BookService) factory.create(serviceModel, "xfire.local://BookService");
            List list = service.findBooksByCategory("0");
            assertNotNull(list);
          ...

          3.3 純服務端測試

             編寫一段SOAP XML,以任意命名保存,下文以"Java"作參數,調用findBooksByName方法。

          <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
              <env:Header/>
              <env:Body>
                  <findBooksByName xmlns="http://www.springside.org.cn">
                      <in1>Java</in1>
                  </findBooksByName>
              </env:Body>
          </env:Envelope>

             測試代碼調用前面的XML,返回XML Document對象,再用基類提供的一些Assert方法檢查結果

            Document doc = invokeService("BookService","/org/springside/xfire/BookService.FindBooksByName.xml");
            assertNoFault(doc);
            addNamespace("ss", "http://domain.commons.bookstore.springside.org");
            assertValid("//ss:Book/ss:category/ss:descn= \"Java Book\"", doc);
          posted on 2010-03-05 11:44 小蟲旺福 閱讀(445) 評論(0)  編輯  收藏 所屬分類: javaEE
          主站蜘蛛池模板: 周宁县| 元氏县| 科技| 亚东县| 鹤山市| 富锦市| 阿图什市| 韶山市| 吴堡县| 长丰县| 乳山市| 河南省| 蒙山县| 封开县| 赤壁市| 习水县| 道孚县| 阿坝县| 兖州市| 印江| 皋兰县| 平果县| 安丘市| 临江市| 贡山| 新兴县| 庐江县| 冕宁县| 微山县| 乐东| 修水县| 麻阳| 禹城市| 香格里拉县| 涟源市| 盐津县| 奇台县| 湘西| 抚顺县| 昌图县| 东乌珠穆沁旗|