43.3. 处理逻辑处理程序中的消息
概述
正常消息处理由 handleMessage ()
方法处理。
handleMessage ()
方法收到一个 LogicalMessageContext
对象,它提供对消息正文的访问以及消息上下文中存储的任何属性。
handleMessage ()
方法返回 true 或 false,具体取决于消息处理如何继续。它还可能会抛出异常。
获取消息数据
传递给逻辑消息处理程序的 LogicalMessageContext 对象允许使用上下文的 getMessage ()
方法访问消息正文。getMessage ()
方法(如 例 43.2 “在逻辑处理程序中获取消息有效负载的方法” 所示)将消息有效负载返回为 LogicalMessage 对象。
例 43.2. 在逻辑处理程序中获取消息有效负载的方法
LogicalMessage
getMessage
具有 LogicalMessage 对象后,您可以使用它来操作消息正文。例 43.3 “逻辑消息冻结器” 中显示的 LogicalMessage 接口具有 getters 和 setters,用于处理实际消息正文。
例 43.3. 逻辑消息冻结器
LogicalMessage
Source
getPayload
Object
getPayload
JAXBContext
context
setPayload
Object
payload
JAXBContext
context
setPayload
Source
payload
消息有效负载的内容由使用的绑定类型决定。SOAP 绑定只允许访问消息的 SOAP 正文。XML 绑定允许访问整个消息正文。
使用消息正文作为 XML 对象
逻辑消息的一对 getters 和 setters 使用消息有效负载作为 javax.xml.transform.dom.DOMSource
对象。
没有参数的 getPayload ()
方法将消息有效负载返回为 DOMSource
对象。返回的对象是实际消息有效负载。对返回对象所做的任何更改都会立即更改消息正文。
您可以使用采用单个 Source 对象的 setPayload ()
方法将消息的正文替换为 DOMSource
对象。
使用消息正文作为 JAXB 对象
通过另一对 getters 和 setters,您可以将消息有效负载用作 JAXB 对象。它们使用 JAXBContext
对象将消息有效负载转换为 JAXB 对象。
要使用 JAXB 对象,请执行以下操作:
获取
JAXBContext
对象,它可以管理消息正文中的数据类型。有关创建
JAXBContext
对象的详情,请参考 第 39 章 使用 AJAXBContext
对象。获取 例 43.4 “将消息正文作为 JAXB 对象获取” 中显示的消息正文。
例 43.4. 将消息正文作为 JAXB 对象获取
JAXBContext jaxbc = JAXBContext(myObjectFactory.class); Object body = message.getPayload(jaxbc);
- 将返回的对象转换为正确的类型。
- 根据需要操作消息正文。
将更新的消息正文重新置于上下文中,如 例 43.5 “使用 JAXB 对象更新消息正文” 所示。
例 43.5. 使用 JAXB 对象更新消息正文
message.setPayload(body, jaxbc);
使用上下文属性
传递给逻辑处理程序的逻辑消息上下文是应用的消息上下文的实例,可以访问它中存储的所有属性。处理程序有权访问应用范围和 HANDLER
范围中的属性。
与应用的消息上下文一样,逻辑消息上下文是 Java Map 的子类。要访问存储在上下文中的属性,您可以使用从 Map 接口继承的 get ()
方法和 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,则消息为 inbound。
确定返回值
handleMessage ()
方法如何完成其消息处理对消息处理的方式有直接影响。它可以通过执行以下操作之一完成:
-
将 true-Returning true 信号返回到消息处理应该继续正常运行的 Apache CXF 运行时。下一个处理程序(若有)调用了其
handleMessage ()
。 将 false-Returning false 信号返回到正常消息处理必须停止的 Apache CXF 运行时。运行时的继续取决于用于 当前消息 的消息交换模式。
对于请求响应消息交换,会出现以下情况:
消息处理的方向被撤销。
例如,如果某个请求由服务提供商处理,消息将停止进入服务的实施对象。相反,它会发回到绑定,以返回到源自请求的消费者。
-
在新处理方向中驻留在处理程序链的任何消息处理程序都按照它们位于链中的顺序调用其
handleMessage ()
方法。 当消息到达处理程序链的末尾时,会被分配。
对于单向消息交换会出现以下情况:
- 消息处理将停止。
-
所有之前调用的消息处理程序都具有其
close ()
方法调用。 - 消息被分配。
抛出一个 ProtocolException 异常-Throwing a ProtocolException 异常或这个例外的子类,向 Apache CXF 运行时发送错误消息处理。运行时的继续取决于用于 当前消息 的消息交换模式。
对于请求响应消息交换,会出现以下情况:
- 如果处理程序尚未创建 fault 消息,则运行时会将消息嵌套在出错消息中。
消息处理的方向被撤销。
例如,如果某个请求由服务提供商处理,消息将停止进入服务的实施对象。相反,它会发回到绑定,以返回到源自请求的消费者。
-
在新处理方向中驻留在处理程序链的任何消息处理程序都按照它们位于链中的顺序调用其
handleFault ()
方法。 当故障消息到达处理程序链的末尾时,它将被分配。
对于单向消息交换会出现以下情况:
- 如果处理程序尚未创建 fault 消息,则运行时会将消息嵌套在出错消息中。
- 消息处理将停止。
-
所有之前调用的消息处理程序都具有其
close ()
方法调用。 - 已分配 fault 消息。
-
抛出任何其他运行时异常-浏览除 ProtocolException 异常之外的运行时异常,信号了消息处理要停止的 Apache CXF 运行时。所有之前调用的消息处理程序都有一个
close ()
方法,并分配异常。如果消息是请求响应消息交换的一部分,则会分配异常,使其返回到源自请求的消费者。
Example
例 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 以停止消息处理,并将响应返回给客户端。
如果消息不是正确的类型,则抛出运行时异常。
此例外返回给客户端。
如果消息是入站响应或 sum 没有达到阈值,则返回 true。
消息处理通常继续。
如果遇到 JAXB marshalling 错误,则抛出 ProtocolException。
异常通过当前处理程序和客户端之间的处理程序的 handleFault
() 方法处理后传递给客户端。