Spring Cloud Stream 3.x弃用@Input/@Output和Source等接口,唯一推荐发送方式是注入StreamBridge;其参数需匹配配置中binding名(如my-out-0),而非exchange名或routingKey,且须配置content-type和正确依赖以支持自动序列化。
发送消息必须用 StreamBridge,别再写 @Output 和 Source
spring cloud stream 3.x 彻底移除了 @input/@output 注解和基于接口的绑定方式,source、sink、processor 这些预定义接口也废弃了。现在唯一推荐的发送方式是注入 streambridge 实例,它支持动态 destination 和运行时参数化。
常见错误:还在配置 @EnableBinding(Source.class) 或手动 new MessageChannel,会直接启动失败或抛 IllegalStateException: No binding targets defined。
-
StreamBridge是线程安全的,可全局单例复用,无需每次 new - destination 名称要和
spring.cloud.stream.bindings.<name>.destination</name>配置项一致(不是 exchange 名,而是逻辑 binding 名) - 不支持在
@PostConstruct中提前调用send(),因为 binding 初始化可能尚未完成;建议放在业务方法中触发
destination 名怎么配?不是 exchange 名,也不是 routingKey
你传给 streamBridge.send("my-out-0", message) 的字符串 "my-out-0",必须对应配置文件中声明的 binding 名,例如:
spring:
cloud:
stream:
bindings:
my-out-0:
destination: orders.exchange
binder: rabbit
content-type: application/json
这里 my-out-0 是 binding 名(任意合法 ID),orders.exchange 才是 RabbitMQ 的 exchange 名。如果写反了——比如把 orders.exchange 直接当参数传给 send()——会报 No binding found for 'orders.exchange'。
- RabbitMQ binder 默认将
destination映射为 exchange,若需指定 routingKey,得用spring.cloud.stream.rabbit.bindings.<name>.producer.routing-key-expression</name> - 如果没配
destination,只写了my-out-0绑定但没设值,StreamBridge会尝试创建一个默认 exchange,名字是my-out-0,但通常不符合预期 - 多个 destination 共享同一个 exchange?可以,只要各自 binding 的
destination值相同即可
发 JSON 消息要手动序列化?不,靠 content-type 和 MessageBuilder
别再用 ObjectMapper.writeValueAsBytes() 手动转 JSON 再封装 Message。正确做法是让 binder 自动处理序列化,前提是:
- 配置里明确声明
content-type: application/json(否则默认是text/plain,对象会被 toString()) - 用
MessageBuilder.withPayload(obj).build()构造消息,payload 是 POJO,不要提前转成 String 或 byte[] - 确保 POJO 有 public getter、无参构造器,且类路径下有 Jackson 依赖(
spring-boot-starter-json)
如果 payload 是 String 类型,又没设 content-type,binder 会把它当纯文本发出去,RabbitMQ 里看到的是带引号的字符串,而不是解析后的 JSON 对象。
测试时收不到消息?先检查 binder 是否真正启用了
本地跑不通最常见原因是 RabbitMQ binder 没加载成功,表现为 StreamBridge.send() 不报错但消息根本没进 RabbitMQ。典型原因:
- 漏加依赖:
spring-cloud-starter-stream-rabbit(不是spring-boot-starter-amqp) - 配置里写了
binder: rabbit,但没配spring.rabbitmq.*基础连接参数,导致 binder 初始化失败后静默跳过 - 使用了
test-binder(如spring-cloud-stream-test-binder),它会拦截所有 send 调用,消息根本不落地
验证方法:启动日志搜 Creating binder 和 RabbitServiceAutoConfiguration,没看到说明 binder 没生效;或者用 rabbitmqctl list_exchanges 看目标 exchange 是否被自动创建出来。
binding 名和配置项名称对不上、content-type 没显式声明、binder 未实际加载——这三个点最容易卡住人,而且错误表现都很“安静”。











