1.JAX-WS以文檔作為消息傳遞模型為中心,取代JAX-RPC程式設計模型定義的遠端過程調用。
JAX-WS程式設計标準的實作為開發WEB服務和用戶端提供了如下好處:
(1)為JAVA應用提供了更好的平台獨立性:
使用JAX-WS的API開發web服務和用戶端使開發過程更簡化并使java應用具有平台獨立性。
JAX-WS利用動态代理機制來提供一個可插拔的正式委托模型實作。
而JAX-RPC要依賴于特定供應商的調用存根來生成。
4.開發jax-ws用戶端
(1)排程用戶端(Dispatch Client):基于XML消息級别的服務于web service和web service client之間通信的動态用戶端。
a.支援的對象類型:javax.xml.transform.Source(可以與SOAP和HTTP進行綁定);
JAXB對象(隻能與SOAP和HTTP進行綁定);
javax.xml.soap.SOAPMessage(隻能與SOAP進行綁定);
javax.activation.DataSource(用戶端可工作于多用途郵件擴充消息(MIME),隻與HTTP綁定)。
b.調用方式:使用invoke方法對requests和responses的同步調用;
使用invokeAsync方法和一個回調(callback)對象或者一個輪詢(polling)對象對requests和responses進行異步調用;
使用invokeOneWay方法進行單向調用。
c.開發要求:對Dispatch用戶端API的了解;對支援的對象類型的了解;了解WSDL相關檔案的資訊表征知識。
d.建立動态用戶端的步驟:
i.确定動态用戶端是以MESSAGE還是PAYLOAD模式發送資料;
ii.建立一個服務執行個體并添加至少一個端口(port),端口攜帶了協定綁定和服務端點位址資訊;
iii.使用Service.Mode.PAYLOAD 模式或者 Service.Mode.MESSAGE 模式建立一個Dispatch<T>對象;
iiii.配置javax.xml.ws.BindingProvider的請求上下文屬性,使用請求上下文指定附加屬性如啟用HTTP身份驗證或指定端點位址;
iiiii.組裝動态用戶端的請求消息;
iiiiii.用排程用戶端同步或異步調用服務端點;
iiiiiii.處理來自服務的響應消息。
(2)動态代理用戶端(Dynamic Proxy Client):JAX-WS的靜态用戶端程式設計模型。動态代理用戶端根據必須提供的服務端點接口(SEI)對服務進行調用。
a. 動态代理執行個體擴充了java.lang.reflect.Proxy類并利用了以JRE5的動态代理功能為基礎。
在運作時環境動态建立代表了SEI的java對象時,動态代理用戶端可以提供建立動态代理執行個體的接口。
b.調用方式:使用invoke方法對requests和responses的同步調用;
使用invokeAsync方法和一個回調(callback)對象或者一個輪詢(polling)對象對requests和responses進行異步調用;
使用invokeOneWay方法進行單向調用。
7.異步調用JAX-WS webservice服務
(1)使用回調(callback)異步調用模型:用戶端提供了一個AsyncHandler對象來接收和處理入站響應對象。用戶端回調處理程式實作了javax.xml.ws.AsynchHandler接口,
該接口包含了在收到來自服務端的異步響應時需要執行的應用程式代碼。在運作時環境收到并處理來自服務端的異步響應之後,javax.xml.ws.AsynchHandler接口中的
handleResponse(java.xml.ws.Response)方法會被調用。響應以javax.xml.ws.Response對象的形式傳遞給回調處理程式。調用Response對象的get()方法可得到響應的内容。
此外,如果收到一個錯誤,用戶端調用中會傳回一個異常。然後響應方法會根據執行器方法使用的線程模型進行調用, 這裡的執行器是指用來建立動态代理或排程用戶端執行個體的用戶端的
java.xml.ws.Service上的java.util.concurrent.Executor。該執行器用來執行任何被應用程式注冊的異步回調。使用setExecutor()和getExecutor()方法來修改和檢索服務配置的執行器。
(2)使用輪詢(polling)異步調用模型:使用輪詢模式,用戶端可以向服務端送出請求,随後收到響應對象,該響應對象能确認伺服器成功對請求作出響應。當伺服器響應時,實際響應可以被檢索,、
調用響應對象(Response)的get()方法可以傳回響應對象的内容。用戶端可以從invokeAsync方法那得到一個javax.xml.ws.Response類型的對象。該響應對象用于監視發送給伺服器請求的狀态,
确定當操作完成時,檢索響應的結果。
(3)使用異步消息交換:預設情況下,異步用戶端調用沒有線上的消息交換模式的行為。程式設計模型是異步的;然而與伺服器互動的請求或響應消息的交換不是異步的。
為了使用異步消息交換,用戶端請求上下文的org.apache.axis2.jaxws.use.async.mep屬性必須被設定成Boolean.Ture。當這個屬性可用,用戶端和伺服器之間的消息交換就不同于同步消息交換。
在異步消息交換下,請求和響應消息有WS-addressing頭部,這些頭部提供了消息的額外路由資訊。異步消息交換和同步消息交換的另一個主要差別是響應會被傳遞給
一個異步偵聽器,然後異步偵聽器傳回響應給用戶端。如果想強迫用戶端停止等待響應,可以通過輪詢(polling)調用傳回的對象調用Response.cancel()方法或者通過回調(callback)調用傳回的對象調用Future.cancel()方法。
取消的響應不影響正在處理一個請求的伺服器。
(4)異步調用web service的步驟:
a.确定你想要實作的回調方法或用戶端異步輪詢方法調用Web服務。
b.(可選)配置用戶端請求上下文。添加org.apache.axis2.jaxws.use.async.mep屬性到請求上下文來啟用web services用戶端的異步消息。
使用該屬性要求服務端點支援WS-addressing(應用程式伺服器預設支援)。示例:
Map<String, Object> rc = ((BindingProvider) port).getRequestContext();
rc.put("org.apache.axis2.jaxws.use.async.mep", Boolean.TRUE);
c.實作異步回調(callback)方法,執行以下步驟:
i.在SEI或javax.xml.ws.Dispatch接口找到異步回調方法。對于SEI,方法名以Async結束,并有比javax.xml.ws.AsyncHandler類型的同步方法多的一個以上的參數。
invokeAsync(Object, AsyncHandler)方法是在Dispatch接口使用。
ii.(可選)向用戶端應用程式添加service.setExecutor方法。添加執行器方法給了用戶端對處理響應的排程方法的控制。
你也可以使用java.current.Executors類工廠獲得打包的執行器或者實作你自己的執行器類。
iii.實作javax.xml.ws.AsynchHandler接口。該接口隻有一個handleResponse(javax.xml.ws.Response)方法,該方法必須包含處理響應或者一個異常的邏輯。
用戶端在運作時收到和處理來自伺服器的異步響應時,該方法會被調用。
iiii.利用參數資料和回調處理handler調用異步回調方法。
iiiii.當響應可用時handleResponse(Response)方法會調用作用在回調對象上。在該方法調用裡面提供響應時,Response.get()方法會被調用。
d.實作輪詢(polling)的方法:
i.在SEI或javax.xml.ws.Dispatch接口找到異步輪詢方法。對于SEI,方法名以Async結束,并有一個javax.xml.ws.Response的傳回類型。
invokeAsync(Object)方法用在Dispatch接口。
ii.利用參數資料調用異步輪詢方法。
iii.用戶端接收對象類型javax.xml.ws.Response,這個對象用于監聽發送到伺服器請求的狀态。isDone()方法表示是否調用完成。
當isDone()方法傳回true,調用get()方法可檢索到響應對象。
e. 如果用戶端需要停止等待服務的響應可以使用回調方法或者輪詢方法的cancel()進行取消。
如果cancel()被調用,端點繼續處理請求。然而,用戶端的等待和響應處理被停止。
-->下面的例子說明了一個有用戶端異步請求方法的web services接口:
@WebService
public interface CreditRatingService {
// Synchronous operation.
Score getCreditScore(Customer customer);
// Asynchronous operation with polling.
Response<Score> getCreditScoreAsync(Customer customer);
// Asynchronous operation with callback.
Future<?> getQuoteAsync(Customer customer,AsyncHandler<Score> handler);
}
-->使用回調(callback)方法需要一個回調處理器(handler)。當回調方法請求之後,回調處理器負責對響應進行處理,響應的值有可能是響應對象或者一個異常。
Future<?>表示一個異步計算及檢查異步計算是否完成的結果,調用Future.isDone()可檢查請求是否完成。
請注意Future.get()不提供一個有意義的響應,且和Response.get()方法不同。如下示例:
CreditRatingService svc = ...;
Future<?> invocation = svc.getCreditScoreAsync(customerTom,
new AsyncHandler<Score>() {
public void handleResponse (
Response<Score> response)
{
score = response.get();
// process the request...
}
}
);
-->下面的示例說明了一個使用異步輪詢方法的用戶端:
CreditRatingService svc = ...;
Response<Score> response = svc.getCreditScoreAsync(customerTom);
while (!response.isDone()) {
// Do something while we wait.
}
score = response.get();
8.在JAX-WS web服務中使用處理程式(handlers):
(1)相對于基于xml的RPC的Java API(jax-rpc)程式設計模型,jax-ws的程式設計模型提供了一個應用程式處理器工具,可以使你操作處理出入站消息流。
你可以添加處理程式到你的JAX-WS運作時環境中去對請求和響應消息做附加的處理。您可以使用各種各樣的處理程式達到捕獲和列印日志資訊和添加資訊安全或其他資訊等目的。
因為支援除SOAP之外多個附加協定,JAX-WS提供了兩種不同分類的處理程式(handlers)。
a.一種類型的處理程式是一個協定獨立的并可獲得流消息作為可擴充标記語言(XML)消息的邏輯處理器(logic handler)。
邏輯處理程式操作消息上下文屬性和消息有效負載。這些處理器必須實作javax.xml.ws.handler.LogicalHandler接口。
一個邏輯處理器接收一個LogicalMessageContext對象以獲得消息資訊。邏輯處理器在SOAP和基于XML/HTTP協定的應用程式中都可以配置。
b.另一種處理程式是一個協定處理器(protocal handler)。協定處理程式操作消息上下文屬性和特定于協定的消息。
協定處理程式是有限的,它基于soap配置且必須實作javax.xml.ws.handler.soap.SOAPHandler接口。
協定處理器接收一個javax.xml.soap.SOAPMessage來閱讀消息資料。
(2)JAX-WS運作時沒有在伺服器端和用戶端對處理器類加以區分。當特定的處理器調用了handleMessage(MessageContext)方法或 handleFault(MessageContext)方法,
運作時不區分入站流或出站流。你必須為伺服器或用戶端配置處理器,并且在這些方法裡實作充分的邏輯以檢測目前消息入站或出站的方向。
(3)web services用戶端應用程式使用處理器必須在服務端點接口或者生成的服務類上添加@HandlerChain注解,并提供相關的處理程式鍊(handler chain)配置檔案。
@HandlerChain 注釋包含一個檔案屬性指向一個您建立的處理程式鍊配置檔案。對于Web服務用戶端應用程式,你還可以使用Binding API程式設計方式配置處理程式鍊。
使用預設實作或一個HandlerResolver的自定義的實作,程式設計式的修改handlerchain 類。
(4)web services伺服器應用程式使用處理器必須在服務端點接口或者端點實作類上添加@HandlerChain注解,并提供相關的處理程式鍊(handler chain)配置檔案。
配置伺服器的處理器隻需要在服務端點實作或者實作類上添加@HandlerChain注解。處理器類必須被包含在部署工件裡。
(5)客戶機和伺服器為實作處理程式使用 @HandlerChain注釋,必須指定一個處理程式的配置檔案的位置,可能會是一個檔案相對路徑或絕對URL。例如:
@HandlerChain(file="../../common/handlers/myhandlers.xml") 或 @HandlerChain(file="http://foo.com/myhandlers.xml")
(6)建立JAX-WS處理器程式(handler):
a.确定實作用戶端或伺服器處理程式。
i.使用處理程式解析器(handler resolver)的預設實作。運作時現在使用 @HandlerChain注釋和HandlerResolver類的預設實作建構處理程式鍊。
你可以從Binding中擷取現有的處理程式鍊,添加或删除處理器,然後将修改後的處理程式鍊傳回給Binding對象。
ii.使用處理程式解析器(handler resolver)的定制實作,需要對Service執行個體設定自定義HandlerResolver。在運作時使用HandlerRosolver類的自定義實作
建構處理程式鍊,且不使用預設的運作時實作。在這種情況下,當在自定義的HandlerResolver執行個體被注冊到Service執行個體後,從Binding中檢索處理程式鍊時,
@HandlerChain注解不會被讀取。你可以從Binding中擷取現有的處理程式鍊,添加或删除處理器,然後将修改後的處理程式鍊傳回給Binding對象。
b.配置用戶端處理程式可以通過在service執行個體或服務端點接口(SEI)上添加@HandlerChain注解,也可以通過程式設計式修改處理程式鍊來控制運作時如何建構處理程式鍊。
如果你選擇以程式設計式修改處理程式鍊,那麼你必須确定是否使用預設的處理程式解析器或使用已注冊到service執行個體上的處理程式解析器的自定義實作。
當建立binding providers時可以使用處理程式解析器。當binding providers建立好後,注冊到一個service上的處理程式解析器将會被用來建立處理程式鍊,
随後處理程式鍊将會被用于配置binding providers。
c.配置伺服器處理程式可以通過在服務端點接口或實作類上添加@HandlerChain注解。當@HandlerChain注解在服務端點接口和實作類上都配置了,那麼實作類優先。
d.建立處理程式鍊配置檔案(xml)。你必須建立一個處理程式鍊配置檔案供@HandlerChain參考。
e.當配置伺服器或用戶端處理程式(handlers)時使用@HandlerChain注解,需要将處理程式鍊配置XML檔案添加到服務端點接口所在的類路徑下。
你還必須在類路徑下的處理程式鍊配置檔案(XML)中包含處理程式類(handler classes)。
f.編寫處理程式實作。
(7)@HandlerChain注解有一個file屬性指向你建立的處理程式鍊配置檔案。配置檔案示例如下,protocol-bindings, port-name-pattern, and service-name-pattern元素
都是限制哪些services能夠使用這些處理程式的過濾器。
<?xml version="1.0" encoding="UTF-8"?>
<jws:handler-chains xmlns:jws="http://java.sun.com/xml/ns/javaee">
<!-- Note: The '*" denotes a wildcard. -->
<jws:handler-chain name="MyHandlerChain">
<jws:protocol-bindings>##SOAP11_HTTP ##ANOTHER_BINDING</jws:protocol-bindings>
<jws:port-name-pattern
xmlns:ns1="http://handlersample.samples.apache.org/">ns1:MySampl*</jws:port-name-pattern>
<jws:service-name-pattern
xmlns:ns1="http://handlersample.samples.apache.org/">ns1:*</jws:service-name-pattern>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleLogicalHandler</jws:handler-class>
</jws:handler>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleProtocolHandler2</jws:handler-class>
</jws:handler>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleLogicalHandler</jws:handler-class>
</jws:handler>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleProtocolHandler2</jws:handler-class>
</jws:handler>
</jws:handler-chain>
</jws:handler-chains>
以下示例說明了一個處理程式的實作:
package org.apache.samples.handlersample;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPMessageContext;
public class SampleProtocolHandler implements
javax.xml.ws.handler.soap.SOAPHandler<SOAPMessageContext> {
public void close(MessageContext messagecontext) {
}
public Set<QName> getHeaders() {
return null;
}
public boolean handleFault(SOAPMessageContext messagecontext) {
return true;
}
public boolean handleMessage(SOAPMessageContext messagecontext) {
Boolean outbound = (Boolean) messagecontext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outbound) {
// Include your steps for the outbound flow.
}
return true;
}
}
9.對JAX-WS應用程式啟用HTTP會話管理支援
使用HTTP會話管理以保持伺服器上的使用者的狀态資訊,同僚傳回極少的資訊給使用者以跟蹤會話。
你可以使用會話cookies或URL重寫實作應用程式伺服器上的HTTP會話管理。浏覽器、應用程式伺服器、應用之間的互動對使用者和應用程式來說是透明的。
應用程式和使用者通常不知道伺服器提供的會話辨別符。
(1)會話cookie
HTTP會話使用一個cookie和JSESSIONID維持會話功能,這個cookie包含會話辨別符。該cookie與對存儲在伺服器上會話資訊的請求相關聯。
從JAX-WS應用程式的後續請求中,會話ID會作為請求頭的一部分被傳送,這使得應用程式可以關聯來自該使用者之前的請求給定的會話ID相關的每一個請求。
JAX-WS用戶端應用程式可以從響應頭中檢索會話ID,然後通過在HTTP請求頭中設定會話ID,以在後續請求中使用這些會話ID。
(2)URL重寫
URL重寫類似重定向的URL工作因為它在URL中存儲了會話辨別符。會話辨別符被編碼作為從網頁送出的任何連結或形式的參數。
該編碼的URL用于後續的請求到同一伺服器。要啟用HTTP會話管理。
a.配置伺服器以啟用會話跟蹤。
b.啟用用戶端會話管理,可通過在BindingProvider上設定JAX-WS屬性javax.xml.ws.session.maintain的值為true。
Map<String, Object> rc = ((BindingProvider) port).getRequestContext();
...
...
rc.put(BindingProvider.SESSION_MAINTAIN_PROPERTY, Boolean.TRUE);
...
...
10.啟用MTOM(Message Transmission Optimization Mechanism)消息優化傳輸機制
JAX-WS支援使用SOAP消息優化傳輸機制即MTOM發送二進制附件資料。