<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Flier's Sky

    天空,藍色的天空,眼睛看不到的東西,眼睛看得到的東西
    posts - 1, comments - 0, trackbacks - 0, articles - 0

    使用 xfire 快速發布 WebService

    Posted on 2006-03-10 22:56 Flier Lu 閱讀(4352) 評論(0)  編輯  收藏

    寫個短篇開個張,呵呵 :P

    原文:http://www.blogcn.com/User8/flier_lu/blog/29729701.html

          在經歷過早年 Delphi, C++, Java 等不成熟環境中開發 WebService 的折磨之后,接觸 ASP.NET 的最大感觸,就是 WebService 的開發門檻被大大降低了。無需對 SOAP 或基本架構有任何了解,僅需簡單的定義幾個 Attribute 即可,所有的 dirty work 都由 ASP.NET 在后臺自動完成。例如:
    1[ WebService(Description="Common Server Variables",Namespace="http://flier.yeah.net/")]
    2public class ServerVariables: WebService {
    3
    4
    5  [ WebMethod(Description="Obtains the Server Computer Name",EnableSession=false)]
    6  public string GetMachineName() {
    7     return Server.MachineName;
    8  }
       
    9}

          而這一巨大的生產力進步,現在開始在 Java 領域也可直接享用。例如:
     1/**
     2 * Common Server Variables
     3 * 
     4 * @@WebService(name = "ServerVariables", serviceName = "ServerVariables", targetNamespace = "http://flier.yeah.net/")
     5 * @@SOAPBinding(style = SOAPBindingAnnotation.STYLE_RPC)
     6 */

     7public interface ServerVariables
     8{
     9  /**
    10   * @@WebMethod(operationName = "GetMachineName", action="urn:GetMachineName")
    11   * @@.return WebResult("machineName")
    12   */

    13  string GetMachineName();
    14}

          在項目搭建時完成一次性的配置之后,我們絕大多數的工作就是定義 WebService 接口,設定 WebService 的發布方式。然后就是實現此接口并放入 spring 中進行管理,例如:
    1<bean id="serverVariables" class="net.yeah.flier.ws.impl.ServerVariablesImpl" singleton="true">

          這一神奇效果的幕后英雄就是 codehaus 最新發布的 xfire 1.0 SOAP 框架。
          與 Axis 等現有實現相比,xfire 的最大優點就是改用 StAX 基于流的 XML 分析引擎,加上其 SOAP 協議棧實現上的精巧設計,能夠帶來比 Axis 快 2-5 倍的性能提升。具體的性能評測數據,可以參考  一些第三方評測結果 
          而在功能上 xfire 也毫不遜色,其 Features & Goals 里面充滿了各種 big words。

    * Support for important Web Service standards - SOAP, WSDL, WS-I Basic Profile, WS-Addressing, WS-Security, etc.
    * High performance SOAP Stack
    * Pluggable bindings POJOs, XMLBeans, JAXB 1.1, JAXB 2.0, and Castor support
    * JSR 181 API to configure services via Java 5 and 1.4 (Commons attributes JSR 181 syntax)
    * Support for many different transports - HTTP, JMS, XMPP, In-JVM, etc.
    * Embeddable and Intuitive API
    * Spring, Pico, Plexus, and Loom support.
    * JBI Support
    * Client and server stub generation
    * JAX-WS early access support

          與 Axis, Glue 以及 ActiveSOAP  的詳細功能對比,可以參考 Stack Comparison 文檔。

          下面先就 xfire 基礎架構以及與 spring 集成的基本情況大概做一個簡單介紹,回頭有時間再整一個 xfire 與 axis 實現架構的橫向對比。
          與 axis 很相似 xfire 在架構上也可以大概分為 Service, Transport 和 Invoker 三個層面。
          Service 層是 xfire 架構的靜態基礎,負責完成對服務的注冊及其管理。核心的 ServiceRegistry 接口完成對服務自身的生命期管理,如注冊/注銷/獲取等等;而 ServiceFactory 接口則負責從具體的 POJO 類型,生成實現  Service 接口的可被管理的服務代理。
          Transport 層則是 xfire 的外部 IO 處理系統。由 TransportManager 接口對具體的 Transport 接口實現進行管理,默認提供了基于 pipe 的 LocalTransport 和基于 Http 協議的 SoapHttpTransport。理論上可以任意進行擴展,例如 xfire 發布包中還提供了基于 JMS 和 XMPP 的實現。
          Invoker 則是 xfire 的動態調用層,負責在 Transport 層接受到請求后,解析內容、調用合適服務并最終返回 SOAP 封包給調用者。運行時 Invoker 負責維系 Service 和 Transport 之間的聯系。
          因此一個服務的生成和注冊往往類似如下代碼:
    1Service endpoint = serviceFactory.create(clazz); // 根據具體類型創建服務
    2xFire.getServiceRegistry().register(endpoint);     // 向服務管理注冊服務
    3endpoint.setInvoker(new BeanInvoker(bean));             // 設定服務調用模式


          最基本的 XFire 接口,實際上就是 getServiceRegistry() 和 getTransportManager() 的封裝。

          xfire 中另一塊核心的思想,就是其靈活而強大的 binding 機制,負責完成 Java 類型與 SOAP 消息的雙向轉換。xfire 僅僅內建就支持 POJO(Aegis), Castor, JAXB 1.1, JAXB 2.0 和 XMLBeans 多種模式,你可以根據需求選擇從全自動 POJO 生成,到全手工 xsd 文件定義的不同方式。

          而對使用 spring 環境的開發者來說,要提供上述這一系列支持,只需要直接將 xfire-spring 工程中的 fire.xml 文件包括到 applicationContext.xml 中,即可直接獲得完整的 xfire 架構。
    1<import resource="classpath:/org/codehaus/xfire/spring/xfire.xml"/>


          不過相比于通過 xml 文件定義服務來說,我更傾向于直接用 Annotation 方式在代碼級完成定義。xfire-annotation 提供了對 Java 5 Annotation 和 apache common-attribute 的完整支持。例如上述例子中在 javadoc 里定義的 @@ 標簽,就是 用于使用 xdoclet 生成 common-attribute 支持的。
          因為 common-attribute 并非編譯器一級提供支持,因此要在編譯之前增加一道處理過程。個人推薦直接使用 maven 進行管理,當然也可以在 ant 中直接配置 task。maven 1.x 的具體配置方式如下:

    # project.properties for maven 1.x
    #
    org.apache.commons.attributes.enable=true
    org.apache.commons.attributes.index.enable=true
    org.apache.commons.attributes.attributepackages=org.codehaus.xfire.annotations.commons;org.codehaus.xfire.annotations.commons.soap;org.codehaus.xfire.annotations.soap
          其中 org.apache.commons.attributes.enable 負責啟用 maven 的 common-attribute 支持;org.apache.commons.attributes.index.enable 啟用索引模式,生成時會自動產生一個索引文件 META-INF/attrs.index;org.apache.commons.attributes.attributepackages 則是預定義可能用到的 annotations 的包名稱,以便直接用 WebService 這樣的簡短名字。
          增加了以上配置后,在 maven 編譯時,會自動增加一個 common-attribute 支持文件的編譯過程,并在 target/commons-attributes 下生成類似 ServerVariables$__attributeRepository.java 的文件,以存儲 @@ 標簽中指定的 Metadata。在 eclipse 等 IDE 中,我們可以直接把這些目錄添加為源碼目錄。

          而在為了使用 common-attribute 定義的元信息,xfire 提供了 Jsr181HandlerMapping 來自動完成服務映射支持。
     1<bean id="webAnnotations" class="org.codehaus.xfire.annotations.commons.CommonsWebAttributes"/>
     2<bean id="handlerMapping" class="org.codehaus.xfire.spring.remoting.Jsr181HandlerMapping">
     3    <property name="typeMappingRegistry">
     4        <ref bean="xfire.typeMappingRegistry"/>
     5    </property>
     6    <property name="xfire">
     7        <ref bean="xfire"/>
     8    </property>
     9    <property name="webAnnotations">
    10        <ref bean="webAnnotations"/>
    11    </property>
    12</bean>

          因為 xfire 同時需要支持 Java 5 模式和 common-attribute 模式的元信息,所以對元信息的獲取被封裝到 annotations.commons.CommonsWebAttributes 和 annotations.jsr181.Jsr181WebAnnotations 中,以便根據實際使用進行配置。而 xfire 和 xfire.typeMappingRegistry 則是引用前面提到的 xfire.xml 中定義的基礎接口和類型映射支持。

          Jsr181HandlerMapping 是從 spring 提供的 ApplicationObjectSupport 上基礎出來的,它實現了 ApplicationContextAware 接口,因此會在 bean 定義被加載完成后,調用其 setApplicationContext 方法,并進而調用其 initApplicationContext 方法完成初始化。
          Jsr181HandlerMapping.initApplicationContext 方法中,會遍歷當前 ApplicationContext 的所有父容器,調用 processBeans 方法處理器其 bean 定義。而在 processBeans 中針對每個 bean,檢查其是否為 singleton 的非抽象對象,且定義了 WebService Annotation;如果是則構造 bean 并以前面提到的方式進行注冊。
    值得注意的是,xfire 1.0 乃至最新 CVS 版本,在這塊的實現都有一個嚴重 bug,沒有對 abstract bean 進行處理。其代碼中直接用 beanFactory.getBean(beanNames[i]) 試圖獲取實例,如果 bean 是 singleton 的 abstract 模式,則會導致 spring 拋出異常。可以將其檢測代碼改成如下方式:
     1public class Jsr181HandlerMapping extends AbstractUrlHandlerMapping
     2{
     3    private void processBeans(ApplicationContext beanFactory, AnnotationServiceFactory serviceFactory)
     4    {
     5        String[] beanNames = beanFactory.getBeanDefinitionNames();
     6        
     7        ConfigurableApplicationContext ctxt = (ConfigurableApplicationContext) beanFactory;
     8
     9        // Take any bean name or alias that has a web service annotation
    10        for (int i = 0; i < beanNames.length; i++)
    11        {
    12            BeanDefinition def = ctxt.getBeanFactory().getBeanDefinition(beanNames[i]);
    13            
    14            if (!def.isSingleton() || def.isAbstract()) continue;
    15            
    16            //
    17        }

    18    }
        
    19}
        

          此 bug 及修復代碼已提交到 xfire 的 JIRA 上,待進一步確認。

          而在具體對 bean 是否定義服務的判斷上,xfire 1.0 中的支持實際上也是很不完整的。象最上面例子中,由 ServerVariables 定義服務接口,ServerVariablesImpl 中實現服務的方式,直接在 xfire 下是無法使用的。關鍵原因在于 xfire-annotations 工程在定義 WebService 等 annotation 時,沒有指定其可繼承性。
          改進方法也很簡單,在 org.codehaus.xfire.annotations.commons 包的 WebService, WebMethod, WebResult, WebParam 等 annotation 定義中,類一級增加一個 @@org.apache.commons.attributes.Inheritable() 標簽即可。common-attribute 在判斷是否存在某個 annotation 時,會自動將具有 Inheritable 屬性的自定義屬性,繼承到其所有子類。這樣一來就可以很完美的解決通過接口定義服務的問題。此改進也已提交到 xfire 的 JIRA 上,待進一步確認。

          完成了這些基礎性工作后,剩下的任務就非常簡單了。根據 xfire 的 Servlet Setup 文檔,在 web.xml 中增加相關 servlet 的定義,接管 /service/** 或其它 URL。
     1  <servlet>
     2    <servlet-name>XFire</servlet-name>
     3    <display-name>XFire Servlet</display-name>
     4    <servlet-class>
     5        org.codehaus.xfire.transport.http.XFireConfigurableServlet
     6    </servlet-class>
     7    <init-param>
     8      <param-name>config</param-name>
     9      <param-value>services.xml</param-value>
    10    </init-param>
    11  </servlet>
    12
    13  <servlet-mapping>
    14    <servlet-name>XFire</servlet-name>
    15    <url-pattern>/servlet/XFireServlet/*</url-pattern>
    16  </servlet-mapping>
    17
    18  <servlet-mapping>
    19    <servlet-name>XFire</servlet-name>
    20    <url-pattern>/services/*</url-pattern>
    21  </servlet-mapping>

          然后就可以通過 ::URL::http://localhost:8080/xfire/services/WeatherService?wsdl  類似的方式訪問 wsdl 或調用 WebService 了。詳細的配置請參考 xfire 相關文檔。
          完整的 xfire 支持 bean 配置大致如下:
     1<?xml version="1.0" encoding="UTF-8"?>
     2<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
     3<!-- applicationContext-xfire.xml -->
     4<beans>
     5    <import resource="classpath:/org/codehaus/xfire/spring/xfire.xml"/>
     6    
     7    <bean id="webAnnotations" class="org.codehaus.xfire.annotations.commons.CommonsWebAttributes"/>
     8    <bean id="handlerMapping" class="org.codehaus.xfire.spring.remoting.Jsr181HandlerMapping">
     9        <property name="typeMappingRegistry">
    10            <ref bean="xfire.typeMappingRegistry"/>
    11        </property>
    12        <property name="xfire">
    13            <ref bean="xfire"/>
    14        </property>
    15        <property name="webAnnotations">
    16            <ref bean="webAnnotations"/>
    17        </property>
    18    </bean>
    19    
    20    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    21        <property name="urlMap">
    22            <map>
    23                <entry key="/">
    24                    <ref bean="handlerMapping"/>
    25                </entry>
    26            </map>
    27        </property>
    28    </bean>
    29</beans>

          如果需要使用 abstract bean 的話,可以按前面所說修改 Jsr181HandlerMapping,并重新編譯 xfire-spring 工程;如果需要提供接口定義服務的支持,可以按前面所說修改 WebService 等,并重現編譯 xfire-annotation 工程。
     
    end.


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 未满十八私人高清免费影院| 亚洲av专区无码观看精品天堂| 亚洲精品无码久久久久久| 免费A级毛片无码A∨免费| 久久91亚洲人成电影网站| 成人A毛片免费观看网站| 亚洲欧洲自拍拍偷午夜色无码| 99re6在线视频精品免费| 亚洲av永久无码精品古装片| 精品在线免费观看| 亚洲色图.com| 美女视频黄免费亚洲| 亚洲精品无码久久久久久| 亚洲国产精品无码久久九九| 一区二区三区在线免费| 欧洲亚洲国产清在高| 91青青国产在线观看免费| 国产成人精品日本亚洲网址| 性做久久久久免费观看| 一级大黄美女免费播放| 亚洲gv猛男gv无码男同短文| 成人福利免费视频| 亚洲熟妇av午夜无码不卡| 一区国严二区亚洲三区| 国产午夜无码精品免费看动漫| 亚洲天堂一区二区| 夭天干天天做天天免费看| 中文字幕无码免费久久9一区9 | 4虎永免费最新永久免费地址| 四虎亚洲精品高清在线观看| 免费**毛片在线播放直播| 丝袜足液精子免费视频| 亚洲福利视频网站| 免费观看午夜在线欧差毛片| 久章草在线精品视频免费观看| 亚洲 欧洲 视频 伦小说| 亚洲人成无码久久电影网站| 国产成人精品免费午夜app| 污污免费在线观看| 亚洲国产一区国产亚洲| 亚洲Av无码乱码在线观看性色 |