Apache Camel中从CXF组件获取HTTP响应码的正确方式

作者:技术拾光时间:2026-07-12 08:10:01浏览:461

在ApacheCamel的CXF组件POJO模式下,HTTP响应码CamelHttpResponseCode不在消息头,而在消息体Map中,需通过${in.body[CamelHttpResponseCode]}获取。onCompletion()是获取响应码的稳妥方式,且需注意声明位置。

在使用 Apache Camel 的 CXF 组件调用 WebService 时,您是否遇到过想要获取 HTTP 响应码却总是无法获取的情况?一个常见的误区是:许多开发者习惯性地去 in.headers 中查找 CamelHttpResponseCode,结果发现它始终为空。实际上,该值并不存在于那里。

首先需要明确一个核心问题:在 Apache Camel 中使用 CXF 组件(默认 POJO 模式)时,CamelHttpResponseCode 并不位于 in.headers 中,而是作为消息体(Message Body)的属性存在。正确的访问方式应为 ${in.body[CamelHttpResponseCode]},而非 ${in.header.CamelHttpResponseCode}。

Apache Camel中从CXF组件获取HTTP响应码的正确方式

为何会出现这种情况?这源于 CXF 组件的处理机制。默认情况下,它采用 POJO 模式(DataFormat.POJO)处理 SOAP 请求与响应,底层通过 CXF 的本地 JVM 调用进行,而非直接连接 HTTP 传输层。因此,HTTP 状态码(如 200、500)并非标准 HTTP 响应头的一部分。Camel 在封装响应时,由 CXF Transport 或 Camel 的 CxfEndpoint 自动将其注入到 Exchange 的 in.body 属性映射中,键名即为 CamelHttpResponseCode。

这意味着:
正确访问方式为 ${in.body[CamelHttpResponseCode]}(即从 Message.getBody(Map.class) 中取值);
${in.header.CamelHttpResponseCode} 始终为空,因为该值从未写入 headers。

推荐实践:使用 onCompletion() 获取响应码

onCompletion() 会在路由完成(包括所有后续 .to() 处理)之后触发,此时 Exchange 已完整承载响应数据,是获取响应码的最稳妥方式:

from(cxf("/test")        .wsdlURL("wsdl/wsdl.wsdl")        .serviceClass("org.tempuri.Class")        .dataFormat(DataFormat.POJO)        .advanced().schemaValidationEnabled(true))    .to("direct:route")    .onCompletion()        .log("${in.header.operationName} - ${in.body[CamelHttpResponseCode]}");

注意:onCompletion() 必须置于 .to(...) 之后。若放在 from(...) 后立即声明,它会在请求发出后、响应尚未返回前就执行,导致 CamelHttpResponseCode 尚未注入,日志输出为 null 或空字符串。

调试小技巧:验证响应码是否存在

如果不确定响应结构,可在路由中插入一个临时处理器,直接查看实际内容:

.process(exchange -> {    Object body = exchange.getIn().getBody();    Map, ?> bodyMap = body instanceof Map  (Map, ?>) body : Collections.emptyMap();    log.info("Response body keys: {}", bodyMap.keySet());    log.info("CamelHttpResponseCode = {}", bodyMap.get("CamelHttpResponseCode"));})

常见键还包括 CamelHttpResponseText(如 "OK")、CamelHttpUri、operationName(来自 WSDL 操作名)等,这些均可作为调试线索。

补充说明:何时能获取真实的 HTTP 状态码?

  • 如果使用 DataFormat.PAYLOAD 或 DataFormat.RAW,且底层启用了 HTTP Transport(例如 cxf:http://...),则可通过 Exchange.HTTP_RESPONSE_CODE header 获取真实状态码。但前提是必须配置 httpClientConfigurer 启用 HTTP 协议栈。
  • 但在 POJO 模式下,默认走的是 JVM 内部调用(local:// transport),此时 CamelHttpResponseCode 仅为 Camel 模拟的“逻辑状态码”,通常为 200(成功)或 500(CXF 抛出 Fault)。它并非原始 HTTP 连接的真实状态码,这一点需格外留意。

总结

场景获取方式说明
POJO 模式(默认)${in.body[CamelHttpResponseCode]}值由 Camel/CXF 注入到 body map,最可靠
Payload 模式 + HTTP Transport${in.header.Exchange.HTTP_RESPONSE_CODE}需显式配置 HTTP client,依赖网络层
日志中动态拼接${in.header.operationName} - ${in.body[CamelHttpResponseCode]:200}支持默认值 fallback(:200)避免 null

按照上述方式操作,即可稳定输出形如 sayHello - 200 的日志,精准反映服务调用结果的状态。