程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java Web服務: Metro簡介

Java Web服務: Metro簡介

編輯:關於JAVA

Metro Web 服務棧是由 Sun Microsystems 開發的一個開源工具。它將 JAXB 2.x 數據綁定和 JAX-WS 2.x Web 服務標准的參考實現與其他與 XML 相關的 Java 標准相結合。Metro 還包括一些附加組件,以 支持基本 JAX-WS 服務的定義和使用以及 SOAP 消息交換的各種 WS-* 擴展。

Metro 既可以用作獨立的 Web 服務棧,也可以用作開源 Glassfish 應用服務器中的集成組件。如果 使用 Glassfish,尤其是在擁有配置基本 Web 服務和 WS-* 擴展的 GUI 工具的開源 NetBeans IDE 上進 行開發時,Web 服務配置會變得更加容易。本系列繼續關注 Web 服務。以前的文章討論 Apache Axis2 的獨立使用,而不是包含 Axis2 並支持 GUI 工具的 Apache Axis2 應用服務器。本文也一樣,只討論以 獨立於 IDE 的方式單獨使用 Metro。

Metro 基礎與 Axis2

本系列之前的文章已經深入討論了 Axis2,所以本文首先討論 Metro 與 Axis2 之間的相似點和不同 點。兩者的相似點比較有限,主要圍繞於使用 Web 服務開發代碼的常見需求。這兩個框架都允許要麼從 已有的 Java 代碼開始構建 Web 服務(但是,除非使用 Jibx2Wsdl 之類的單獨的工具,否則 Axis2 對 這種方法的支持有限),要麼從 WSDL Web 服務描述開始,生成使用或實現服務的 Java 代碼。這兩個框 架都是將服務操作建模為方法調用,而將服務端口類型建模為接口。

Metro 與 Axis2 之間的不同點比相似點要鮮明得多。從基礎上講,Metro 是圍繞 JAXB 2.x 和 JAX- WS 2.x 設計的,無意支持這兩種技術以外的任何替代技術(除了遺留的 JAX-RPC 的使用)。而 Axis2 則被設計為支持無限種技術,尤其是在 XML 數據綁定領域。雖然它包括對 JAXB 2.x 和 JAX-WS 2.x 的 支持,但是二者並無特殊地位。(如果說有的話,也僅限於 JAX-WS 某種意義上是 Axis2 中的第二類方 案,原因正如 “Axis2 中的 JAXB 和 JAX-WS” 中所述,無法為 JAX-WS 服務配置 WS-Security 或其他 特性)。

從結構上講,兩種棧在處理請求和響應時都使用處理器。Axis2 以這種處理器方法為基礎實現模塊: 基本 SOAP 消息交換的可插拔擴展,用於以高度可配置的方式實現 WS-* 技術。Metro 支持多種實現處理 器的 WS-* 技術,但是這些技術都被集成到 Metro 引擎,而不是作為可分離組件。Metro 使用的集成方 法不如 Axis2 模塊靈活,但是在配置和使用 WS-* 擴展方面有一些優勢。

在客戶端代碼如何使用 WSDL 服務定義方面,這兩種棧之間也有不同。Axis2 主要將 WSDL 服務定義 用於客戶端代碼生成,從 WSDL 中提取服務定義信息,並生成代碼,以在運行時構造匹配的 Axis2 客戶 端配置(不過也可以在運行時解析 WSDL 定義)。JAX-WS 2.x,當然還有 Metro,在運行時都需要 WSDL 服務定義,以便構建服務定義。在運行時使用 WSDL 會增加啟動開銷 — 不過僅限於第一次服務調用 — 沒有任何明顯的優點。

在服務器端也有不同之處。對於常見的 HTTP 傳輸,Axis2 通常作為單獨的 Web 應用程序(一個 WAR 程序),另外還有任意數量的服務被部署到該 Axis2 Web 應用程序(不過也可以將它打包到應用程序 WAR 中)。可以通過 Web 頁面上傳部署服務,也可以通過直接將 Axis2 服務 AAR 文件拖放到擴展的 Axis2 Web 應用程序的適當目錄中來部署服務。通常,在構建時,Axis2 從 WSDL 服務定義生成各個服務 的配置信息,然後將其包括在服務 AAR 文件中。標准的 Axis2 Web 應用程序還通過 Web 頁面提供多種 監視和控制工具。

相反,Metro 要求為每個 Web 服務應用程序構建單獨的 WAR 文件,而 Metro 庫 JAR 文件要麼包括 在 WAR 中,要麼包含在類中(作為 HTTP 服務器的一部分),WAR 中還有一個 WEB-INF/web.xml 文件, 該文件引用服務和 Metro servlet。當單獨使用 Metro 時,還需要創建一個 sun-jaxws.xml 配置文件, 該文件提供關於服務配置的附加信息。這些配置文件中的信息與實際 Web 服務類中的 JAX-WS 注釋相結 合,一同為服務配置 Metro。由於 Metro 被設計為以這種嵌入式的方式使用,所以不提供任何直接監視 或控制的工具。

Axis2 和 Metro 都提供集成的 HTTP 服務器支持。對於 Metro,這是通過 JAX-WS 特性 javax.xml.ws.Endpoint 類提供的。Axis2 和 Metro/JAX-WS 的集成 HTTP 服務器都適合在測試中使用, 或者作為異步響應端口,但是不能容納生產 Web 服務,對於生產 Web 服務,可以使用支持 Servlet API 的 Java 應用服務器。

示例應用程序

代碼下載 部分提供了本系列之前文章中使用的簡單的書庫管理服務的一個版本,該版本經過了修改, 以演示 Metro 的使用。和之前的版本一樣,WSDL 服務定義一共定義 4 個操作:

getBook,用於獲取國際標准書號(International Standard Book Number,ISBN)標識的特定圖書的 詳細信息

getBooksByType,用於獲取某種類型的所有圖書的詳細信息

getTypes,用於發現現有的圖書類型

addBook,用於將新的圖書添加到書庫

在 “Axis2 中的 JAXB 和 JAX-WS” 中,您看到了這個應用程序在 Axis2 中如何工作:首先使用 JAXB 2.x 數據綁定生成代碼,然後進行 JAX-WS 2.x 服務配置。該文章的大部分內容也適用於使用 Metro 的情況。除了服務名稱和端點地址不同外,WSDL 是相同的,生成的 JAXB 數據模型是相同的,甚 至生成的服務類也是相同的,只是 Java 包和 JAX-WS 注釋中使用的服務名稱不同。

客戶端的使用

與使用 Axis2 和 JAX-WS 相比,在使用 Metro 的情況下,示例應用程序的客戶端代碼是相同的,甚 至構建步驟也是相同的。請參閱 “Axis2 中的 JAXB 和 JAX-WS” 了解代碼和處理的詳細信息。

服務器端的使用

與使用 Axis2 和 JAX-WS 相比,在使用 Metro 的情況下,示例應用程序的服務器端代碼也是一樣的 ,只是構建步驟有所不同。使用 Axis2 時,是通過創建一個包含服務和數據模型類的 JAR 文件來准備用 於部署的服務,然後通過將該 JAR 拖放到 Axis2 服務器安裝目錄中的 WEB-INF/servicejars 目錄中來 部署服務。

而當使用 Metro 時,則需要創建一個包含服務和數據模型類的 WAR 文件,然後創建 Metro 庫 JAR( 不過也可以將 Metro JAR 直接安裝到 Web 服務器 — 如果使用 Tomcat,Metro 下載文件中包括一個用 於安裝 JAR 的 metro-on-tomcat.xml Ant 構建文件,另外在文檔中還有說明),以及一對配置文件。 WEB-INF/web.xml 文件配置實際的 servlet 處理。清單 1 顯示用於示例應用程序的版本:

清單 1. 示例應用程序 web.xml

<web-app version="2.4"  xmlns="http://java.sun.com/xml/ns/j2ee">
  <display-name>MetroLibrary</display-name>
  <description>Metro Library Service</description>
  <listener>
   <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener
   </listener-class>
  </listener>
  <servlet>
   <servlet-name>MetroLibraryPort</servlet-name>
   <display-name>MetroLibraryService</display-name>
   <description>Endpoint for Metro Library Service</description>
   <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet- class>
   <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
   <servlet-name>MetroLibraryPort</servlet-name>
   <url-pattern>/</url-pattern>
  </servlet-mapping>
  <session-config>
   <session-timeout>60</session-timeout>
  </session-config>
</web-app>

如果以前開發過 Java Web 應用程序,那麼 清單 1 WEB-INF/web.xml 文件看上去應該很熟悉(至少 結構上是這樣)。相應的條目告訴 servlet 引擎將 WAR 文件部署到哪裡,以便使用 com.sun.xml.ws.transport.http.servlet.WSServletContextListener 類作為 servlet 上下文事件的偵 聽器,另外使用 com.sun.xml.ws.transport.http.servlet.WSServlet 類作為實際的 servlet。這兩個 類是 Sun 的 Metro 棧特有的,要使用 Metro 必須引用這兩個類。servlet 被配置為接收所有傳入該 Web 應用程序的請求(通過 <url-pattern>/</url-pattern> 條目)。

清單 1 WEB-INF/web.xml 文件本身只是配置 servlet 引擎,讓它使用 Metro 提供的偵聽器和 servlet。另有一個文件 WEB-INF/sun-jaxws.xml(清單 2所示)用於配置 Metro,使其將 servlet 接收 的請求路由到服務實現代碼。

清單 2. 示例應用程序 sun-jaxws.xml

<endpoints  xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0">

   <endpoint name="MetroLibraryPort"
     implementation="com.sosnoski.ws.library.metro.MetroLibraryImpl"
     url-pattern="/"
     wsdl-location="WEB-INF/wsdl/library.wsdl"/>

</endpoints>

清單 2 WEB-INF/sun-jaxws.xml 文件非常簡單,只有一個端點定義,其中包括端口名、實現類、請求 的匹配模式以及 WSDL 文檔位置。WSDL 文檔位置是端點定義中唯一的可選項。如果在 sun-jaxws.xml 文 件中不指定服務端點的 WSDL 文檔,Metro 會在運行時自動生成一個 WSDL 文檔。

捆綁帶來的問題

從 Java SE 6 開始,JAXB 2.x 和 JAX-WS 2.x 參考實現運行時(除了供應商擴展)成為標准 Java Runtime Environment(JRE)庫的一部分。其本意是鼓勵將這些技術作為 Java 標准使用,但是這也帶來 一個副作用:為了使用這些技術的更新的版本,可能需要更改 JRE 的安裝。

示例應用程序下載文件中使用的 build.xml 將 Metro JAR 文件直接復制到服務 WAR 文件。如果使用 Java SE 5 或者 Java SE 6 JDK/JRE,並且應用程序被部署到 Apache Tomcat 6.0.20 Web 服務器,那麼 在作者的系統上是可行的。使用 Java SE 6 或更高版本時,如果類裝載沖突(例如拋出 ClassCastException,或者未發現 com.sun.xml... 類)導致問題,那麼可以使用下面的修復方法:

確保使用適合您的系統的最新 JRE 版本,因為更新可能包括更高版本的 JAXB 2.x 和 JAX-WS 2.x。

使用 java.endorsed.dirs 系統屬性從 Metro lib 目錄中指定一個包含 webservices-api.jar 文件 的目錄(僅限於 webservices-api.jar 文件,因為將其他 JAR 包括進來會導致類裝載沖突)作為更新的 庫的源。(Tomcat 6.0.x 支持這種機制,方法是查找一個 JAVA_ENDORSED_DIRS 環境變量,並使用它作 為系統屬性值)。

如果以上方法仍然失敗,那麼在 JRE 安裝目錄下的 lib 目錄中創建一個 endorsed 目錄(如果該目 錄不存在的話),然後將 Metro webservices-api.jar 文件復制到該目錄。

對於最後兩種技巧,不需要將 Metro webservices-api.jar 包括在服務 WAR 文件中,因為它在 Web 服務器的類路徑中是直接可用的。

構建和運行示例代碼

在運行示例代碼之前,首先需要下載和安裝當前版本的 Metro(代碼經過 1.5 版的測試)。另外還需 要對解壓的示例代碼下載文件根目錄中的 build.properties 文件進行編輯,將 metro-home 屬性的值改 為 Metro 安裝目錄的路徑。如果要使用不同的系統或端口上的服務器進行測試,那麼可能需要更改 host-name 和 host-port。

要使用 Ant build.xml 構建示例應用程序,打開一個控制台,進入下載文件的根目錄,輸入 ant。這 將首先調用 JAX-WS wsimport 工具(包括在 Metro 中),然後編譯客戶端和服務器,最後將服務器代碼 打包為 WAR。接著可以將生成的 metro-library.war 文件部署到測試服務器,並在在控制台輸入 ant run,嘗試運行示例客戶端。示例客戶端運行,經過一系列對服務器的請求,打印出每個請求的簡要結果 。

不幸的是,Metro 處理不會完全地執行例子。當 Metro 服務器代碼將異常轉換成 SOAP Fault 消息時 ,它還(默認地)發送棧跟蹤細節。Metro 客戶端代碼不能識別響應中的 Fault 數據,只是拋出適當的 Fault 對象,而不會填充包含的數據。在例子代碼中,這會導致一個 NullPointerException。

為了改變這種令人驚訝的默認行為,需要在服務器 JVM 上設置一個 com.sun.xml.ws.fault.SOAPFaultBuilder.disableCaptureStackTrace=false 屬性。(是的,正是這樣 — 將 disableCaptureStackTrace 屬性設為 false,以禁止發送棧跟蹤)。通常需要在 Java Web 服務 器啟動時進行這樣的屬性設置。對於 Tomcat,可以通過定義一個環境變量來完成這項工作:

CATALINA_OPTS=
  -Dcom.sun.xml.ws.fault.SOAPFaultBuilder.disableCaptureStackTrace=false

對服務器配置進行了更改並且重新啟動服務器後,應該可以完全運行示例程序。

結束語

在本文中,您看到了使用 Metro Web 服務棧的基本知識。由於 Metro 使用 JAX-WS 2.x 注釋進行配 置,因此 “Axis2 中的 JAXB 和 JAX-WS” 中使用的 JAX-WS 2.x 示例應用程序代碼在 Metro 中也可以 使用。唯一需要關心的是如何打包代碼並將其部署到服務器端,Metro 和 Axis2 在這方面有明顯的差異 。Metro 使用嵌入式方法為每個服務或服務組創建一個 Web 應用程序(不提供控制或監視功能)。而 Axis2 通常使用一個專用的 Web 應用程序作為任意數量的服務的宿主(通過 Web 頁面直接提供基本的控 制和監視功能)。

除了基本的 Web 服務消息交換外,Metro 還支持 SOAP 擴展,例如 WS-Security。和服務打包問題一 樣,Metro 和 Axis2 對這方面的相似問題采取不同的方法。在下一篇文章中,您將看到 Metro 如何處理 在前面的文章中使用 Axis2 處理的 WS-Security 例子。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved