Spring Cloud Stream Router应用JSON payload解析问题咨询
解决Spring Cloud Stream Router Sink中JSON Payload未自动解析的问题
我之前碰到过几乎一模一样的问题,折腾了好一阵才找到症结,咱们一步步来排查和解决:
核心问题分析
Filter处理器能自动解析JSON到LinkedHashMap,但Router不行,本质是消息转换的触发条件没满足——Spring Cloud Stream的消息转换器需要依赖消息头里的content-type标识,或者接收端的强制配置来触发JSON解析。
排查与解决步骤
1. 先确认发送端的消息是否携带了正确的Content-Type头
这是最容易忽略的点:如果发送的JSON字符串只是纯文本消息(没有content-type: application/json的消息头),即使接收端Router配置了content-type,转换器也不会触发,只会把payload当成String处理。
- 如果发送端是Spring Cloud Stream Source应用,部署时添加配置:
stream deploy --name router-flow --properties "app.<your-source-name>.spring.cloud.stream.bindings.output.content-type=application/json" - 如果是自定义发送逻辑,构建消息时手动添加头:
Message<String> jsonMessage = MessageBuilder.withPayload("{\"key\":\"value\"}") .setHeader(MessageHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) .build();
2. 修正Router Sink的接收端配置
你已经设置了content-type,但可能还需要补充两个关键配置:
- 确保Header Mode不是
none:如果Header Mode设为none,接收端会忽略所有消息头,包括content-type,导致转换失效。部署时添加:
(注:如果用Kafka binder,把stream deploy --name router-flow --properties "app.router.spring.cloud.stream.bindings.input.consumer.header-mode=embeddedHeaders"embeddedHeaders改成headers) - 禁用Native Decoding:部分binder(比如Kafka)默认开启
native-decoding,会绕过Spring的消息转换器,直接返回原始字节/字符串。添加配置:stream deploy --name router-flow --properties "app.router.spring.cloud.stream.bindings.input.consumer.use-native-decoding=false"
3. 调整JUnit测试的消息构建方式
你的测试用例里直接传JSON字符串,没有携带content-type头,所以Router还是按String处理。修改测试代码,模拟带正确头的消息:
@Test void testRouterWithJsonPayload() { String jsonPayload = "{\"status\":\"success\",\"data\":{}}"; Message<?> message = MessageBuilder.withPayload(jsonPayload) .setHeader(MessageHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .build(); // 发送消息并断言路由结果 routerSink.input().send(message); // ... 后续断言逻辑 }
4. 验证配置是否生效
可以在Router应用里加个简单的日志,打印接收到的消息头和payload类型,确认content-type是否存在,payload是否已经转为LinkedHashMap:
@ServiceActivator(inputChannel = Sink.INPUT) public void handleMessage(Message<?> message) { System.out.println("Content-Type: " + message.getHeaders().get(MessageHeaders.CONTENT_TYPE)); System.out.println("Payload Type: " + message.getPayload().getClass().getName()); // 后续路由逻辑 }
总结
核心就是让发送端带上正确的Content-Type头,同时确保接收端的转换器能识别并触发解析。按照上面的步骤调整后,Router的payload应该就能自动转为LinkedHashMap,你也可以正常编写基于JSON属性的SpEL表达式了。
内容的提问来源于stack exchange,提问作者Greg Charles
相关产品推荐
相关产品推荐

