如何在Apache Camel的RouteBuilder中获取Out Message?
问题分析与解决方案
你遇到的核心问题是:文件组件(File Component)的Producer行为是单向写入文件,不会等待路由后续的Webhook调用结果,所以producerTemplate.requestBody返回的只是你写入文件的原始JSON,而非Webhook的响应。
要解决这个问题,需要调整路由结构,使用支持请求-响应模式的端点作为主动调用的入口,同时保留文件读取的功能。
具体修改方案
1. 重构RouteBuilder,拆分路由逻辑
将主动调用和文件读取的逻辑分离,用direct端点作为同步调用的入口,文件路由复用该逻辑:
public class WebhookRouteBuilder extends RouteBuilder { @Override public void configure() throws Exception { // 同步调用入口:direct端点,支持请求-响应模式 from("direct:invoke-webhook") .log("Received message: ${body}") .process(new WebhookProcessor()) .log("Invoking webhook with headers: ${headers}") .log("Invoking webhook with body: ${body}") .toD("${header." + HTTP_URI + "}") .end(); // 文件读取路由:读取文件后转发到direct端点处理 final String messageSource = "/tmp/messages/webhook"; from(messageSource) .to("direct:invoke-webhook") .log("Webhook response for file ${header.CamelFileName}: ${body}") .end(); } // WebhookProcessor保持不变 protected class WebhookProcessor implements Processor { public void process(Exchange exchange) throws Exception { try { Message message = exchange.getIn(); JsonNode json = JacksonUtils.getObjectMapper().readTree(message.getBody(String.class)); message.setHeader(HTTP_URI, json.get("targetUrl").asText()); message.setHeader(HTTP_METHOD, "POST"); message.setHeader(HttpHeaders.CONTENT_TYPE, json.get("contentType").asText()); final String username = json.get("username").asText(); final String password = json.get("password").asText(); if (username != null && password != null) { String encodedAuth = Base64.getEncoder().encodeToString(String.format("%s:%s", username, password).getBytes(StandardCharsets.UTF_8)); message.setHeader(HttpHeaders.AUTHORIZATION, String.format("Basic %s", encodedAuth)); } message.setBody(json.get("body").asText()); } catch (Exception e) { e.printStackTrace(); } } } }
2. 修改ProducerTemplate调用逻辑
将消息发送到direct:invoke-webhook端点,而非文件路径,这样就能同步获取Webhook的响应:
private static CamelContext camel; private static ProducerTemplate producerTemplate; ... if (camel == null) { camel = new DefaultCamelContext(); camel.addRoutes(new WebhookRouteBuilder()); producerTemplate = camel.createProducerTemplate(); camel.start(); } final String webhookJson = JacksonUtils.getObjectMapper() .writerWithDefaultPrettyPrinter() .writeValueAsString(webhook); // 发送到direct端点,获取Webhook响应 Object result = producerTemplate.requestBody("direct:invoke-webhook", webhookJson);
3. 获取完整Exchange(若需要)
如果要获取响应头、状态码等完整Exchange信息,可使用request方法:
Exchange exchange = producerTemplate.request("direct:invoke-webhook", ex -> ex.getIn().setBody(webhookJson)); Message responseMessage = exchange.getOut(); // 获取响应体 String responseBody = responseMessage.getBody(String.class); // 获取响应头(如状态码) Integer statusCode = responseMessage.getHeader(HTTP_RESPONSE_CODE, Integer.class); String contentType = responseMessage.getHeader(HttpHeaders.CONTENT_TYPE, String.class);
关键原理说明
- 文件组件的Producer仅负责将内容写入文件,写入完成后立即返回原始内容,路由中
from(messageSource)的后续处理是异步执行的,因此无法通过producerTemplate获取Webhook响应。 direct端点是同步的请求-响应模式,消息会在同一个线程中走完整个路由流程,处理完成后才返回结果,完美匹配你主动调用并获取响应的需求。
内容的提问来源于stack exchange,提问作者Martin Smithson
相关产品推荐
相关产品推荐

