Apache CXF 架構指南

jopen 11年前發布 | 73K 次閱讀 Apache CXF WEB服務/RPC/SOA
 本文旨在介紹CXF架構,以便對CXF有一個快速的理解。 
    
一、架構目標和約束 

    Apache CXF 服務框架旨在構建服務所必須的基礎組件。目標有許多,其中包括 
下幾方面: 
    1. 可嵌入式 
    2. 高性能 
    3. 易配置 
    4. 直觀易用 
    5. 前后端(front-end)與核心代碼完全分離 
    6. 數據格式化支持 
    7. 數據綁定支持 
    8. 協議綁定支持 
    9. 多種層傳輸支持 
   10. 多種編程語言支持 
   11. WS-*和相關特性支持 
   12. 代碼生成工具盒WSDL驗證工具 
   13. 靈活部署 

二、 CXF-API 

    整個CXF架構主要由以下幾個部分組成: 
    1. BUS:包含 擴展(extensions)、攔截器和屬性配置的注冊入口 
    2. Front-end: Front-end 提供編程模型來創建服務 
    3. Messaging & Interceptors : 提供底層級別的消息和管道處理,大部分功能都建立在這個基礎之上。 
    4. Pluggable Data Bindings: 插件式的數據綁定 
    5. Protocol Bindings: 解析協議的功能。 
    6. Transports: TransportFactory 創建Destinations(接受數據)和Conduits(發送數據)。 

    請看下圖各層順序,可見他們是如何在一起工作的。 
Apache CXF 架構指南  

三、 BUS 

    Bus,作為CXF的核心,是運行時各種共享資源的提供者。共享資源包括像WSDL管理器,綁定工廠管理器等。Bus可以非常容易的擴展,以此來加入你自 己的資源和服務,甚至用你自己的組件(tomcat)替換像HTTP destination factory(建立在Jetty基礎之上)的默認的資源。 

    這種可擴展性使得依賴注入變得可能。默認的Bus實現建立在spring framework之上,在運行時,組裝這些組件在一起供你使用。 

    SpringBusFactory 在classpath/META-INF/cxf目錄下搜索所有的bean配置文件, 并以此建立application context。以下文件默認會被掃描: 
    META-INF/cxf/cxf.xml (e.g., in cxf-rt-core only) 
    META-INF/cxf/cxf-extension.xml (e.g. in cxf-rt-bindings-soap) 
    META-INF/cxf/cxf-property-editors.xml (e.g. in cxf-rt-transports-http) 
更詳細的配置,可以參考 http://cxf.apache.org/docs/configuration-of-the-bus.html 

四、服務調用時如何處理的? 

    參考以下客戶端處理方式以及服務端處理方式: 

    客戶端: 
     Apache CXF 架構指南  

    服務端: 
     Apache CXF 架構指南  

五、 Front-end 

    Front-end 提供編程的方式來與CXF進行交互。提供的基礎功能有:JAX-WS, JAX-RS, Simple和Javascript。各種基礎功能相互獨立,和綁定,核心功能類似。Front-end通過將攔截器加入到服務和端點來提供功能。 

六、 Messaging & Interceptors 

    CXF建立在通用消息層之上,由Messages,Interceptors(攔截器),和InterceptorChains(攔截器鏈)組成。 Interceptors是功能單元的基礎。通過分離消息處理和消息發送,使得CXF具備非常靈活的架構。可以對任何處理點進行配置。這也使得CXF局部 暫停&恢復攔截器鏈。 

    Interceptors定義了handleMessage方法,可以用來處理Message.這邪惡Interceptors可以組成一個鏈狀的攔截器,即攔截器鏈。下面的例子說明了這個結構: 
    
    a. Header Interceptor只處理SOAP消息的header。 
    b. WS-Security Interceptor 用來解密和認證接受到的消息。 
    c. 發送數據的Interceptor用來序列化處理結果。 

注意:Interceptors 是沒有方向性的,本質上,他們都可以處理request,response,和fault。(關鍵是看你把這個攔截器放在哪里) 

七、 Phase Interceptors 

    CXF提供了一個InterceptorChain的實現:PhaseInterceptorChain。當Interceptors加入到這個鏈時,他 們將按處理階段進行排序分組。因此PhaseInterceptor需要告知鏈,它處于哪個階段(即需要調用 super(Phase.PRE_PROTOCOL))。 
    
    我們假設一個簡單的例子(注意,這些攔截器鏈在CXF中不是必須的,只是提供攔截點)。我們正在處理一個SOAP消息。有兩個地方需要處理。第一、分發攔 截器組(Dispatch Interceptor) 負責解析SOAP的頭部信息并決定將消息路由到哪個服務上。第二、反序列化攔截器組負責將SOAP body 綁定到 JAXB 對象上。分發攔截器組需要通過兩個攔截器來實現,第一個ReadHeadersInterceptor,用來解析header信息,第二個攔截器WS- AddressingInInterceptor負責根據頭部信息判斷調用哪個服務。反序列化攔截器組只需要一個 JAXBUnmarshallerIntercptor。  ReadHeadersInterceptor 和 AddressingInInterceptor 的getPhase()返回"dispath"告訴 PhaseInterceptorChain 他們在Dispath 階段.另外,ReadHeadersInterceptor 提供getBefore()方法,用來指定它必須在AddressingInInterceptor之前執行。 

    攔截鏈靈活可變。在以上例子上,我們可以把攔截器加到服務處理完成后,或者可以暫停攔截器鏈以便等待外部處理,像異步返回response。 

八、 Fault Handling 

    在處理的任何階段,攔截器都可能拋出Fault或者它的子類。這會導致停止正常處理,并調用善后機制:按順序調用 handleFault 。 

    攔截器鏈具備失敗觀察者的功能。一旦失敗,fault Interceptor被調用。fault observer將會觸發一個新的鏈來處理錯誤。 

九、 Exchanges 
  
    除了消息的概念外,還有個Exchage的概念。Exchange類保持當前入的消息,出的消息和錯誤消息的引用。還保持著Exchange自身的配置屬性。Exchange的實例保持著當前調用的服務。 

十、 Reentrant InterceptorChains(可重入的攔截器鏈) 

    PhaseInterceptorChain的一個非常有趣的特征是它自己是可重入的。這是一個強大的功能也有一點點危險。這個特征僅僅在CXF發送消息時使用。SoapOutInterceptor是最好的例子 


public void handleMessage(Message m) { 
  writeSoapEnvelopeStart(); 
  writeSoapBodyStart(); 

  // invoke next interceptor, which writes the contents of the SOAP Body 
  m.getInterceptorChain().doIntercept(m); 
  writeSoapBodyEnd(); 

  writeSoapEnvelopeEnd(); 


十一、The Service Model(服務模型) 

    服務模型是CXF對服務的描述。由兩部分組成。第一,有一個ServiceInfo類,包含一個類似WSDL描述服務和他的 operations,bindings,endpoints和schema。第二,有一個Service類,其中包含 ServiceInfo,data-binding(稍后介紹Data-binding) 信息,服務攔截器,服務屬性等。 

    一個服務可以根據許多不同的資源來構建,包括classes和WSDL(1.1和2.0). 一般front-ends都通過Service Factory來創建服務。front-end通過Factory組件(ServerFactoryBean, ClientProxyFactoryBean)來創建,發布和消費服務。factory組件構建Service model,配置Interceptor,data bindings等。 

    Service model自身包被包含在ServiceInfo中。如下圖所示: 

     Apache CXF 架構指南  

十二、 Data Bindings 

    Data Bindings 實現 XML elements和 Java 對象之間的映射關系。Data Bindings 在data和xml之間互相轉換,產生XML schema,提供wsdl2java代碼生成支持。并非所有的Data binding都支持這些功能。但最少,每個Data binding必須提供數據轉換(對象和xml之間的轉換啦)。更詳細的說明,可以參考 http://cxf.apache.org/docs/data-binding-architecture.html。當前CXF支持的Data binding包括JAXB 2.x (default), Aegis, Apache XMLBeans, Service Data Objects (SDO) and JiBX (under development). 

十三、Protocol Bindings 

    Protocal Bindings提供方法在傳輸層上映射具體的格式和協議。一個Protocal Bindings 包括兩個主要部分:BindingFactory 和 Binding。BindingFactory負責從ServiceInfo創建Binding。Protocal Binding包含一個特殊的Inteceptor并實現了createMessage() 方法。這個方法負責創建符合Binding要求的消息。 

    目前,CXF支持的Protocal 包括:SOAP 1.1, SOAP 1.2, REST/HTTP, pure XML 和 CORBA. 

    a. The Soap Binding 
    CXF原生支持的是soap。它擁有自己的一個消息類SoapMessage。它增加了表示當前soapVesion以及header的字段。 

    Soap Binding還增加了一個特別的Interceptor,即SoapInterceptor。這個攔截器增加了兩個方法: 
    Set getRoles(); 
    Set getUnderstoodHeaders(); 

    這就使得特定的SoapInterceptor能夠理解特定的角色和header。 

    CXF也設計了其他的攔截器來處理Soap消息。 
    StaxInInterceptor: 根據傳入的InputStream創建XMLStreamReader 
    ReadHeadersInterceptor: 從SoapMessage中讀取消息頭header 
    MustUnderstandInterceptor: 檢查所有的MustUnderstand attributes是否符合所有SoapInterceptor的getUnderstoodHeaders()返回值。 
    SoapOutInterceptor:在發送soap消息前,處理消息。 

    b.其他Bingding。 
    其他bindings 包括 REST/HTTP binding, pure XML binding, 和 CORBA binding. 
十四、Transports 

    CXF提供了一個自己的傳輸抽象層,對protocal binding和front-end隱藏具體的傳輸細節。當前支持的 transports 包括:HTTP, HTTPs, HTTP-Jetty, HTTP-OSGI,Servlet, local, JMS和 In-VM。 通過Camel transport,還可以支持SMTP/POP3, TCP和Jabber。 

十五、Conduits(翻譯是管道) 
   
    Conduit提供了發送消息的基礎。一個Conduit是用ConduitInitiator創建的。發送一個消息有多個步驟: 
    1. 調用conduit.prepare(message):調用后就開始發送消息了,這個時候,Conduit會初始化一個連接,并為將發送的消息設置一個OutputStream(流)。 
    2. 將消息寫入這個流。 
    3. 調用conduit.close(message): 關閉和釋放所有相關的資源。 

    消息發送器還可以注冊一個觀察者 MessageObserver。如果這個Conduit是同步的,當消息被(客戶端)接受到時,MessageObserver將可以得到通知。 

十六、Destinations 

    Destinations是接受進來的消息的基礎。DestinationFactory可以創建Destinations。例如: 

    DestinationFactoryManager dfManager =     bus.getExtension(DestinationFactoryManager.class); 

    // Find a DestinationFactory for the SOAP HTTP transport 
    DestinationFactory df =  dfManager.getDestinationFactory("http://schemas.xmlsoap.org/wsdl/soap/http"); 

    // TODO: outline building of EndpointInfo 
    EndpointInfo endpointInfo = ...; 
    Destination destination = df.getDestination(endpointInfo); 

    MessageObserver通過以下方式進行注冊: 

    MessageObserver myObserver = ...; 
    destination.setMessageObserver(myObserver); 



十七、 A JAX-WS example 

    舉例說明創建和消費一個服務,各個組件如何協同工作: 

    1. 調用Endpoint.publish("http://localhost/service", myService); 
    2. EndpointImpl 使用JaxWsServiceFactoryBean根據class 或者 WSDL創建myService的web服務。 
    3. 根據"http://localhost/service" 創建了EndpointInfo 
    4. 根據EndpointInfo創建JaxWsEndpointImpl,這個類包含JAX-WS 的具體攔截器。 
    5. JaxWsEndpointImpl創建Binding 和 Destination。并監聽相應的端口。 

十八、Dependencies 
    依賴關系請參考: 
    http://cxf.apache.org/docs/cxf-dependency-graphs.html
 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!