spring boot 3.x 中 spring-boot-starter-amqp 强制使用 jakarta ee 9+,导致 javax. 注解(如 @postconstruct、@valid)编译失败,需替换为 jakarta.;queue/exchange 构造推荐 queuebuilder/exchangebuilder;监听器仅支持 direct 模式,配置前缀须改为 direct.;死信交换机不得为空字符串。

Spring Boot 3.x 中 spring-boot-starter-amqp 不再拉取 javax.* 依赖
直接后果是:所有显式 import javax.annotation.PostConstruct、javax.validation.Valid 或 javax.persistence.Entity 的代码,在 Spring Boot 3.x 下编译失败。这不是 RabbitMQ 模块自身的问题,而是它所依赖的整个生态链(Spring Framework 6 + Jakarta EE 9)已彻底弃用 javax.* 命名空间。
关键点在于:spring-boot-starter-amqp 在 2.x 版本中传递依赖了 spring-amqp 2.4.x 和 amqp-client 5.x,它们仍兼容 javax.*;而 3.x 版本拉取的是 spring-amqp 3.0+,底层已强制使用 jakarta.annotation.*、jakarta.validation.* 等。
- 如果你在消费者方法上写了
@Valid参数校验,必须把 import 改为jakarta.validation.Valid - 如果用了
@PostConstruct初始化 RabbitMQ 相关 bean,需替换为jakarta.annotation.PostConstruct - IDE 全局替换时注意别误伤
javax.crypto、javax.net这类 JDK 标准包——它们不受 Jakarta 迁移影响
RabbitMQConfig 中声明 Queue、Exchange 时的构造参数差异
Spring Boot 2.x 常用 new Queue("name", true) 这种构造方式,第三个布尔参数是 autoDelete;但 Spring Boot 3.x 推荐使用 QueueBuilder,因为旧构造器在 3.x 中虽未删除,却隐含默认行为变更风险。
比如以下写法在 2.x 安全,在 3.x 可能导致队列非预期自动删除:
new Queue("my.queue", true, false, true)
原因:最后一个 true 表示 autoDelete,但在某些 spring-amqp 3.0.x 小版本中,该参数语义被重解释为“仅当 channel 关闭时才 auto-delete”,和你预期不符。
- 统一改用
QueueBuilder.durable("my.queue")显式声明持久化 - 需要排他性(exclusive)或自动删除(auto-delete)时,明确调用
.exclusive()或.autoDelete() -
DirectExchange、TopicExchange同理,优先用ExchangeBuilder构造,避免依赖构造函数参数顺序
消费者确认模式配置项从 spring.rabbitmq.listener.simple.acknowledge-mode 彻底移除
Spring Boot 2.x 支持 simple 和 direct 两种监听容器,对应两套配置前缀;但 Spring Boot 3.x 废弃了 SimpleMessageListenerContainer,只保留 DirectMessageListenerContainer,因此所有以 simple. 开头的配置项(包括 acknowledge-mode、concurrency、max-concurrency)全部失效。
现象:配置了 spring.rabbitmq.listener.simple.acknowledge-mode=manual,但消费者依然自动确认,消息处理异常后直接丢失。
- 必须改用
spring.rabbitmq.listener.direct.acknowledge-mode=manual -
concurrency配置也需同步改为spring.rabbitmq.listener.direct.concurrency - 若项目中混用
@RabbitListener和手动创建SimpleMessageListenerContainer,升级后会启动失败,报BeanCreationException找不到SimpleMessageListenerContainerFactory
死信队列绑定中 deadLetterExchange 参数值不能为 ""
Spring Boot 2.x 允许在 QueueBuilder 中写 .deadLetterExchange(""),表示使用默认交换机(AMQP default direct exchange);但 Spring Boot 3.x 的 spring-amqp 3.1+ 对此做了严格校验,空字符串会被拒绝,抛出 IllegalArgumentException: deadLetterExchange must not be empty。
这不是 bug,而是对 AMQP 协议语义的回归——默认交换机虽存在,但不应由客户端显式指定为空字符串,应明确指向 amq.direct 或业务自建交换机。
- 正确写法:
QueueBuilder.durable("dlq").deadLetterExchange("amq.direct").deadLetterRoutingKey("my.dlq.route") - 更推荐做法:定义一个专用的死信交换机(如
dlx.exchange),所有死信队列都绑定到它,便于统一监控和路由策略管理 - 注意:
deadLetterRoutingKey必须与目标死信队列的 binding key 一致,否则消息进不了死信队列
acknowledge-mode 配置前缀,却忘了同步检查 RetryTemplate 是否还在用已废弃的 SimpleRetryPolicy 类型;又或者修复了 deadLetterExchange,但没意识到 spring.rabbitmq.listener.direct.retry.enabled=true 在 3.x 中默认关闭,导致重试逻辑根本没生效。每个点都得对照 spring-amqp 的 release note 逐条验证。Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











