JMS 传输和 SOAP 消息处理程序

使用 JMS 传输作为连接协议

通常情况下,客户端应用程序在调用 WebLogic Web Service 时使用 HTTP/S 作为连接协议。但是,您可以对 WebLogic Web Service 进行配置,以便客户端应用程序可以改用 JMS 作为传输。请按照后面部分中的描述使用 JWS 批注或 jwsc Ant 任务的子元素配置传输。

将 WebLogic Web Service 配置为使用 JMS 进行连接传输时,为 Web Service 的已生成 WSDL 中的对应端口指定的端点地址在其 URL 中使用 jms:// 而不是 http://。下面是 JMS 端点地址的示例:

jms://myHost:7001/transports/JMSTransport?URI=JMSTransportQueue

URL 的 URI=JMSTransportQueue 部分指定已经为 JMS 传输功能配置的 JMS 队列。虽然无法使用 HTTP 调用 Web Service,但可以使用 HTTP 查看它的 WSDL,这就是 clientgen 为什么仍旧能够为 Web Service 生成 JAX-RPC 存根控件。

对于您指定的每个传输,WebLogic Server 都会在 WSDL 中生成一个附加端口。因此,如果要为客户端应用程序提供传输选项以供它们在调用 Web Service 时使用(JMS、HTTP 或 HTTPS),应使用适当的 JWS 批注或 jwsc 的子元素明确添加传输。

警告: 使用 JMS 传输是 WebLogic 功能的一项增值之处。非 WebLogic 客户端应用程序(如 a.NET 客户端)可能无法使用 JMS 端口调用 Web Service。

使用 JMS 传输:主要步骤

以下过程描述如何指定可使用 JMS 传输调用 Web Service。

它假设您已经创建了一个实现 Web Service 的基本 JWS 文件,并且您想要配置该 Web Service 以使用 JMS 对其进行调用。它还假设您设置了一个基于 Ant 的开发环境并且您有一个有效的 build.xml 文件,该文件包括用于运行 jwsc Ant 任务和部署服务的目标。有关详细信息,请参阅 WebLogic Web Service 的迭代开发 和 JWS 文件编程。

  1. 为所需 JMS 组件配置 WebLogic Server 域。

您可以自己配置这些资源,也可以使用 Configuration Wizard 通过 Web Service 特定扩展模板来扩展 WebLogic Server 域。使用 Configuration Wizard 可以大大简化所需的配置步骤;有关详细信息,请参阅配置域的 Web Service 功能。

但是,如果您喜欢自己配置资源,请执行下列步骤:

  1. 在浏览器中调用管理控制台,如调用管理控制台中所述。
  2. 使用管理控制台创建并配置下列 JMS 组件(如果它们尚不存在):
  • JMS 服务器。请参阅创建 JMS 服务器
  • JMS 模块,定位到上一个 JMS 服务器。请参阅创建 JMS 模块
  • JMS 队列,包含在上一个 JMS 模块中。您可以指定 WebLogic Web Service 在默认情况下监听的 JMS 队列的 JNDI 名称 (weblogic.wsee.DefaultQueue),也可以指定其他名称。如果指定其他 JNDI 名称,则可以以后将该名称传递到 Web Service 本身。配置队列时,请确保您指定的此 JMS 队列为本地队列,通常通过设置本地 JNDI 名称进行指定。请参阅创建队列

除了 JMS 队列的 JNDI 名称以外,还可以用任何所需的名称命名其他组件。

将  @WLJmsTransport 批注添加到 JWS 文件中。

请参阅使用 @WLJmsTransport JWS 批注。

如果要替代在上一步指定的文件中的 JMS 端口,可以选择将   子元素添加到  jwsc Ant 任务。

有关详细信息,请参阅使用 jwsc Ant 任务的 子元素。

通过在调用  jwsc 任务的  build.xml Ant 文件中重新运行目标来重新生成 Web Service。

例如,如果调用 jwsc Ant 任务的目标名为 build-service,则要运行:

prompt> ant build-service
将 Web Service 重新部署到 WebLogic Server。

有关更新客户端应用程序以使用 JMS 传输调用 Web Service 的信息,请参阅使用 JMS 传输调用 WebLogic Web Service。

使用 @WLJmsTransport JWS 批注

如果您在为 JWS 文件编程时知道您希望客户端应用程序使用 JMS 传输(而不是 HTTP/S)调用 Web Service,可以使用 @WLJmsTransport 指定调用的详细信息。以后在生成时,可以通过指定 jwsc Ant 任务的  子元素(如使用 jwsc Ant 任务的 子元素中所述)来替代 JWS 文件中的批注并添加其他 JMS 传输规范。

使用 @WLJmsTranport 批注时,请遵循下列原则:

  • 只能在 JWS 文件中包括一个 @WLJmsTransport 批注。
  • 如果指定 @WLJmsTransport 批注,则不能同时指定 @WLHttpTransport
  • 使用 queue 特性指定之前在本部分中配置的 JMS 队列的 JNDI 名称。如果要使用默认的 Web Service 队列 (weblogic.wsee.DefaultQueue),则不必指定 queue 特性。

以下示例显示了一个使用 @WLJmsTransport 批注的简单 JWS 文件,相关代码以粗体显示:

package examples.webservices.jmstransport;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import weblogic.jws.WLJmsTransport;
@WebService(name="JMSTransportPortType",
serviceName="JMSTransportService",
targetNamespace="http://example.org")
@SOAPBinding(style=SOAPBinding.Style.DOCUMENT,
use=SOAPBinding.Use.LITERAL,
parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)
// WebLogic 特定的 JWS 批注,用于指定生成 Web Service 
// 的 URI 所使用的上下文路径和服务 URI 为
// “transports/JMSTransport”
@WLJmsTransport(contextPath="transports", serviceUri="JMSTransport",
queue="JMSTransportQueue", portName="JMSTransportServicePort")
/**
* 此 JWS 文件形成了带有下列单个操作的简单 Java 类实现的 WebLogic
* Web Service 的基础:sayHello
*
* @作者版权所有 (c) 2005,BEA Systems。保留所有权利。
*/
public class JMSTransportImpl {
  @WebMethod()
public String sayHello(String message) {
System.out.println("sayHello:" + message);
return "Here is the message: '" + message + "'";
}
}

使用 jwsc Ant 任务的 子元素

您也可以在生成时使用 jwsc Ant 任务的  元素的  子元素指定 JMS 传输。在生成时指定传输的原因包括:

  • 需要替代在 JWS 文件中指定的特性值。
  • JWS 文件指定不同的传输,并且在生成时决定该传输应该是 JMS。
  • JWS 文件不包括 @WLXXXTransport 批注;因此,默认情况下会使用 HTTP 传输,但您在生成时确定希望客户端使用 JMS 传输调用 Web Service。

如果为 jwsc Ant 任务指定一种传输,则该传输优先于 JWS 文件中的任何传输批注。

以下示例说明如何为 jwsc Ant 任务指定传输:

  
          srcdir="src"
destdir="${ear-dir}">
                        contextPath="transports" 
serviceUri="JMSTransport"
portName="JMSTransportServicePort"
queue="JMSTransportQueue"/>
      
    
  

上面的示例说明如何将在使用 @WLJmsTransport JWS 批注中显示的 JWS 文件中指定的值指定给 URL 和 JMS 队列。

有关使用 jwsc Ant 任务的详细信息,请参阅 jwsc。

使用 JMS 传输调用 WebLogic Web Service

可编写客户端应用程序以使用 JMS 传输调用 Web Service,方式与编写使用 HTTP 传输的客户端应用程序一样。唯一区别是:必须确保已经创建了 JMS 队列(由 @WLJmsTransport 批注或 jwsc 任务的 子元素指定)和其他 JMS 对象。有关详细信息,请参阅使用 JMS 传输:主要步骤。

虽然无法使用 HTTP 调用 JMS 传输配置的 Web Service,但可以使用 HTTP 查看它的 WSDL,因此 clientgen Ant 任务仍旧能够为 Web Service 创建 JAX-RPC 存根控件。例如,此部分中显示的 Web Service 的 WSDL 的 URL 将会是:

http://host:port/transports/JMSTransport?WSDL

但是,因为已部署的 Web Service 的 WSDL 中的端点地址使用 jms:// 而不是 http://,并且该地址包括限定符 ?URI=JMS_QUEUE,所以 clientgen Ant 任务会在调用 Web Service 时自动创建使用 JMS 传输所需的存根控件,并且客户端应用程序不需要执行不同于平常的操作。下面是 JMS 端点地址的示例:

jms://host:port/transports/JMSTransport?URI=JMSTransportQueue
警告: 如果您已经指定使用 JMS 传输调用的 Web Service 还在事务上下文中运行(也就是说,JWS 文件包括 @weblogic.jws.Transactional 批注),必须在调用该服务时使用异步请求响应。如果不这样,将会发生死锁,并且调用将会失败。

有关调用 Web Service 的常规信息,请参阅调用 Web Service。

替代默认服务地址 URL

如果编写的客户端应用程序使用 clientgen 生成的 JAX-RPC 存根控件调用 Web Service,则 Web Service 的默认服务地址 URL 是在 Service 构造方法的 WSDL 文件参数的 

 元素中指定的 URL。

但是,有时可能需要替代该地址,尤其是在调用的 WebLogic Web Service 部署到某个群集并且您想要指定群集地址或群集中受管服务器的地址列表时。可能还需要使用 t3 协议调用 Web Service。要在使用 JMS 传输时替代此服务端点 URL,请使用 weblogic.wsee.jaxrpc.WLStub.JMS_TRANSPORT_JNDI_URL 存根控件属性,如以下示例所示:

package examples.webservices.jmstransport.client;
import weblogic.wsee.jaxrpc.WLStub;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.Stub;
/**
* 这是一个简单的独立客户端应用程序,用以调用
* JMSTransport Web service 中的 sayHello 操作。
*
* @作者版权所有 (c) 2004,BEA Systems。保留所有权利。
*/
public class Main {
  public static void main(String[] args)
throws ServiceException, RemoteException{
    JMSTransportService service = new JMSTransportService_Impl(args[0] + "?WSDL" );
JMSTransportPortType port = service.getJMSTransportServicePort();
    Stub stub = (Stub) port;
    stub._setProperty(WLStub.JMS_TRANSPORT_JNDI_URL,
"t3://shackell01.amer.bea.com:7001");
try {
String result = null;
      result = port.sayHello("Hi there!");
      System.out.println( "Got JMS result: " + result );
    } catch (RemoteException e) {
throw e;
}
}
}

有关其他存根控件属性的参考文档,请参阅 WLStub

使用 JMS BytesMessage 而不是默认的 TextMessage

使用 JMS 传输时,Web Service 运行时默认使用 javax.jms.TextMessage 对象发送该消息。对于大多数客户端应用程序,这通常足够了,但有时可能需要发送二进制数据而不是普通文本,在这种情况下,必须请求 Web Service 运行时改用 javax.jms.BytesMessage。要这样做,请使用客户端应用程序中的 WLStub.JMS_TRANSPORT_MESSAGE_TYPE 存根控件属性并将它的值设置为WLStub.JMS_BYTESMESSAGE,如以下示例所示:

    stub._setProperty(WLStub.JMS_TRANSPORT_MESSAGE_TYPE,
WLStub.JMS_BYTESMESSAGE);

Web Service 运行时会使用与请求相同的消息数据类型传回响应。

有关可在其中设置此属性的客户端应用程序的完整示例,请参阅替代默认服务地址 URL。有关其他存根控件属性的参考文档,请参阅 WLStub。

禁用对 WSDL 文件进行 HTTP 访问

如 使用 JMS 传输调用 WebLogic Web Service 中所述,默认情况下,部署的 Web Service 的 WSDL 仍可使用 HTTP 进行访问。如果要禁用对 WSDL 文件进行访问,特别是禁用从防火墙外访问 Web Service,则您可以执行下列操作之一:

  • 在 JWS 文件中使用 weblogic.jws.WSDL 批注,以编程方式禁用访问。有关详细信息,请参阅 weblogic.jws.WSDL。
  • 在部署 Web Service 之后,使用管理控制台禁用对 WSDL 文件进行访问。在这种情况下,配置信息将存储在部署计划而不是整个批注中。

要使用管理控制台执行此任务,请转至部署的 Web Service 的“配置”->“常规”页,取消选中“查看动态 WSDL 已启用”复选框。将配置保存到部署计划后,您必须重新部署(更新) Web Service 或包含它的企业应用程序,以使所做的更改生效。

 


创建和使用 SOAP 消息处理程序

有些 Web Service 需要访问 SOAP 消息,对于 SOAP 消息,可为其创建 SOAP 消息处理程序。

SOAP 消息处理程序提供在 Web Service 的请求和响应中截获 SOAP 消息的机制。您可以同时在 Web Service 本身或调用该 Web Service 的客户端应用程序中创建处理程序。

访问 SOAP 消息头部分中的信息就是使用处理程序的简单示例。您可以使用 SOAP 头存储 Web Service 特定的信息,然后使用处理程序操作它。

也可以使用 SOAP 消息处理程序提高 Web Service 的性能。在将 Web Service 部署了一段时间后,您可能会发现许多使用者使用相同的参数来调用它。通过缓存 Web Service 的常见调用的结果(假设结果是静态的)并在适当时立即返回这些结果(而不需要先调用实现 Web Service 的后端组件),可以提高 Web Service 的性能。通过使用处理程序检查请求 SOAP 消息以查看其中是否包含常见参数,可以实现此性能改进。

下表列出了可在 JWS 文件中用于指定配置了处理程序链的 Web Service 的 JWS 批注;后面的部分更加详细地讨论如何使用这些批注。有关其他信息,请参阅 Web Services MetaData for the Java Platform (JSR-181) specification。

表 7-1 用于配置 SOAP 消息处理程序链的 JWS 批注
JWS 批注
描述
javax.jws.HandlerChain
将 Web Service 与在外部定义的处理程序链相关联。当多个 Web Service 需要共享同一处理程序配置时,或者如果处理程序链包含多个传输的处理程序,请使用此批注(而不是  @SOAPMessageHandlers)。
javax.jws.soap.SOAPMessageHandlers
指定在调用每个 Web Service 操作前后运行的 SOAP 处理程序的列表。如果首选在 JWS 文件本身中嵌入处理程序配置信息,而不是获取外部配置文件,请使用此批注(而不是  @HanderChain)。
@SOAPMessageHandler 批注是  @SOAPMessageHandlers 的数组。处理程序按它们在此数组中的列出顺序执行。
javax.jws.soap.SOAPMessageHandler
在  @SOAPMessageHandlers 数组中指定一个 SOAP 消息处理程序。

 

下表描述 javax.xml.rpc.handler API 的主要类和接口,其中一些可在创建处理程序本身时使用。后面的部分详细讨论了这些 API。有关这些 API 的其他信息,请参阅 JAX-RPC 1.1 specification

表 7-2 JAX-RPC 处理程序接口和类
javax.xml.rpc.handler 类和接口
描述
Handler
创建处理程序时实现的主接口。包含用于处理 SOAP 请求、响应和错误的方法。
GenericHandler
实现  Handler 接口的抽象类。用户应该在创建处理程序时扩展此类,而不是直接实现  Handler
GenericHandler 类是便于编写处理程序的便利抽象类。此类提供生命周期方法 init 和 destroy 及不同的处理方法的默认实现。处理程序开发人员只有在需要将方法限定为派生处理程序实现类的一部分时,才可对其进行替代。
HandlerChain
表示处理程序的列表的接口。 HandlerChain 接口的实现类将用于调用已注册处理程序的策略和机制抽象化。
HandlerRegistry
为 HandlerRegistry 中处理程序的编程配置提供支持的接口。
HandlerInfo
包含处理程序链中处理程序的相关信息的类。 HandlerInfo 实例在  Handler.init 方法中传递以初始化  Handler 实例。
MessageContext
将处理程序处理的消息上下文抽象化。 MessageContext 属性允许处理程序链中的处理程序共享处理状态。
soap.SOAPMessageContext
用于处理或更新 SOAP 消息的 MessageContext 接口的子接口。
javax.xml.soap.SOAPMessage
包含实际请求或响应 SOAP 消息(包括它的头、正文和附件)的对象。

 

将 SOAP 消息处理程序添加到 Web Service:主要步骤

以下过程描述用于将 SOAP 消息处理程序添加到 Web Service 的高级步骤。

它假设您已经创建了一个实现某 Web Service 的基本 JWS 文件,并且您想要通过添加 SOAP 消息处理程序和处理程序链来更新该 Web Service。它还假设您设置了一个基于 Ant 的开发环境并且您有一个有效的 build.xml 文件,该文件包括用于运行 jwsc Ant 任务的目标。有关详细信息,请参阅 WebLogic Web Service 的迭代开发 和 JWS 文件编程。

  1. 设计处理程序和处理程序链。

请参阅设计 SOAP 消息处理程序和处理程序链。

对于处理程序链中的每个处理程序,创建可扩展  javax.xml.rpc.handler.GenericHandler 抽象类的 Java 类。

请参阅创建 GenericHandler 类。

更新 JWS 文件,添加批注以配置 SOAP 消息处理程序。

请参阅在 JWS 文件中配置处理程序。

如果要在 JWS 文件中使用  @HandlerChain 标准批注,请创建处理程序链配置文件。

请参阅创建处理程序链配置文件。

编译处理程序链中的所有处理程序类并重新生成 Web Service。

请参阅编译和重新生成 Web Service 。

有关创建客户端 SOAP 消息处理程序和处理程序链的信息,请参阅创建并使用客户端 SOAP 消息处理程序。

设计 SOAP 消息处理程序和处理程序链

设计 SOAP 消息处理程序和处理程序链时,必须确定:

  • 执行所有工作需要的处理程序的数量
  • 执行序列

处理程序链中的每个处理程序都有一个用于处理请求 SOAP 消息的方法和一个用于处理响应 SOAP 消息的方法。一组有序处理程序被称为“处理程序链”。请指定某 Web Service 上附加有一个处理程序链,而该处理程序链使用以下两个 JWS 批注之一附加到其上:@HandlerChain 或 @SOAPMessageHandler。后面的部分讨论何时使用哪个批注。

调用 Web Service 时,WebLogic Server 按照如下方式执行处理程序:

  1. 处理程序链中的处理程序的 handleRequest() 方法全部按 JWS 批注指定的顺序执行。这些 handleRequest() 方法中任何一个都可能会更改 SOAP 消息请求。
  2. 当处理程序链中最后一个处理程序的 handleRequest() 方法执行时,WebLogic Server 会调用实现 Web Service 的后端组件,并向它传递最终 SOAP 消息请求。
  3. 当后端组件执行完以后,处理程序链中处理程序的 handleResponse() 方法会按 JWS 批注指定的反向顺序执行。这些 handleResponse() 方法中任何一个都可能会更改 SOAP 消息响应。
  4. 当处理程序链中第一个处理程序的 handleResponse() 方法执行时,WebLogic Server 会将最终 SOAP 消息响应返回给调用 Web Service 的客户端应用程序。

例如,假设您要在 JWS 文件中使用 @HandlerChain JWS 批注指定外部配置文件,并且该配置文件定义一个名为 SimpleChain 的处理程序链(该程序链包含三个处理程序),如以下示例所示:

   xmlns:soap1="http://HandlerInfo.org/Server1"
xmlns:soap2="http://HandlerInfo.org/Server2"
xmlns="http://java.sun.com/xml/ns/j2ee" >
   
     SimpleChain
     
handlerOne
examples.webservices.soap_handlers.global_handler.ServerHandler1
     
handlerTwo
examples.webservices.soap_handlers.global_handler.ServerHandler2
     
handlerThree
examples.webservices.soap_handlers.global_handler.ServerHandler3
   
 
  

下图显示 WebLogic Server 执行每个处理程序的 handleRequest() 和 handleResponse() 方法的顺序。

图 7-1 处理方法0 的执行顺序

 

每个 SOAP 消息处理程序都有一个单独的方法来处理请求和响应 SOAP 消息,原因是:对于入站和出站消息,通常必须进行相同类型的处理。例如,可以设计一种加密处理程序,其 handleRequest() 方法为 SOAP 请求中的安全数据解密,handleResponse() 方法为 SOAP 响应加密。

但是,可以设计只处理 SOAP 请求而不对响应进行等同处理的处理程序。

也可以选择不调用处理程序链中的下一个处理程序,并随时向客户端应用程序发送即时响应。

创建 GenericHandler 类

SOAP 消息处理程序类应该扩展 javax.rpc.xml.handler.GenericHandler 抽象类,而该抽象类本身实现 javax.rpc.xml.handler.Handler 接口。

GenericHandler 类是便于编写处理程序的便利抽象类。该类提供生命周期方法 init() 和 destroy() 以及 Handler 接口的各种 handleXXX() 方法的默认实现。编写处理程序类时,只替代需要作为Handler 实现类的一部分自定义的那些方法。

尤其是,处理程序接口包含下列可在扩展 GenericHandler 的处理程序类中实现的方法:

  • init()

请参阅实现 Handler.init() 方法。

destroy()

请参阅实现 Handler.destroy() 方法。

getHeaders()

请参阅实现 Handler.getHeaders() 方法。

handleRequest()

请参阅实现 Handler.handleRequest() 方法。

handleResponse()

请参阅实现 Handler.handleResponse() 方法。

handleFault()

请参阅实现 Handler.handleFault() 方法。

有时,可能需要从处理程序中直接查看或更新 SOAP 消息,尤其是在处理附件(如图像)时。在这种情况下,请使用 javax.xml.soap.SOAPMessage 抽象类,该类是 SOAP With Attachments API for Java 1.1 (SAAJ) 规范的一部分。有关详细信息,请参阅使用 SAAJ 直接操作 SOAP 请求和响应消息。

以下示例说明了一个简单的 SOAP 消息处理程序,该处理程序将 SOAP 请求和响应消息输出到 WebLogic Server 日志文件中:

package examples.webservices.soap_handlers.global_handler;
import javax.xml.namespace.QName;
import javax.xml.rpc.handler.HandlerInfo;
import javax.xml.rpc.handler.GenericHandler;
import javax.xml.rpc.handler.MessageContext;
import javax.xml.rpc.handler.soap.SOAPMessageContext;
import javax.xml.rpc.JAXRPCException;
import weblogic.logging.NonCatalogLogger;
/**
* 此类实现处理程序链内的某个处理程序,用于访问 SOAP
* 请求及响应消息。
*


* 在实现 Web Service 本身的后端
* Java 类处理消息之前,此类将扩展 javax.xml.rpc.handler.GenericHandler
* 抽象类,并只将 SOAP 请求和响应消息输出到
* 服务器日志文件。
*/

public class ServerHandler1 extends GenericHandler {
  private NonCatalogLogger log;
  private HandlerInfo handlerInfo;
  /**
* 初始化处理程序实例。创建 nonCatalogLogger
* 以记录消息。
*/
  public void init(HandlerInfo hi) {
    log = new NonCatalogLogger("WebService-LogHandler");
handlerInfo = hi;
  }
  /**
* 指定在将消息发送至实现 Web Service 的 Java 类之前,
* 将 SOAP 请求消息记录到日志文件。
*/
  public boolean handleRequest(MessageContext context) {
   SOAPMessageContext messageContext = (SOAPMessageContext) context;
   System.out.println("** Request: "+messageContext.getMessage().toString());
log.info(messageContext.getMessage().toString());
return true;
  }
  /**
* 指定在将消息发送回至
*调用 Web Service 的客户端应用程序之前,
* 将 SOAP 响应消息记录到日志文件。
*/
  public boolean handleResponse(MessageContext context) {
    SOAPMessageContext messageContext = (SOAPMessageContext) context;
    System.out.println("** Response: "+messageContext.getMessage().toString());
log.info(messageContext.getMessage().toString());
return true;
  }
  /**
* 指定在处理程序实例引发 SOAP 错误的情况下,
*将消息记录到日志文件。
*/
  public boolean handleFault(MessageContext context) {
   SOAPMessageContext messageContext = (SOAPMessageContext) context;
   System.out.println("** Fault: "+messageContext.getMessage().toString());
log.info(messageContext.getMessage().toString());
return true;
  }
  public QName[] getHeaders() {
    return handlerInfo.getHeaders();
  }
}

实现 Handler.init() 方法

调用 Handler.init() 方法可创建 Handler 对象的实例并启用该实例以将它本身初始化。它的签名是:

  public void init(HandlerInfo config) throws JAXRPCException {}

HandlerInfo 对象包含 SOAP 消息处理程序的相关信息,尤其是初始化参数。使用 HandlerInfo.getHandlerConfig() 方法可获取这些参数;该方法返回包含名称-值对的 java.util.Map 对象。

如果需要处理初始化参数,或者如果有其他初始化任务需要执行,请实现 init() 方法。

初始化参数的示例用法有:打开或关闭调试,指定要在其中写入消息或错误的日志文件的名称,等等。

实现 Handler.destroy() 方法

调用 Handler.destroy() 方法可破坏 Handler 对象的实例。它的签名是:

  public void destroy() throws JAXRPCException {}

实现 destroy() 方法可释放在处理程序的整个生命周期获取的所有资源。

实现 Handler.getHeaders() 方法

Handler.getHeaders() 方法获取可由此 Handler 实例处理的头块。它的签名是:

  public QName[] getHeaders() {}

实现 Handler.handleRequest() 方法

调用 Handler.handleRequest() 方法可在后端组件处理 SOAP 消息请求前将其截获。它的签名是:

  public boolean handleRequest(MessageContext mc) 
throws JAXRPCException,SOAPFaultException {}

实现此方法可执行一些任务,如在后端组件处理 SOAP 消息前将其中的数据解密,等等。

MessageContext 对象将 SOAP 消息处理程序处理的消息上下文抽象化。MessageContext 属性允许处理程序链中的处理程序共享处理状态。

使用 MessageContext 的 SOAPMessageContext 子接口可处理或更新 SOAP 消息请求的内容。SOAP 消息请求本身存储在 javax.xml.soap.SOAPMessage 对象中。有关此对象的详细信息,请参阅使用 SAAJ 直接操作 SOAP 请求和响应消息。

SOAPMessageContext 类定义了两种用于处理 SOAP 请求的方法:

  • SOAPMessageContext.getMessage() 返回包含 SOAP 消息请求的 javax.xml.soap.SOAPMessage 对象。
  • SOAPMessageContext.setMessage(javax.xml.soap.SOAPMessage) 在您更改它之后更新 SOAP 消息请求。

在为 SOAP 请求的所有处理编码之后,请为以下场景之一编码:

  • 通过返回 true 调用处理程序请求链中的下一个处理程序。

对于请求链中的下一个处理程序,在 @HandlerChain 批注指定的配置文件中将其指定为  元素的下一个  子元素,或在 @SOAPMessageHandlers 批注指定的数组中将其指定为下一个 @SOAPMessageHandler。如果链中没有其他处理程序,则该方法或者调用后端组件,将最终 SOAP 消息请求传递给它,或者调用最后一个处理程序的 handleResponse() 方法,具体取决于配置 Web Service 的方式。

通过返回  false 阻塞处理程序请求链的处理。

阻塞处理程序请求链处理意味着,不会因为 Web Service 的此调用而执行后端组件。如果已经缓存了 Web Service 的某些调用的结果并且当前调用在列表中,则可能需要这样做。

虽然处理程序请求链不会继续处理,但 WebLogic Server 确实会调用处理程序响应链(从当前处理程序开始)。例如,假设处理程序链包括两个处理程序:handlerA 和 handlerB,其中 handlerA 的handleRequest() 方法在 handlerB 的该方法之前被调用。如果处理在 handlerA 中受到阻塞(因此,不会调用 handlerB 的 handleRequest() 方法),处理程序响应链会在 handlerA 处开始,并且不会调用 handlerB 的 handleRequest() 方法。

引发  javax.xml.rpc.soap.SOAPFaultException 以指示 SOAP 错误。

如果 handleRequest() 方法引发 SOAPFaultException,WebLogic Server 会捕获该异常,终止处理程序请求链的进一步处理,并调用此处理程序的 handleFault() 方法。

由于任何处理程序特定的运行时错误而引发  JAXRPCException

如果 handleRequest() 方法引发 JAXRPCException,WebLogic Server 会捕获该异常,终止处理程序请求链的进一步处理,将该异常记录到 WebLogic Server 日志文件中,并调用此处理程序的handleFault() 方法。

实现 Handler.handleResponse() 方法

调用 Handler.handleResponse() 方法可在后端组件处理 SOAP 消息响应后,但将其传回到调用 Web Service 的客户端应用程序前将其截获。它的签名是:

  public boolean handleResponse(MessageContext mc) throws JAXRPCException {}

实现此方法可执行一些任务,如在将 SOAP 消息传回到客户端应用程序前将其中的数据解密以便进一步处理返回值,等等。

MessageContext 对象将 SOAP 消息处理程序处理的消息上下文抽象化。MessageContext 属性允许处理程序链中的处理程序共享处理状态。

使用 MessageContext 的 SOAPMessageContext 子接口可处理或更新 SOAP 消息响应的内容。SOAP 消息响应本身存储在 javax.xml.soap.SOAPMessage 对象中。请参阅使用 SAAJ 直接操作 SOAP 请求和响应消息。

SOAPMessageContext 类定义了两种用于处理 SOAP 响应的方法:

  • SOAPMessageContext.getMessage():返回包含 SOAP 消息响应的 javax.xml.soap.SOAPMessage 对象。
  • SOAPMessageContext.setMessage(javax.xml.soap.SOAPMessage):在您更改它之后更新 SOAP 消息响应。

在为 SOAP 响应的所有处理编码之后,请为以下场景之一编码:

  • 通过返回 true 调用处理程序响应链中的下一个处理程序。

对于处理程序链中的下一个响应,在 @HandlerChain 批注指定的配置文件中将其指定为  元素的上一个  子元素,或在 @SOAPMessageHandlers 批注指定的数组中将其指定为上一个 @SOAPMessageHandler。(请记住,处理程序链中的响应按在 JWS 文件中指定它们的反向顺序执行。有关详细信息,请参阅设计 SOAP 消息处理程序和处理程序链。)

如果链中没有其他处理程序,则该方法会将最终 SOAP 消息响应发送到调用 Web Service 的客户端应用程序。

通过返回  false 阻塞处理程序响应链的处理。

阻塞处理程序响应链处理意味着,不会因为 Web Service 的此调用而执行响应链中的其余处理程序,并且会将当前 SOAP 消息传回到客户端应用程序。

由于任何处理程序特定的运行时错误引发  JAXRPCException

如果 handleRequest() 方法引发 JAXRPCException,WebLogic Server 会捕获该异常,终止处理程序请求链的进一步处理,将该异常记录到 WebLogic Server 日志文件中,并调用此处理程序的handleFault() 方法。

实现 Handler.handleFault() 方法

Handler.handleFault() 方法根据 SOAP 消息处理模式处理 SOAP 错误。它的签名是:

    public boolean handleFault(MessageContext mc) throws JAXRPCException  {}

实现此方法可处理由 handleResponse() 和 handleRequest() 方法生成的任何 SOAP 错误以及由后端组件生成的错误。

MessageContext 对象将 SOAP 消息处理程序处理的消息上下文抽象化。MessageContext 属性允许处理程序链中的处理程序共享处理状态。

使用 MessageContext 的 SOAPMessageContext 子接口可处理或更新 SOAP 消息的内容。SOAP 消息本身存储在 javax.xml.soap.SOAPMessage 对象中。请参阅使用 SAAJ 直接操作 SOAP 请求和响应消息。

SOAPMessageContext 类定义了下面两种用于处理 SOAP 消息的方法:

  • SOAPMessageContext.getMessage():返回包含 SOAP 消息的 javax.xml.soap.SOAPMessage 对象。
  • SOAPMessageContext.setMessage(javax.xml.soap.SOAPMessage):在您更改它之后更新 SOAP 消息。

在为 SOAP 错误的所有处理编码之后,请为以下场景之一编码:

  • 通过返回 true 调用处理程序链中下一个处理程序的 handleFault() 方法。
  • 通过返回 false 阻塞处理程序错误链的处理。

使用 SAAJ 直接操作 SOAP 请求和响应消息

javax.xml.soap.SOAPMessage 抽象类是 SOAP With Attachments API for Java 1.1 (SAAJ) 规范的一部分。创建 SOAP 消息处理程序时,使用该类可操作请求和响应 SOAP 消息。本部分描述SOAPMessage 对象的基本结构以及可用于查看和更新 SOAP 消息的一些方法。

SOAPMessage 对象包含 SOAPPart 对象(该对象包含实际的 SOAP XML 文档)以及零个或多个附件。

有关 SOAPMessage 类的完整描述,请参阅 SAAJ Javadocs。有关 SAAJ 的详细信息,请转至 http://java.sun.com/xml/saaj/index.html

SOAPPart 对象

SOAPPart 对象在 SOAPEnvelope 对象内包含 XML SOAP 文档。使用此对象可获取实际的 SOAP 头和正文。

以下示例 Java 代码说明如何从 Handler 类提供的 MessageContext 对象检索 SOAP 消息并处理它的各部分:

SOAPMessage soapMessage =  messageContext.getMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
SOAPBody soapBody = soapEnvelope.getBody();
SOAPHeader soapHeader = soapEnvelope.getHeader();
AttachmentPart 对象

javax.xml.soap.AttachmentPart 对象包含 SOAP 消息的可选附件。不同于 SOAP 消息的其余部分,附件不需要是 XML 格式,因此,可以是任何格式(从简单文本到图像文件)。

警告: 如果您要从 SOAP 消息处理程序访问 java.awt.Image 附件,请参阅在 SOAP 消息处理程序中操作图像附件以获取重要信息。

使用 SOAPMessage 类的下列方法可操作附件:

  • countAttachments():返回此 SOAP 消息中的附件数。
  • getAttachments():将所有附件(作为 AttachmentPart 对象)检索到 Iterator 对象中。
  • createAttachmentPart():从另一类 Object 创建 AttachmentPart 对象。
  • addAttachmentPart():创建 AttachmentPart 对象后将其添加到 SOAPMessage
在 SOAP 消息处理程序中操作图像附件

本部分假设您要创建访问 java.awt.Image 附件的 SOAP 消息处理程序,并且已从使用 clientgen Ant 任务生成的客户端 JAX-RPC 存根控件的客户端应用程序发送了 Image

在 clientgen Ant 任务生成的客户端代码中,会使用 MIME 类型的 text/xml 而不是 image/gif 将 java.awt.Image 附件发送到所调用的 WebLogic Web Service,并且会将图像序列化为表示图形的整数流。尤其是,客户端代码会使用以下格式序列化图像:

  • int width
  • int height
  • int[] pixels

这意味着,在操作所收到的图像附件的 SOAP 消息处理程序中,必须取消此数据流的序列化,然后重新创建原始图像。

在 JWS 文件中配置处理程序

有两种标准批注可在 JWS 文件中用于为 Web Service 配置处理程序链:@javax.jws.HandlerChain 和 @javax.jws.soap.SOAPMessageHandlers

@javax.jws.HandlerChain

使用 @javax.jws.HandlerChain 批注(为了简便,也称为 @HandlerChain)时,使用 file 特性可指定包含要与 Web Service 关联的处理程序链的配置的外部文件。配置包括链中处理程序的列表、它们的执行顺序、初始化参数等。

如果符合以下一种或多种条件,请在 JWS 文件中使用 @HandlerChain 批注而不是 @SOAPMessageHandlers 批注:

  • 希望多个 Web Service 共享同一个配置。
  • 处理程序链包括用于多个传输的处理程序。
  • 希望能够更改 Web Service 的处理程序链配置,且不重新编译实现它的 JWS 文件。

以下 JWS 文件所示为 @HandlerChain 批注的使用示例;相关 Java 代码以粗体显示:

package examples.webservices.soap_handlers.global_handler;
import java.io.Serializable;
import javax.jws.HandlerChain;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.soap.SOAPBinding;
import weblogic.jws.WLHttpTransport;
@WebService(serviceName="HandlerChainService",
name="HandlerChainPortType")
// 标准 JWS 批注,指定每次调用 Web Service 
// 操作时,应引发 HandlerConfig.xml 文件
// 中配置的称为“SimpleChain”的处理程序链。
@HandlerChain(file="HandlerConfig.xml", name="SimpleChain")
@SOAPBinding(style=SOAPBinding.Style.DOCUMENT,
use=SOAPBinding.Use.LITERAL,
parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)
@WLHttpTransport(contextPath="HandlerChain", serviceUri="HandlerChain",
portName="HandlerChainServicePort")
/**
* 此 JWS 文件形成了带有下列单个操作的简单 Java 类实现的 WebLogic
* Web Service 的基础:sayHello。如 @HandlerChain 批注所指定,
*Web Service 也
* 有一个与之相关联的处理程序链。
*


* @作者版权所有 (c) 2005,BEA Systems, Inc. 保留所有权利。
*/

public class HandlerChainImpl  {
   public String sayHello(String input) {
weblogic.utils.Debug.say( "in backend component. input:" +input );
return "'" + input + "' to you too!";
}
}

因为使用 @HandlerChain 批注,所以必须将它导入到 JWS 文件中,如上一个示例所示。

使用 @HandlerChain 批注的 file 特性可指定包含处理程序链的配置信息的外部文件的名称。此特性的值是 URL(可以是相对的,也可以是绝对的)。相对 URL 相对于运行 jwsc Ant 任务以编译 JWS 文件时该文件的位置。

使用 name 特性可指定配置文件中要与 Web Service 相关联的处理程序链的名称。此特性的值对应于该配置文件中  元素的 name 特性。

警告: 在单个 JWS 文件中指定多于一个的 @HandlerChain 批注,是错误的。将 @HandlerChain 批注与 @SOAPMessageHandlers 批注组合也是错误的。

有关创建外部配置文件的详细信息,请参阅创建处理程序链配置文件。

有关本部分中讨论的标准 JWS 批注的其他详细信息,请参阅 Web Services Metadata for the Java Platform specification

@javax.jws.soap.SOAPMessageHandlers

如果使用 @javax.jws.soap.SOAPMessageHandlers(为了简便,在本部分中也称为 @SOAPMessageHandlers)批注,可在 JWS 文件本身中指定在 Web Service 操作的前后执行的一系列 SOAP 消息处理程序(使用 @SOAPMessageHandler 批注指定)。 @SOAPMessageHandler 批注包括一些特性,用于指定处理程序的类名、初始化参数、处理程序处理的 SOAP 头的列表,等等。因为在 JWS 文件本身中指定处理程序列表,所以处理程序链的配置嵌入在 Web Service 中。

如果符合以下一个或多个条件,请使用 @SOAPMessageHandlers 批注:

  • 希望将处理程序链的配置嵌入到 Web Service 本身内,而不是在外部文件中指定该配置。
  • 处理程序链只包括 SOAP 处理程序,而不包括任何其他传输的处理程序。
  • 希望每次更改处理程序链配置时都重新编译 JWS 文件。

以下 JWS 文件所示为 @SOAPMessageHandlers 批注的简单使用示例;相关 Java 代码以粗体显示:

package examples.webservices.soap_handlers.simple;
import java.io.Serializable;
import javax.jws.soap.SOAPMessageHandlers;
import javax.jws.soap.SOAPMessageHandler;
import javax.jws.soap.SOAPBinding;
import javax.jws.WebService;
import javax.jws.WebMethod;
import weblogic.jws.WLHttpTransport;
@WebService(name="SimpleChainPortType",  
serviceName="SimpleChainService")
// 标准 JWS 批注,指定 SOAP 消息处理程序列表,
// 该消息处理程序在调用
// Web Service 中的所有操作前后执行。
@SOAPMessageHandlers ( {
@SOAPMessageHandler (
className="examples.webservices.soap_handlers.simple.ServerHandler1"),
@SOAPMessageHandler (
className="examples.webservices.soap_handlers.simple.ServerHandler2")
} )
@SOAPBinding(style=SOAPBinding.Style.DOCUMENT,
use=SOAPBinding.Use.LITERAL,
parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)
@WLHttpTransport(contextPath="SimpleChain", serviceUri="SimpleChain",
portName="SimpleChainServicePort")
/**
* 此 JWS 文件形成了带有下列单个操作的简单 Java 类实现的 WebLogic
* Web Service 的基础:sayHello。如 @SOAPMessageHandler/s 批注所指定,
* Web Service 也有一个
* 与之相关联的处理程序链。
*


* @作者版权所有 (c) 2005,BEA Systems, Inc. 保留所有权利。
*/

public class SimpleChainImpl  {
   // 默认情况下,所有公共方法都作为操作公开
   public String sayHello(String input)  {
weblogic.utils.Debug.say( "in backend component. input:" +input );
return "'" + input + "' to you too!";
}
}

在使用 @SOAPMessageHandlers 和 @SOAPMessageHandler 批注之前,必须将它们导入到 JWS 文件中,如上一个示例所示。请注意,这些批注在 javax.jws.soap 包中。

在 @SOAPMessageHandlers 数组中列出处理程序的顺序(使用 @SOAPMessageHandler 批注)指定处理程序的执行顺序:在操作前以正向顺序执行,在操作后以反向顺序执行。上一个示例在处理程序链中配置两个处理程序,其类名为 examples.webservices.soap_handlers.simple.ServerHandler1 和 examples.webservices.soap_handlers.simple.ServerHandler2

使用 @SOAPMessageHandler 的 initParams 特性可指定某特定处理程序需要的一系列初始化参数。使用 @InitParam 标准 JWS 批注可指定名称/值对,如以下示例所示:

@SOAPMessageHandler(
className = "examples.webservices.soap_handlers.simple.ServerHandler1",
initParams = { @InitParam(name="logCategory", value="MyService")}
)

@SOAPMessageHandler 批注还包括用于列出由处理程序实现的 SOAP 角色的 roles 特性,以及用于列出由处理程序处理的 SOAP 头的 headers 特性。

警告: 将 @SOAPMessageHandlers 批注与 @HandlerChain 批注组合是错误的。

有关本部分中讨论的标准 JWS 批注的其他详细信息,请参阅 Web Services Metadata for the Java Platform specification

创建处理程序链配置文件

如果决定在 JWS 文件中使用 @HandlerChain 批注将处理程序链与 Web Service 相关联,必须创建外部配置文件,以指定处理程序链中处理程序的列表、它们的执行顺序、初始化参数,等等。

因为此文件在 JWS 文件外部,所以可以将多个 Web Service 配置为使用这一个配置文件,以将企业中所有 Web Service 的处理程序配置文件标准化。此外,可以更改处理程序链的配置,且不需要重新编译所有 Web Service。最后,如果在处理程序链中包括使用非 SOAP 传输的处理程序,则需要使用 @HandlerChain 批注而不是 @SOAPMessageHandler 批注。

该配置文件使用 XML 列出一个或多个处理程序链,如以下简单示例所示:

   xmlns:soap1="http://HandlerInfo.org/Server1"
xmlns:soap2="http://HandlerInfo.org/Server2"
xmlns="http://java.sun.com/xml/ns/j2ee" >

SimpleChain

handler1
examples.webservices.soap_handlers.global_handler.ServerHandler1


handler2
examples.webservices.soap_handlers.global_handler.ServerHandler2


在该示例中,名为 SimpleChain 的处理程序链包含两个处理程序:handler1 和 handler2,这两个处理程序使用在  元素中指定的类名实现。这两个处理程序在相关 Web Service 操作执行之前以正向顺序执行,在该操作执行之后以反向顺序执行。

使用  元素的  和  子元素分别指定处理程序初始化参数、处理程序实现的 SOAP 角色和处理程序处理的 SOAP 头。

如需定义外部配置文件的 XML Schema、有关创建它的其他信息,以及其他示例,请参阅 Web Services Metadata for the Java Platform specification

编译和重新生成 Web Service

本部分假设您有一个有效的 build.xml Ant 文件(该文件编译并生成 Web Service),并且您想要更新该构建文件以包括在处理程序链中。有关创建此 build.xml 文件的信息,请参阅 WebLogic Web Service 的迭代开发。

要更新开发环境以使其包括消息处理程序编译和生成功能,请遵循以下原则:

  • 使用 @HandlerChain 或 @SOAPMessageHandlers 批注更新 JWS 文件后,必须重新运行 jwsc Ant 任务以重新编译 JWS 文件并生成新的 Web Service。只要在 JWS 文件中更改批注,就要这样。

如果在 JWS 文件中使用 @HandlerChain 批注,之后重新运行 jwsc Ant 任务来重新生成 Web Service,然后又只更改了外部配置文件,则不需要重新运行 jwsc,第二次更改即可生效。

如果满足以下所有条件, jwsc Ant 任务会将 SOAP 消息处理程序 Java 文件编译为处理程序类(然后,将它们打包到所生成的应用程序中):
  • JWS 文件的 @HandlerChain 或 @SOAPMessageHandler(s) 批注中引用了处理程序类。
  • Java 文件位于由 sourcepath 特性指定的目录中。
  • 类当前未在 CLASSPATH 中。

如果您要亲自编译处理程序类,而不是让 jwsc 自动编译它们,请先确保所编译的类在 CLASSPATH 中,然后再运行 jwsc Ant 任务。

您部署并调用具有相关联的处理程序链的 Web Service,方式与部署和调用没有处理程序链的 Web Service 的方式相同。唯一区别是:当调用 Web Service 的任何操作时,WebLogic Web Service 运行时都会在操作调用前后执行处理程序链中的处理程序。

摘自http://www.oraclefmw.com/wls92/webserv/advanced2.html

你可能感兴趣的:(java)