Apache CXF 架構指南
本文旨在介紹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(發送數據)。
請看下圖各層順序,可見他們是如何在一起工作的。
三、 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
四、服務調用時如何處理的?
參考以下客戶端處理方式以及服務端處理方式:
客戶端:
服務端:
五、 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中。如下圖所示:
十二、 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
一、架構目標和約束
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(發送數據)。
請看下圖各層順序,可見他們是如何在一起工作的。

三、 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
四、服務調用時如何處理的?
參考以下客戶端處理方式以及服務端處理方式:
客戶端:

服務端:

五、 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中。如下圖所示:

十二、 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
Set
這就使得特定的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 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!