開始之前
關于本教程
在本教程中,我們将設計和開發一個訂單處理應用程式,并将其功能作為 Web 服務公開,以便各種使用者以獨立于平台的方式送出訂單資訊。
目标
完成了此教程後,可以應用相關概念和知識來使用 JAX-WS 技術為應用程式開發 Web 服務。
先決條件
要成功完成此教程,應該對 Web 服務技術具有基本的了解,而且需要能較為熟練地進行 Java 程式設計。
系統要求
要運作此教程中的示例,需要安裝 Java Platform, Standard Edition (Java SE) 6.0。
JAX-WS 簡介
為何使用 JAX-WS?
JAX-WS 是用于簡化使用 Java 構造 Web 服務和 Web 服務客戶機的工作的技術。該技術提供了完整的 Web 服務堆棧,可減少開發和部署 Web 服務的任務。JAX-WS 支援 WS-I Basic Profile 1.1,後者可確定使用 JAX-WS 堆棧開發的 Web 服務能夠供采用 WS-I Basic Profile 标準使用任意語言開發的任意客戶機使用。JAX-WS 還包括了 Java Architecture for XML Binding (JAXB) 和 SOAP with Attachments API for Java (SAAJ)。
JAXB 提供了一種非常友善的方法來将 XML 模式映射到 Java 代碼的表示形式,進而支援資料綁定功能。JAXB 消除了将 SOAP 消息中的 XML 模式消息轉換為 Java 代碼的工作,因而不必全面了解 XML 和 SOAP 解析。JAXB 規範定義 Java 和 XML 模式之間的綁定。SAAJ 提供了标準的方法來處理 SOAP 消息中包含的 XML 附件。
而 且,JAX-WS 提供了用于将傳統 Java 對象(Plain Old Java Object,POJO)類轉換為 Web 服務的 Annotation 庫,進而加速了 Web 服務的開發工作。另外,它還指定了從采用 Web 服務描述語言(Web Services Description Language,WSDL)定義的服務到實作該服務的 Java 類之間的詳細映射。采用 WSDL 定義的任意複雜類型都通過遵循 JAXB 規範定義的映射來映射為 Java 類。JAX-WS 之前與 Java Platform, Enterprise Edition (Java EE) 5 綁定。而 JAX-WS 2.0 規範是作為 Java Community Process (JCP) 的 JSR 224 開發的。
開發 Web 服務
契約優先方法與代碼優先方法
進入 JAX-WS 時代的最好方法莫過于首先開發一個 Web 服務。可以采用以下兩種方法之一開發 Web 服務:
- 契約優先: 從 WSDL 契約着手,生成 Java 類來實作服務。
- 代碼優先: 從 Java 類着手,使用 Annotation 來生成 WSDL 檔案和 Java 接口。
契約優先 WSDL 方法需要對用于定義消息格式的 WSDL 和 XML 模式定義(XML Schema Definition,XSD)有良好的了解。如果您對 Web 服務相當陌生,最好從代碼優先方法着手,本教程中将使用此方法開發 Web 服務。
代碼優先 Web 服務開發
使用代碼優先方法時,将從實作希望作為服務公開的功能的 Java 類或類入手。在已經提供了 Java 實作且需要将實作作為服務公開的情況下,代碼優先方法尤為有用。
開發訂單處理 Web 服務
讓我們首先建立一個訂單處理 Web 服務,用于接受訂單資訊、配送資訊和訂購物品并最終生成确認 ID 作為響應。訂單處理服務的代碼如清單 1 中所示。這是一個虛拟實作,将在控制台輸出客戶 ID 和物品數量,然後輸出虛拟訂單 ID A1234 。(可以在本文的下載下傳 部分下載下傳完整的應用程式源代碼。)将源代碼解壓到 C 盤,會在其中建立一個名為 JAXWS-Tutorial 的檔案夾。此檔案夾包含對應的源代碼,如清單 1 中所示。
清單 1. 訂單處理 Web 服務實作
|
OrderBean
中包含訂單資訊,如清單 2 中所示。具體來說,其中包含對客戶、訂單項和配送位址對象的引用。
清單 2. 包含訂單資訊的 OrderBean 類
|
開發 JAX-WS Web 服務的起點是一個使用
javax.jws.WebService
Annotation 進行了标注的 Java 類。所使用的 JAX-WS Annotation 屬于 Web Services Metadata for the Java Platform 規範 (JSR-181) 的一部分。您可能已經注意到了,
OrderProcessService
使用
WebService
Annotation 進行了标注,而後者将類定義為了 Web 服務端點。
OrderProcessService
類(帶有
@javax.jws.WebService
Annotation 的類)隐式地定義了服務端點接口(Service Endpoint Interface,SEI),用于聲明客戶機可以對服務調用的方法。除了使用
@WebMethod
Annotation 标注且 exclude 元素設定為 true 的方法外,類中定義的所有公共方法都會映射到 WSDL 操作。
@WebMethod
Annotation 是可選的,用于對 Web 服務操作進行自定義。除了 exclude 元素外,
javax.jws.WebMethod
Annotation 還提供 operation name 和 action 元素,用于在 WSDL 文檔中自定義操作的 name 屬性和 SOAP action 元素。這些屬性是可選的;如果未定義,會從類名稱派生預設值。
實 現 Web 服務後,需要生成部署服務所需的所有構件,然後将 Web 服務打包為部署構件(通常為 WAR 檔案),并将 WAR 檔案部署到任何支援 JAX-WS 2.0 規範的相容伺服器上。通常生成的構件是提供基于服務接口将 Java 對象轉換為 XML、WSDL 檔案和 XSD 模式的功能的類。
出于測試目的,Java 6 綁定了一個輕量級 Web 伺服器,可以通過調用簡單的 API 調用将 Web 服務釋出到該伺服器上。接下來我們将了解如何使用此方法測試 Web 服務。
釋出服務
生成 JAX-WS 構件
運作 wsgen 工具,以生成訂單處理 Web 服務的 JAX-WS 可移植構件。此工具将讀取 Web SEI 類,并生成 Web 服務部署和調用所需的所有構件。wsgen 工具生成需要釋出的 Web 服務的 WSDL 檔案和 XSD 模式。
為了生成 JAX-WS 構件,首先需要編譯服務和 Bean 源檔案:
- 打開指令提示符,并進入到 c:/JAXWS-Tutorial目錄。
- 運作以下指令,以編譯 Java 檔案,并将類檔案放入其各自檔案夾中:
javac com/ibm/jaxws/tutorial/service/*.java com/ibm/jaxws/tutorial/service/bean/*.java
- 運作以下指令,以生成 JAX-WS 構件:
wsgen -cp . com.ibm.jaxws.tutorial.service.OrderProcessService -wsdl
wsgen 工具提供了大量的選項,例如,其中提供了
-wsdl
選項,用于生成服務的 WSDL 和模式構件。運作此指令後,應該在 JAXWS-Tutorial 檔案夾中看到生成的 OrderProcess.wsdl 和 OrderProcess_schema1.xsd,而且會看到在 com/ibm/jaxws/tutorial/service/jaxws 檔案夾中建立了 JAX-WS 構件。
生成了構件後,運作以下 Web 服務釋出器客戶機,以釋出訂單處理 Web 服務。
- 從 c:/JAXWS-Tutorial 檔案夾運作以下指令,以編譯
:OrderWebServicePublisher
javac com/ibm/jaxws/tutorial/service/publish/OrderWebServicePublisher.java
- 然後運作以下指令:
java com.ibm.jaxws.tutorial.service.publish.OrderWebServicePublisher
運作 Java 程式後,應該看到以下消息:
The Web service is published at http://localhost:8080/OrderProcessWeb/orderprocess. To stop running the Web service, terminate this Java process.
這會将訂單 Web 服務釋出到 http://localhost:8080/OrderProcessWeb/orderprocess。可以通過顯示訂單處理 Web 服務生成的 WSDL 來驗證 Web 服務是否在運作:
- 打開浏覽器,并導航到 http://localhost:8080/OrderProcessWeb/orderprocess?wsdl。
![]() |
|
分析 OrderWebServicePublisher
在分析 WSDL 和模式構件前,讓我們分析一下
OrderWebServicePublisher
的代碼。清單 3 提供了
OrderWebServicePublisher
客戶機的源代碼。
清單 3. 用于釋出訂單處理 Web 服務的代碼
|
通過
Endpoint.publish()
方法,可以友善地釋出和測試 JAX-WS Web 服務。
publish()
接受兩個參數:Web 服務的位置和 JAX-WS Web 服務實作類。
publish()
方法在指定的 URL(本例中為本地主機,端口為 8080)建立輕量級 Web 伺服器,并将 Web 服務部署到該位置。此輕量級 Web 伺服器在 Java 虛拟機(Java Virtual Machine,JVM)中運作,可通過調用
endpoint.stop()
方法以有條件的方式終止,或終止
OrderWebServicePublisher
客戶機。
![]() |
|
分析生成的 WSDL
要檢視生成的訂單處理 Web 服務 WSDL,在浏覽器中鍵入以下 URL 位置:
http://localhost:8080/OrderProcessWeb/orderprocess?wsdl
.
讓我們分析 WSDL 一些重要方面的内容,并了解如何基于 JAX-WS 中繼資料生成 WSDL 和模式構件,首先要分析的是生成的 XSD。此内容使用
xsd:import
标記導入到 WSDL 檔案中(請參見清單 4);
schemaLocation
指定 XSD 的位置。
清單 4. 包含訂單處理模式定義的 WSDL 檔案
|
在浏覽器中打開
schemaLocation
(http://localhost:8080/OrderProcessWeb/orderprocess?xsd=1),以檢視模式定義在浏覽器中呈現的情況。讓我們分析一下其中的情況:模式定義最開始是
targetNamspace
和
tns
聲明,映射到在
OrderProcessService
的
@WebService
Annotation 中定義的
targetNamespace
http://jawxs.ibm.tutorial/jaxws/orderprocess。清單 5 給出了對應的代碼。
清單 5. 模式(Schema)命名空間聲明
|
前面指定的 wsgen 工具指令生成兩個包裝 Bean 類,
ProcessOrder
和
ProcessOrderResponse
,分别包含訂單處理 Web 服務的輸入和輸出消息。将基于這些包裝 Bean 類生成以下模式元素:
-
屬于processOrder
類型,表示其中包含一個元素,且此元素的名稱為processOrder
,類型為arg0
。可以看到,在orderBean
類和ProcessOrder
複雜類型之間存在一對一映射。processOrder
-
與processOrderResponse
類型類似,後者的定義映射到processOrderResponse
類。ProcessOrderResponse
讓我們仔細分析一下清單 6 中的代碼。
清單 6. processOrder 的模式聲明
|
清單 7 中所示的
orderBean
類型定義映射到
OrderBean
類。
orderBean
類型定義包括:
- 一個
元素,其類型為customer
。customer
- 一個
,其類型為orderId
。string
-
(它為數組類型,因為其将orderItems
屬性指定為maxOccurs
),其類型為unbounded
。orderItem
-
,其類型為shippingAddress
。address
清單 7. processOrder 的模式聲明
|
類似地,模式的其餘部分
customer
、
orderItems
和
address
分别映射到
Customer
、
OrderItem
和
Address
Java Bean。
分析了模式定義後,接下來讓我們回頭來看看 WSDL 中的消息定義,如清單 8 中所示。WSDL 指定消息
processOrder
和
processOrderResponse
,其所屬的元素為
processOrder
和
processOrderResponse
(我們已經讨論了其模式定義)。
portType
指定操作
processOrder
,其輸入消息為
processOrder
,而輸出消息為
processOrderResponse
。
清單 8. WSDL 文檔中的 processOrder 消息元素
|
接下來定義了 WSDL 綁定。此綁定将
soap:binding
樣式定義為
document
,
soap:body
使用
literal
标記指定操作
processOrder
的輸入和輸出消息格式。生成的 WSDL 定義映射到
@SOAPBinding
Annotation(已在
OrderProcessService
類上定義,請參見清單 9)。
清單 9. WSDL 文檔的綁定資訊
|
接下來定義 WSDL 服務。這将指定端口和對應的綁定類型,以及服務的實際位置。此位置通常為 HTTP 位置,在本例中為 http://localhost:8080/OrderProcessWeb/orderprocess。可以在清單 10 中了解到具體的情況。
清單 10. WSDL 文檔的服務資訊
|
我們已經對生成的 WSDL 和模式構件進行了分析。清單 11 給出了一個示例 SOAP 請求消息,此消息是在 Web 服務客戶機調用
processOrder
操作時發送的。
清單 11. processOrder 操作的示例 SOAP 消息
<?xml version="1.0"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1=" http://jawxs.ibm.tutorial/jaxws/orderprocess"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soapenv:Body>
<ns1:processOrder>
<arg0>
<customer><customerId>A123</customerId>
<firstName>John</firstName><lastName>Smith</lastName></customer>
<orderItems><itemId>11</itemId><qty>11</qty></orderItems>
</arg0>
</ns1:processOrder>
</soapenv:Body>
</soapenv:Envelope>
建立 Web 服務客戶機
從 WSDL 建立 Web 服務客戶機
在本部分,我們将了解如何從 WSDL 建立 Web 服務客戶機。JAX-WS 提供了名為 wsimport 的工具,用于從 WSDL 生成 JAX-WS 可移植構件。生成的可移植構件通常包括以下内容:
- SEI
- 服務(需要實作的服務實作類)
- 從模式類型生成的 JAXB 生成類
- 從 wsdl:fault 映射的異常類(如果有)
客 戶機使用生成的構件調用 Web 服務。Web 服務客戶機并不需要處理任何 SOAP 格式(如建立或解析 SOAP 消息)。這将由 JAX-WS 運作時予以處理,此運作時将使用生成的構件代碼(JAXB 生成類)。Web 服務将處理 Java 代碼(JAXB 生成類),進而減少了開發 Web 服務客戶機和對 Web 服務調用操作的工作。
先使用 wsimport 工具從
OrderProcess
WSDL 生成 JAX-WS 構件。然後要建立 Web 服務客戶機,後者使用生成的構件代碼調用訂單處理 Web 服務。要生成 JAX-WS 構件,賢進入到 JAXWS-Tutorial 目錄,并運作清單 12 中所示的 wsimport 指令。不過,進行操作前,請確定已經按照生成 JAX-WS 構件部分 中的步驟 5 所述的方法,通過運作
OrderWebServicePublisher
釋出了 Web 服務。
清單 12. 用于生成供 Web 服務客戶機使用的 JAX-WS 構件的 wsimport 指令
|
-keep
選項訓示保留生成的檔案,
-p
選項指定需要在其中生成構件的包名稱。
http://localhost:8080/OrderProcessWeb/orderprocess?wsdl
指定 WSDL 檔案的位置。以下構件是從
OrderProcessService
WSDL 生成的:
- JAXB 類(
、Address
,Customer
和OrderBean
): 通過讀取OrderItem
WSDL 中定義的模式定義生成OrderProcessService
-
和RequestWrapper
類(ResponseWrapper
和ProcessOrder
): 包裝 document literal-wrapped 樣式類型的輸入和輸出ProcessOrderResponse
- 服務類 (
): 客戶機用于請求 Web 服務的類OrderProcess
- 服務接口 (
): 包含着用于服務實作接口的類OrderProcessService
接下來了解一下如何使用上面生成的構件建立 Web 服務客戶機。com/ibm/jaxws/tutorial/service/client 檔案夾中提供了一個示例參考代碼。Web 服務客戶機的代碼如清單 13 中所示。
清單 13. 訂單處理 Web 服務客戶機的代碼清單
|
上面列出的 Web 服務客戶機代碼執行以下任務:
- 通過傳入
Web 服務的 WSDL URL 和服務的OrderProcess
建立QName
類的執行個體。OrderProcess
- 建立
的執行個體,并使用OrderBean
方法填充訂單資訊。populateOrder()
- 對服務調用
,以檢索到服務的代理(也稱為端口)。端口實作服務所定義的接口。getOrderProcessPort()
- 調用端口的
方法,并同時傳入在上面的第二個清單項目中建立的processOrder
執行個體。OrderBean
- 從服務獲得
響應并輸出訂單 ID。OrderBean
運作 Web 服務客戶機
要運作 Web 服務客戶機,請首先從 JAXWS-Tutorial 檔案夾運作以下指令來編譯 Web 服務客戶機:
javac com/ibm/jaxws/tutorial/service/client/OrderClient.java
通過使用以下指令提供訂單處理 Web 服務的 WSDL URL 來運作 Web 服務客戶機:
java com.ibm.jaxws.tutorial.service.client.OrderClient http://localhost:8080/OrderProcessWeb/orderprocess?wsdl
運作 Web 服務客戶機時,會在控制台看到以下輸出(
OrderWebServicePublisher
在控制台中運作):
processOrder called for customer A123
Number of items is 1
在運作 Web 服務客戶機的控制台中,會得到以下輸出:
Order id is A1234
如上面的客戶機代碼中所示,并不會處理調用 Web 服務操作時使用的任何基于 SOAP 或 XML 的格式;相反,需要處理的是輸入和輸出消息的 JAXB 生成類,并使用服務接口和服務類對象(充當 Web 服務調用的存根)。存根負責從 JAXB Annotation 建立 SOAP 請求,并将 SOAP 響應轉換回 Java 對象。
您現在已經成功地建立和釋出了 Web 服務,并通過 Web 服務客戶機成功地執行了此服務。
總結
在本教程中,我們了解了如何使用代碼優先的開發方法和 JAX-WS 技術設計和開發 Web 服務。JAX-WS 是一個非常不錯的選擇,因為其中提供了完整的 Web 服務堆棧,以簡化 Web 服務的開發和部署。
本 教程中開發的訂單處理 Web 服務使用 Document 樣式的 Web 服務,可確定服務使用者和服務提供者使用 XML 文檔進行通信。XML 文檔遵循定義良好的契約,而此類契約通常都是使用 XML 模式定義建立的。XML 模式格式指定服務使用者能夠調用和遵循的業務消息的契約。Document 樣式的 Web 服務應該是開發企業 Web 服務的首選方法。
下載下傳
描述 | 名字 | 大小 | 下載下傳方法 |
---|---|---|---|
JAX-WS Web services code | jaxws.zip | 32KB | HTTP |