转载自:http://www.why100000.com/Htmls/tabProgram167.htm
Web services 是一种很有前途的技术,在面向服务的架构( Service Oriented Architectures , SOA ) 中起着重要的作用。这种正在兴起的技术的一个关键方面就是提供了异步服务的能力。尽管现在的 web service 标准规范中包括了提供异步服务的内 容,但客户端应用程序前景的细节还有一些混乱和模糊。 Web services 回调是实现这些异步服务的一个重要因素。这篇文章为创建带有回调操作 的 Web services 的客户应用程序提供了实践指导。这篇文章中所有的代码段都来自于您可以下载的例子。这些例子包含了这些代码段的完整实现和 使用指导。
创建支持回调的客户端
正如前面讨论的,支持回调的 Web services 客户端需要提供一个能够异步接收和处理回调操作消息的回调端点。为避免必须提供回调端点这类 复杂的事情,一种叫做 polling (轮询)的技术可以作为替代技术。然而这种技术要求客户端周期性地调用服务端以校验回调事件。如果这种事件很少发 生,那么调用的开销就太大了。如果客户端提供一个回调端点并直接处理回调操作,这种开销就可以避免。
我们还应该注意到,尽管可以通过用 JMS 上的 Web services (如果提供了这种连接)创建支持回调的客户端,但这种方法有一些限制, 其中一个重要的限制就是客户端要被迫采用与 Web services 提供者相同的 JMS 实现。因此我们将集中于经过 HTTP 传输来完成我们的 任务。有两个领域需要创建这样的客户端:创建适当的客户端启动 SOAP 消息,以及处理回调操作。
当客户端启动有回调的 Web service 操作时,它需要以某种方式包含回调端点的 URI ,使其在请求消息中监 听。 Web Services Addressing 和 SOAP Conversation Protocol 规范都定义了 SOAP 头部元 素,允许您实现这一目标。从理论上说,用于规定回调端点的规范并不重要。但是大多数 Web services 容器(包 括 BEA WebLogic Server 8.1 )都还没有包含 Web services Addressing 规范的实现形式。当 前, BEA WebLogic Workshop 8.1 的 Web services 支 持 SOAP Conversation Protocol 规范,我们将在例子客户端中使用。
根据 SOAP Conversation Protocol , SOAP 头部在会话的不同阶段是不同的。对于会话中的第一个客户端启动(开始) 操作,我们需要通过 callbackLocation 头部元素 提供有回调端点的 Web service 。所有操作(包括第一个操作)也将需要唯 一的 ID ,这个 ID 在整个会话过程中都用在我们的 SOAP 消息里。这可通过 conversationID 元素 来完成。下面是一个启动支 持回调会话的 SOAP 请求消息的例子:
〈soapenv:Envelope soapenv:encodingStyle=“http://schemas.xmlsoap.org/soap/encoding/“
xmlns:soapenv=“http://schemas.xmlsoap.org/soap/envelope/“
xmlns:xsd=“http://www.w3.org/2001/XMLSchema“
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance“
xmlns:enc=“http://schemas.xmlsoap.org/soap/encoding/“
xmlns:env=“http://schemas.xmlsoap.org/soap/envelop/“
xmlns:SOAP-ENC=“http://schemas.xmlsoap.org/soap/encoding/“〉
〈soapenv:Header〉
〈con:StartHeader soapenv:actor=“http://schemas.xmlsoap.org/soap/actor/next“
soapenv:mustUnderstand=“0“
xmlns:con=“http://www.openuri.org/2002/04/soap/conversation/“〉
〈con:conversationID〉[123456]:192.168.1.100:8181〈/con:conversationID〉
〈con:callbackLocation〉
http://192.168.1.100:8181/StockNotificationCallback
〈/con:callbackLocation〉
〈/con:StartHeader〉
〈/soapenv:Header〉
〈soapenv:Body〉
〈n1:registerForThresholdNotif xmlns:n1=“http://www.openuri.org/“〉
〈n1:stockTicker〉CCC〈/n1:stockTicker〉
〈n1:threshold〉10〈/n1:threshold〉
〈/n1:registerForThresholdNotif〉
〈/soapenv:Body〉
〈/soapenv:Envelope〉
现有的大多数 Java Web service 工具包(例 如 BEA WebLogic 的 clientgen 、 Apache Axis 和 JWSDP )都允许您创建一个代理库,客户端程序可以容易地 用它来调用 Web services 操作。但是,这些框架中没有一种支持回调操作,主要问题是它们的代理不生成所需的头部。在能提供这种支持以前,通 过扩展它们对回调操作的支持来利用这些框架(例如复杂类 XML 映射),这种益处还是很需要的。一种用来达到这种效果的技术就是应用 SOAP 消息处 理程序 。
上面提到的所有 Web services 工具包都能支持 SOAP 消息处理程序。消息处理程序是一种 Java 类,它实现 了 javax.xml.rpc.handler.GenericHandler 界面,并且还包含一种称为先送出(或后接收) SOAP 消息的方法。 这里介绍我们客户端中的消息处理程序,它能够找出一个特定会话的当前阶段,并据此扩展带有所需头部的请求消息。
注意到这一点是很重要的,客户端 SOAP 消息处理程序必须能确定消息属于会话的哪个阶段,以便创建合适的头部元素。生成会话 ID 也是客户端处理程序要完成的一个任务。
一旦 Web services 端点收到扩展的请求消息,它就会将请求消息发送到由开始消息的 callbackLocation 元素规定的回调 端点。在大多数情况下,客户端过程自身就需要提供这个端点,并且恰当地处理回调消息。如果客户端在 Web services 的容器中运行,这项工作就 可以通过把有回调操作的 Web services 部署在同一个容器内来完成。然而,如果客户端不是正在容器中运行,这项工作就要靠在一个嵌入在客户端 过程本身的轻量级容器中执行回调端点来完成。这使我们能够调用客户端生成的操作,并且处理同一过程上下文中的传入回调操作。注意在回调端点背后(和在客户 端中)的过程实体要求不仅能够分配对适当域的代码操作,而且还能处理 XML 映射。
当然,客户端也可以选择简单地设置恰当的 callbackLocation 头部元素来规定一个在容器中的回调端点,而这个容器与访问过程相分离。
正如我们已经看到的,为带回调操作的 Web services 创建客户端并不是毫无意义的,它包含了复杂元素,比如处理 SOAP 消息、管理会 话(包括阶段和 ID )、参数映射以及操作分配。当 Web service 通 过 BEA WebLogic Workshop Service Control 访问时,这些复杂性就都不存在了,它会自动为用户执行所有操作。