以异步方式调用 JAX-WS Web Service
Java™ API for XML-Based Web Services (JAX-WS) 支持使用异步客户机调用来调用 Web Service。 以异步方式调用 Web Service 时,JAX-WS 支持回调模型和轮询模型。回调模型和轮询模型在 Dispatch client 和 Dynamic proxy client 上可用。
开始之前
开发 JAX-WS Dynamic Proxy 或 Dispatch client。开发 Dynamic proxy client 时,在使用 wsimport 命令根据 Web Service 描述语言 (WSDL) 文件生成可移植客户机工件后,生成的服务端点接口 (SEI) 未将异步方法包括在此接口中。使用 JAX-WS 绑定在 Dynamic proxy client 的接口上添加异步回调或轮询方法。要启用异步映射,您可以将 jaxws:enableAsyncMapping 绑定声明添加至 WSDL 文件。有关添加绑定定制以生成异步接口的更多信息,请参阅 JAX-WS 规范第 8 章。

关于此任务
对 Web Service 的异步调用将请求发送至服务端点,然后立即将控制权返回给客户机程序,而不等待响应从服务返回。JAX-WS 异步 Web Service 客户机通过回调方法或轮询方法来使用 Web Service。通过使用轮询模型,客户机可以发出请求和接收所轮询的响应对象,以确定服务器是否响应。当服务器响应时,将检索到实际的响应。通过使用回调模型,客户机提供回调处理程序来接受和处理入站响应对象。当结果可用时,将调用处理程序的 handleResponse() 方法。轮询模型和回调模型都支持客户机集中于继续处理工作,而不等待响应返回,同时提供一个更动态和更有效的模型来调用 Web Service。从 Enterprise JavaBeans (EJB) 客户机或 Java Platform, Enterprise Edition (Java EE) 应用程序客户机轮询调用是有效的。只有从 Java EE 应用程序客户机进行回调调用时,回调调用才有效。
- 使用回调异步调用模型
- 为了实现使用回调模型的异步调用,客户机提供了 AsyncHandler 回调处理程序来接受和处理入站响应对象。客户机回调处理程序实现 javax.xml.ws.AsyncHandler 接口,该接口包含从服务器接收异步响应时运行的应用程序代码。javax.xml.ws.AsyncHandler 接口包含运行时从服务器接收到异步响应并对其进行处理后调用的 handleResponse(java.xml.ws.Response) 方法。以 javax.xml.ws.Response 对象的形式将响应传递给回调处理程序。当调用 get() 方法时,响应对象将返回响应内容。另外,如果接收到错误,那么在执行该调用期间,还将向客户机返回异常。随后根据 Executor 方法所使用的线程技术模型来调用 Response 方法,Executor 方法是客户机的 java.xml.ws.Service 实例上用于创建 Dynamic Proxy 或 Dispatch client 实例的 java.util.concurrent.Executor。Executor 用于调用由应用程序注册的任何异步回调。使用 setExecutor 和 getExecutor 方法来修改和检索对服务配置的 Executor。
- 使用轮询异步调用模型
- 通过使用轮询模型,客户机可以请求和接收响应对象,随后可以对该响应对象进行轮询以确定服务器是否已响应。当服务器响应时,将检索到实际的响应。当调用 get() 方法时,响应对象将返回响应内容。客户机从 invokeAsync 方法接收 javax.xml.ws.Response 类型的对象。该 Response 对象用于监视对服务器的请求的状态、确定操作的完成时间以及检索响应结果。
- 使用异步消息交换
- 缺省情况下,异步客户机调用在连线上没有消息交换模式的异步行为。编程模型是异步的,但是,与服务器交换请求或响应消息的过程不是异步的。要使用异步消息交换,必须在客户机请求上下文上将 com.ibm.websphere.webservices.use.async.mep 属性的布尔值设置为 true。启用此属性时,在客户机与服务器之间交换的消息有别于以同步方式交换的消息。借助异步交换,请求和响应消息添加了 WS-Addressing 头,以便为消息提供其他路由信息。异步消息交换与同步消息交换之间的另一重要差别是:响应传递至异步侦听器,然后异步侦听器将该响应传递回至客户机。对于异步交换,不会发送任何超时来通知客户机停止侦听响应。要强制客户机停止等待响应,请对从轮询调用返回的对象发出 Response.cancel() 方法或者对从回调调用返回的对象发出 Future.cancel() 方法。在处理请求时,cancelResponse 不会影响服务器。

<soapenv:Header>
<wsa:To>http://target.bar.com:81/LiteSecurityService/SecurityService</wsa:To>
<wsa:ReplyTo>
<wsa:Address>http://myhost:2146/axis2/services/LiteSecurityService.
WSRMServicePort/AnonOutInOp?IBMwebservicesID=922A5DC38A337C4CEF1168347862705
</wsa:Address>
</wsa:ReplyTo>
<wsa:MessageID>urn:uuid:922A5DC38A337C4CEF1168347862403</wsa:MessageID>
<wsa:Action>getEndpointReference</wsa:Action>
</soapenv:Header>
要解决此问题,请配置客户机,将以下系统属性添加到 Java 虚拟机,以便用 IP 格式来发送异步侦听器的位置详细信息。注意,如果传输 IP 地址,您将无法享受到 DHCP 所带来的好处。-Dcom.ibm.websphere.webservices.transportEPRInIPAddr=yes
gotcha过程
结果
示例
@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);
}
- 使用回调方法
- 回调方法需要回调处理程序,如以下示例所示。如果使用的是回调过程,那么在作出请求后,回调处理程序将负责处理响应。响应值是响应,也可能是异常。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();