Apache CXF Web 服務堆棧是來自 Apache Software Foundation 的另一替代選擇,Axis2 堆棧也來自同一組織。盡管它們來自同一組織,Axis 2 和 CXF 就如何配置和交付 Web 服務 采用完全不同的方法。在本文中,您將學習為 CXF Web 服務使用 JAXB 2.x 和 JAX-WS 2.x 的基礎,還將比較 CXF 與其他 JAXB/JAX-WS 堆棧 — Axis2 和 Metro — 這兩 個堆棧在之前的文章中討論過。
CXF 基礎比較
在用戶界面方面,CXF 與 Axis2 和 Metro Web 服務堆棧有很多共 同之處。三個堆棧都允許要麼從已有 Java™ 代碼開始構建 Web 服務,要麼從 WSDL Web 服務描述開始,生成使用或實現服務的 Java 代碼。而且與其他堆棧一樣,CXF 將服務 操作建模為方法調用,而將服務端口類型建模為接口。
與 Axis2 類似,但是不同於 Metro,CXF 允許選擇不同的數據綁定技術。CXF 對 JAXB 2.x 的支持與 Metro 同等而高於 Axis2,因為它允許從 WSDL 生成代碼時使用 JAXB 標准(而 Axis2 不允許)。CXF 還允許 使用其他數據綁定方法,不過對這些方法的支持不像在 Axis2 中那樣成熟 — 特別是 ,只有在使用 JAXB 或 XMLBeans 數據綁定時才能使用 CXF 從 WSDL 生成代碼。
CXF 使用的首選服務配置技術(或在 CXF 術語中稱為前端) 是 JAX-WS 2.x 注釋,通常附有 XML 配置文件。CXF 中對 JAX-WS 注釋的支持與 Metro 同等,因而與 Axis2(在 Axis2 中 使用 JAX-WS 時存在一些限制,正如 “Axis2 中的 JAXB 和 JAX-WS” 所述)相 比,CXF 更適合使用 JAX-WS。與其他 JAX-WS 實現一樣,CXF 需要服務 WSDL 在運行時可用 於客戶機。
同其他堆棧一樣,CXF 使用由可配置組件組成的請求和響應處理流。CXF 調用組件 intercepters,而非 handlers,不過除此以外的其他組件是等效組件。與 Metro 相同的是 ,CXF 完全支持 WS-Security 和其他擴展技術,將其作為基礎下載的一部分。與 Metro 不 同的是,CXF JARs 是模塊化的 — 即您可以根據正在使用的技術選擇 JARs 使其成為應用程 序的一部分(CXF 安裝目錄中的 /lib/WHICH_JARS 文件會告訴您各種常見用例所需的特定 JARs)。該模塊化的負面效應是最終會產生應用程序所需的一長列特定 JARs;從有利的一面 來說,它允許控制部署的大小。
另一個與 Metro 的相同之處是,CXF 通常需要為 Web 服務構建一個 WAR 文件,而非潛 在地部署多個服務到單個服務安裝上(這正是 Axis2 所用的方法)。CXF 還以 Jetty 服務 器的形式提供一個適合生產使用的集成 HTTP 服務器。與 Axis2 和 Metro 中集成的簡單服 務器支持相比,這可以提供一個更靈活、強大的替代選擇。
示例應用程序
代碼下載 部分提供了本系列之前文章中使用的簡單的書庫管理服務的一個版本,該版本 經過了修改,以演示 CXF 的使用。和之前的版本一樣,WSDL 服務定義一共定義 4 個操作:
getBook 用於獲取 International Standard Book Number (ISBN) 標識的特定圖書的詳 細信息。
getBooksByType 用於獲取某種類型的所有圖書的詳細信息。
getTypes 用於發現現有的圖書類型。
addBook 用於將新的圖書添加到書庫。
在 “Axis2 中的 JAXB 和 JAX-WS” 中,您看到了這個應用程序在 Axis2 中如何工作, 然後在 “Metro 簡介” 中,您看到了它如何在 Metro 中工作。 這幾篇文章中的大部分內 容也適用於使用 CXF 的情況。除了服務名稱和端點地址不同外,WSDL 是相同的;生成的 JAXB 數據模型是相同的,甚至生成的服務類也是相同的,只是 Java 包和 JAX-WS 注釋中使 用的服務名稱不同。
客戶端的使用
與在 Axis2 或 Metro 中使用 JAX-WS 相比,在 CXF 中,示例應用程序的客戶端代碼是 相同的,甚至構建步驟也是類似的:只需代替 JAX-WS 參考實現 wsimport 工具使用 CXF wsdl2java 工具即可。參閱 “Axis2 中的 JAXB 和 JAX-WS” 了解代碼和處理的詳細信息。
盡管客戶端代碼相同,不過 CXF 中的客戶端行為仍然有一個顯著差異。默認情況下,CXF 打印大量令人不悅的日志細節並輸出到控制台。CXF 使用 Java 日志記錄,因此為避免此輸 出,您需要設置一個系統屬性使其指向一個日志屬性文件,設置為僅在有 WARNING 或 SEVERE 信息時輸出日志。示例應用程序所用的 Ant build.xml 使用 JVM 參數行 <jvmarg value="-Djava.util.logging.config.file=${build- dir}/logging.properties"/> 完成這個設置。
服務器端的使用
與在 Axis2 或 Metro 中使用 JAX-WS 相比,在 CXF 中,示例應用程序的客戶端代碼也 是一樣的,且構建步驟與 Metro 很相似。使用 Axis2 時,是通過創建一個包含服務和數據 模型類的 JAR 文件來准備用於部署的服務,然後通過將該 JAR 拖放到 Axis2 服務器安裝目 錄中的 WEB-INF/servicejars 目錄中來部署服務。而當使用 Metro 和 CXF 時,則需要創建 一個包含服務和數據模型類、Metro 或 CXF 庫 JARs 以及一對配置文件(其中一個文件在這 兩個堆棧中名稱不同)的 WAR 文件。WEB-INF/web.xml 文件配置真正的 servlet 處理。用 於示例應用程序的版本如 清單 1 所示:
清單 1. 示例應用程序 web.xml
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee">
<display-name>CXFLibrary</display-name>
<description>CXF Library Service</description>
<listener>
<listener- class>org.springframework.web.context.ContextLoaderListener</listener- class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:META-INF/cxf/cxf.xml
classpath:META-INF/cxf/cxf-extension-soap.xml
classpath:META-INF/cxf/cxf-servlet.xml
</param-value>
</context-param>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet- class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
清單 1 WEB-INF/web.xml 文件正是一個標准 servlet 配置文件,它告訴 Web 應用程序 服務器(比如 Tomcat)如何接口到 servlet 應用程序。詳情與 Metro 示例中的那些細節一 樣,不過對於 CXF,<servlet-class> 是 CXF 代碼的一部分而 <listener- class> 引用一個 Spring Framework 類。與 Metro 示例一樣,servlet 被配置為接收所 有傳入該 Web 應用程序的請求(通過 <url-pattern>/</url-pattern> 條目) 。
一個獨立文件 WEB-INF/cxf-servlet.xml 用於配置 CXF,使其將 servlet 接收的請求路 由到服務實現代碼並按需提供服務 WSDL。該文件如 清單 2 所示:
清單 2. 示例應用程序 cxf-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:soap="http://cxf.apache.org/bindings/soap"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<jaxws:endpoint
id="Processor"
implementor="com.sosnoski.ws.library.cxf.CXFLibraryImpl"
wsdlLocation="WEB-INF/wsdl/library.wsdl"
address="/">
</jaxws:endpoint>
</beans>
清單 2 WEB-INF/cxf-servlet.xml 文件只有一個端點定義,其中包括一個實現類、請求 的匹配模式以及 WSDL 文檔位置。WSDL 文檔位置是這個端點定義中惟一的可選項。如果在 cxf-servlet.xml 文件中不指定服務端點的 WSDL 文檔,CXF 會在運行時基於 JAX-WS 注釋 自動生成一個 WSDL 文檔。
構建和運行示例代碼
捆綁帶來的問題
從 Java SE 6 開始,JAXB 2.x 和 JAX-WS 2.x 參考實現運行時(除了供應商擴展)成為 標准 Java Runtime Environment (JRE) 庫的一部分。其本意是鼓勵將這些技術作為 Java 標准使用,但是這也帶來一個副作用:為了使用這些技術的更新的版本,可能需要更改 JRE 的安裝。
示例應用程序下載文件中使用的 build.xml 將所需的 CXF JAR 文件直接復制到服務 WAR 文件。使用 Java SE 5 構建時,這包括 JAXB 和 JAX-WS JARs;當使用 Java SE 6 構建時 ,構建依賴於 JVM 安裝中 JAXB 和 JAX-WS 的版本。使用 Java SE 6 或更高版本時,如果 類裝載沖突在 JAXB 或 JAX-WS 代碼內產生問題,檢查一下您正在使用的 CXF 發行版是否有 任何 JVM 兼容性說明。
在運行示例代碼之前,首先需要下載並在系統上安裝當前版本的 Metro。示例代碼經過 2.2.5 版的測試。另外還需要對解壓的示例代碼根目錄中的 build.properties 文件進行編 輯,將 cxf-home 屬性的值改為 CXF 安裝目錄的路徑。如果要使用不同的系統或端口上的服 務器進行測試,那麼需要更改 host-name 和 host-port。
要使用所提供的 Ant build.xml 構建示例應用程序,打開一個控制台,進入下載文件的 根目錄,輸入 ant。這將首先調用 CXF wsdl2java 工具(包括在 CXF 中),然後編譯客戶 端和服務器,最後將服務器代碼打包為 WAR。接著可以將生成的 cxf-library.war 文件部署 到測試服務器,並在控制台輸入 ant run 嘗試運行示例客戶端。示例客戶端運行,經過一系 列對服務器的請求,打印出每個請求的簡要結果。正如在 客戶端的使用 中所提到的,構建 過程會配置 CXF 日志記錄,以避免運行示例客戶端時打印配置細節。
CXF 中的 Spring
注意在 清單 2 cxf-servlet.xml 配置文件中 Spring Framework bean 配置的使用。您 可能知道,Spring 是一種開源應用程序框架,它包括許多可用來裝配應用程序的組件庫。 Inversion of Control (IoC) 是 Spring Framework 的原始基礎,它允許鏈接和配置 JavaBean 類型的軟件組件,在運行時使用 Java 映像訪問 bean 對象的屬性。
Spring IoC 容器通常為依賴性信息使用 XML 文件,清單 2 中的 cxf-servlet.xml 文件 就是這種 Spring 配置的一個示例。<beans> 元素僅是單個 bean 配置的一個包裝器 。<jaxws:endpoint> 元素就是這樣的一個 bean,CXF 通過特定類型的對象(一個 org.apache.cxf.jaxws.EndpointImpl 實例)與其相關聯。
除了這個簡單示例中使用的選項之外,還可以指定很多其他選項,包括服務的消息流配置 。參閱 CXF 文檔中的 JAX-WS 配置信息了解完整細節(Frontends/JAX-WS 目錄下)。
除了 JAX-WS 注釋之外,Spring 還用於 CXF 堆棧的所有配置,包括 CXF 內部消息流的 組織。大部分時候,這些配置細節都通過使用直接包含在 CXF JARs 中的 XML 配置得到自動 處理,(參閱 清單 1 web.xml 文件中的 contextConfigLocation 參數值,了解如何引用它 們),不過可以使用自己的配置文件覆蓋或添加到公共流。本系列文章不直接介紹這方面內 容;您可以參閱 CXF 文檔了解詳細信息。
CXF 展望
本文介紹了 CXF Web 服務堆棧使用 JAXB 2.x 數據綁定和對 JAX-WS 2.x 注釋進行配置 的基礎知識。之前的文章中 Axis2 和 Metro 堆棧使用的 JAXB/JAX-WS 代碼在 CXF 中也可 以使用,只是構建過程有些許修改且使用的部署配置文件有所不同。這種跨堆棧兼容性是使 用 JAXB 和 JAX-WS 的主要優點,因為這便於在不同的堆棧之間切換。
CXF 的功能比這個簡單示例顯示的要多很多,在後面的文章中您將了解到其他一些特性。 下一篇文章將著眼於 WS-Security 的使用,您將看到 CXF 實現與 Axis2 和 Metro 的區別 。
本文配套源碼