43.3. 在逻辑处理程序中处理消息

概述

普通消息处理由 handleMessage () 方法处理。

handleMessage () 方法收到 LogicalMessageContext 对象,它提供对消息正文的访问和消息上下文中存储的任何属性。

根据消息处理方式,handleMessage () 方法返回 true 或 false。它还可能会抛出异常。

获取消息数据

传递到逻辑消息处理程序的 LogicalMessageContext 对象允许使用上下文的 getMessage () 方法访问消息正文。getMessage () 方法(如 例 43.2 “在逻辑处理程序中获得消息 Payload 的方法” )将消息有效负载返回为 LogicalMessage 对象。

例 43.2. 在逻辑处理程序中获得消息 Payload 的方法

LogicalMessagegetMessage

具有 LogicalMessage 对象后,就可以使用它来操作消息正文。LogicalMessage 接口显示在 例 43.3 “逻辑消息冻结” 中,具有用于实际消息正文的 getters 和 setters。

例 43.3. 逻辑消息冻结

LogicalMessageSourcegetPayloadObjectgetPayloadJAXBContext上下文setPayloadObjectpayloadJAXBContext上下文setPayloadSourcepayload

重要

消息有效负载的内容由使用中的绑定类型决定。SOAP 绑定只允许访问消息的 SOAP 正文。XML 绑定允许访问整个邮件正文。

将消息正文用作 XML 对象

其中一个对 getters 和 setter of the logical message of the message payload 一起用于 javax.xml.transform.dom.DOMSource 对象。

没有参数的 getPayload () 方法将消息有效负载返回为 DOMSource 对象。返回的对象是实际消息有效负载。对返回对象所做的任何更改都会立即更改消息正文。

您可以使用采用单一 Source 对象的 setPayload () 方法将消息的正文替换为 DOMSource 对象。

将消息正文用作 JAXB 对象

其他对 getters 和 setters 允许您将消息有效负载用作 JAXB 对象。它们使用 JAXBContext 对象将消息有效负载转换为 JAXB 对象。

要使用 JAXB 对象,请执行以下操作:

  1. 获取一个可在消息正文中管理数据类型的 JAXBContext 对象。

    有关创建 JAXBContext 对象的详情,请参考 第 39 章 使用 A JAXBContext 对象

  2. 获取消息正文,如 例 43.4 “获取消息正文作为 JAXB 对象” 所示。

    例 43.4. 获取消息正文作为 JAXB 对象

    JAXBContext jaxbc = JAXBContext(myObjectFactory.class);
    Object body = message.getPayload(jaxbc);
  3. 将返回的对象转换为正确的类型。
  4. 根据需要操作消息正文。
  5. 将更新的消息正文重新置于上下文中,如 例 43.5 “使用 JAXB 对象更新消息正文” 所示。

    例 43.5. 使用 JAXB 对象更新消息正文

    message.setPayload(body, jaxbc);

使用上下文属性

传递到逻辑处理程序的逻辑消息上下文是应用消息上下文的实例,并可访问其中存储的所有属性。处理程序可以访问 APPLICATION 范围和 HANDLER 范围中的属性。

与应用的消息上下文一样,逻辑消息上下文是 Java map 的子类。若要访问上下文中存储的属性,您可以使用 get () 方法和从 Map 接口继承的 put () 方法。

默认情况下,您在逻辑处理程序内在消息上下文中设置的任何属性都会被分配为 HANDLER 范围。如果您希望应用程序代码能够访问所需的属性,您需要使用上下文的 setScope () 方法显式将属性的范围设置为 APPLICATION。

有关在消息上下文中使用属性的更多信息,请参阅 第 42.1 节 “了解上下文”

确定消息的方向

知道消息通过处理程序链的方向通常非常重要。例如,您要从传入请求检索安全令牌,并将安全令牌附加到传出响应。

消息的方向存储在消息上下文的出站消息属性中。您可以使用 MessageContext.MESSAGE_OUTBOUND_PROPERTY 键从消息上下文检索出站消息属性,如 例 43.6 “从 SOAP 消息上下文获取消息的方向” 所示。

例 43.6. 从 SOAP 消息上下文获取消息的方向

Boolean outbound;
outbound = (Boolean)smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

该属性存储为 布尔值 对象。您可以使用对象的 booleanValue () 方法来确定属性的值。如果属性设为 true,则消息是出站。如果属性设为 false,则消息为入站。

确定返回值

handleMessage () 方法完成其消息处理对消息处理方式具有直接影响。它可以通过以下操作之一完成:

  1. 返回 true-Returning true 信号到消息处理应继续的 Apache CXF 运行时。下一个处理程序(若有)已调用了其 handleMessage ()
  2. 将 false-Returning false 信号返回到普通消息处理必须停止的 Apache CXF 运行时。运行时的执行方式取决于用于 当前消息 的消息交换模式。

    对于请求响应的消息会交换以下情况:

    1. 消息处理的方向将被逆向。

      例如,如果某个请求由服务提供商处理,消息将停止提升到服务的实施对象。相反,它会被发回给该绑定,以返回源自请求的使用者。

    2. 在新的处理方向中驻留在处理程序链的任何消息处理程序都会以它们驻留在链中的顺序调用其 handleMessage () 方法。
    3. 当消息到达处理程序链的末尾时,它将被分配。

      对于单向消息交换以下情况:

    4. 消息处理将停止。
    5. 所有之前调用的消息处理程序都具有其 close () 方法调用。
    6. 邮件被发送。
  3. 引发协议Exception 异常异常或此异常的子类,以信号开始消息处理的 Apache CXF 运行时。运行时的执行方式取决于用于 当前消息 的消息交换模式。

    对于请求响应的消息会交换以下情况:

    1. 如果处理程序尚未创建错误消息,则运行时会将消息嵌套在容错消息中。
    2. 消息处理的方向将被逆向。

      例如,如果某个请求由服务提供商处理,消息将停止提升到服务的实施对象。相反,它会被发回给该绑定,以返回源自请求的使用者。

    3. 在新的处理方向中驻留在处理程序链的任何消息处理程序都会以它们驻留在链中的顺序调用其 handleFault () 方法。
    4. 当故障消息到达处理程序链的末尾时,它将被分配。

      对于单向消息交换以下情况:

    5. 如果处理程序尚未创建错误消息,则运行时会将消息嵌套在容错消息中。
    6. 消息处理将停止。
    7. 所有之前调用的消息处理程序都具有其 close () 方法调用。
    8. 将发送错误信息。
  4. 抛出任何其他运行时异常 - 除 ProtocolException 以外的运行时异常会信号消息处理是停止的 Apache CXF 运行时。所有之前调用的消息处理程序都有调用 close () 方法,并且发送异常。如果消息是请求响应的消息交换的一部分,则发送异常,使其返回到源自请求的消费者。

示例

例 43.7 “逻辑消息处理程序消息处理” 为服务消费者使用的逻辑消息处理程序显示 handleMessage () 消息的实现。在向服务提供商发送请求前,它会处理请求。

例 43.7. 逻辑消息处理程序消息处理

public class SmallNumberHandler implements LogicalHandler<LogicalMessageContext>
{
    public final boolean handleMessage(LogicalMessageContext messageContext)
    {
        try
        {
            boolean outbound = (Boolean)messageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

            if (outbound)
            {
                LogicalMessage msg = messageContext.getMessage();

                JAXBContext jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
                Object payload = msg.getPayload(jaxbContext);
                if (payload instanceof JAXBElement)
                {
                    payload = ((JAXBElement)payload).getValue();
                }

                if (payload instanceof AddNumbers)
                {
                    AddNumbers req = (AddNumbers)payload;

                    int a = req.getArg0();
                    int b = req.getArg1();
                    int answer = a + b;

                    if (answer < 20)
                    {
                      AddNumbersResponse resp = new AddNumbersResponse();
                      resp.setReturn(answer);
                      msg.setPayload(new ObjectFactory().createAddNumbersResponse(resp),
                                                      jaxbContext);

                      return false;
                    }
                }
                else
                {
                   throw new WebServiceException("Bad Request");
                }
            }
            return true;
        }
        catch (JAXBException ex)
        {
            throw new ProtocolException(ex);
        }
    }
...
}

例 43.7 “逻辑消息处理程序消息处理” 中的代码执行以下操作:

检查消息是否为出站请求。

如果消息是出站请求,处理程序执行其他消息处理。

从消息上下文获取消息有效负载的 LogicalMessage 表示。

获取实际消息有效负载作为 JAXB 对象。

检查以确保请求是正确的类型。

如果是,处理程序将继续处理消息。

检查 sum 的值。

如果小于 20 的阈值,则构建响应并将其返回到客户端。

构建响应。

返回 false 以停止消息处理,并将响应返回给客户端。

如果消息不是正确的类型,则抛出运行时异常。

这个例外返回给客户端。

如果消息是入站响应,则返回 true,或者 sum 不满足阈值。

消息处理通常会继续。

如果遇到 JAXB marshalling 错误,则引发 ProtocolException。

异常在由当前处理程序和客户端之间的处理程序的 handleFault () 方法处理后返回给客户端。