Java-211 Spring Boot 2.4.1 整合 RabbitMQ 实战:DirectExchange + @RabbitListener 全流程

TL;DR

  • 场景:Spring Boot 快速接入 RabbitMQ,实现 HTTP 触发投递、消费者监听消费。
  • 结论:用 Spring AMQP 声明拓扑(Queue/DirectExchange/Binding)+ AmqpTemplate 投递 + @RabbitListener 消费即可闭环。
  • 产出:可复用的最小可跑 Demo(POM + yml + 配置类 + Controller + Consumer)。

版本矩阵

项目 说明
Spring Boot 2.4.1 spring-boot-starter-parent 版本固定为 2.4.1(你 POM 中写死)。
Java 8 maven.compiler.source/target=8。
spring-boot-starter-amqp 引入 Spring AMQP / Spring Rabbit,提供 AmqpTemplate、@RabbitListener 等。
RabbitMQ Server(版本未标注) 你的配置仅依赖 AMQP 基础能力(Direct/Queue/Binding),通常跨版本兼容;但未提供服务端版本号,无法给出"已验证"结论。
Spring Web(starter-web) 用于暴露 /send/{message} 测试入口。

Spring Boot 整合 RabbitMQ

基本介绍

Spring AMQP 是 Spring 框架对 AMQP (Advanced Message Queuing Protocol) 协议的抽象实现,它提供了统一的编程模型来操作 AMQP。而 Spring Rabbit 是 Spring AMQP 的具体实现,专门针对 RabbitMQ 消息中间件进行了封装和扩展。

PS:续接上节的内容
PS:续接上节的内容
PS:续接上节的内容

POM

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>icu.wzk</groupId>
    <artifactId>rabbitmq-springboot</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.1</version>
        <relativePath/>
    </parent>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

application.yml

yaml 复制代码
spring:
  application:
    name: rabbit-mq
  rabbitmq:
    host: localhost
    port: 5672
    username: admin
    password: secret
    virtual-host: /

StartApp

java 复制代码
package icu.wzk;

@SpringBootApplication
public class StartApp {
    public static void main(String[] args) {
        SpringApplication.run(StartApp.class, args);
    }
}

RabbitConfig

java 复制代码
package icu.wzk.config;

/**
 * RabbitMQ 拓扑声明:
 * - Queue: myqueue
 * - Exchange: myex(direct)
 * - Binding: myqueue <- myex,routingKey = direct.biz.ex
 *
 * 说明:
 * 1) durable=true:broker 重启后依然存在(生产环境默认应为 true)
 * 2) autoDelete=false:没有消费者也不自动删除
 * 3) 这里用 DirectExchange,路由规则是 routingKey 精确匹配
 */
@Configuration
public class RabbitConfig {

    public static final String QUEUE = "myqueue";
    public static final String EXCHANGE = "myex";
    public static final String ROUTING_KEY = "direct.biz.ex";

    /**
     * 队列:持久化队列
     */
    @Bean
    public Queue myQueue() {
        return new Queue(QUEUE, true, false, false);
    }

    /**
     * 交换机:DirectExchange(精确路由)
     */
    @Bean
    public Exchange myExchange() {
        return new DirectExchange(EXCHANGE, true, false);
    }

    /**
     * 绑定:把队列绑定到交换机,并指定 routingKey
     *
     * 推荐写法:用 BindingBuilder,避免手写 Binding 构造参数时填错。
     */
    @Bean
    public Binding myBinding(Queue myQueue, DirectExchange myExchange) {
        return org.springframework.amqp.core.BindingBuilder
                .bind(myQueue)
                .to(myExchange)
                .with(ROUTING_KEY);
    }

    /*
     * 其它 Exchange 的等价写法(按需替换 myExchange()):
     *
     * TopicExchange:
     *   return new TopicExchange("topic.biz.ex", true, false);
     *
     * FanoutExchange:
     *   return new FanoutExchange("fanout.biz.ex", true, false);
     *
     * HeadersExchange:
     *   return new HeadersExchange("header.biz.ex", true, false);
     *
     * CustomExchange:
     *   return new CustomExchange("custom.biz.ex", ExchangeTypes.DIRECT, true, false, null);
     */
}

HelloController

java 复制代码
package icu.wzk.controlle;

@RestController
public class HelloController {
    @Autowired
    private AmqpTemplate rabbitTemplate;
    @RequestMapping("/send/{message}")
    public String sendMessage(@PathVariable String message) {
        rabbitTemplate.convertAndSend("myex", "direct.biz.ex",
                message);
        return "ok";
    }
}

HelloConsumer

使用监听器,用于推消息

java 复制代码
package icu.wzk.consumer;

@Component
public class HelloConsumer {
    @RabbitListener(queues = "myqueue")
    public void service(String message) {
        System.out.println("消息队列推送来的消息:" + message);
    }
}

运行测试

启动后可以看到刚才测试中的数据已经消费到了:

错误速查

症状 根因 定位 修复
启动报错:Parameter 2 of method myBinding required a bean of type 'DirectExchange' that could not be found myExchange() 返回类型写成 Exchange,而 myBinding 形参要求 DirectExchange,Spring 无法按类型注入 看启动日志的 Bean 注入异常;检查 RabbitConfig 中 myExchange() 方法签名 把 myExchange() 返回类型改为 DirectExchange;或把 myBinding 形参改为 Exchange 并在内部强转/改写绑定方式
发送成功但队列无消息/消费者无输出 exchange/routingKey/queue/binding 任一不一致(拼写、大小写、routingKey 不匹配) RabbitMQ Management UI:Exchanges/Queues/Bindings;或用日志打印实际投递参数 统一常量引用:Controller 使用 RabbitConfig.EXCHANGE/ROUTING_KEY;确保 binding routingKey = 投递 routingKey
请求 /send/{message} 404 Controller 包名拼写错误:icu.wzk.controlle 少了 r,导致组件扫描失败 看启动日志是否有映射;检查项目结构与包名 修正包名为 icu.wzk.controller;或确保 @SpringBootApplication 扫描到该包
启动时报 ACCESS_REFUSED - Login was refused 用户名/密码/virtual-host 不正确,或该用户无 vhost 权限 RabbitMQ 日志 + 应用启动日志;Management UI 查看用户权限 校对 application.yml;给用户授予 vhost 权限(configure/write/read)
启动时报 Connection refused / Timeout RabbitMQ 未启动、端口不通、host 写错、容器端口未映射 telnet host 5672/nc;查看 RabbitMQ 监听端口 启动 RabbitMQ;改正确 host;映射 5672;确认防火墙/网络
消费者不消费但无报错 @RabbitListener 未生效(未扫到组件、缺少相关依赖、监听队列名不一致) 启动日志是否打印 listener 容器信息;检查 @Component、包扫描 确保 HelloConsumer 在扫描路径;队列名与声明一致;保留 spring-boot-starter-amqp
消息中文乱码/显示异常 生产者/消费者编码与消息转换器不一致(默认通常 OK,但自定义时易出问题) 查看消息体是否为 byte[]/String;检查 message converter 明确使用 String;必要时配置 Jackson2JsonMessageConverter 或统一编码策略

其他系列

🚀 AI篇持续更新中(长期更新)

AI炼丹日志-29 - 字节跳动 DeerFlow 深度研究框斜体样式架 私有部署 测试上手 架构研究 ,持续打造实用AI工具指南!
AI研究-132 Java 生态前沿 2025:Spring、Quarkus、GraalVM、CRaC 与云原生落地
🔗 AI模块直达链接

💻 Java篇持续更新中(长期更新)

Java-207 RabbitMQ Direct 交换器路由:RoutingKey 精确匹配、队列多绑定与日志分流实战

MyBatis 已完结,Spring 已完结,Nginx已完结,Tomcat已完结,分布式服务已完结,Dubbo已完结,MySQL已完结,MongoDB已完结,Neo4j已完结,FastDFS 已完结,OSS已完结,GuavaCache已完结,EVCache已完结,RabbitMQ正在更新... 深入浅出助你打牢基础!
🔗 Java模块直达链接

📊 大数据板块已完成多项干货更新(300篇):

包括 Hadoop、Hive、Kafka、Flink、ClickHouse、Elasticsearch 等二十余项核心组件,覆盖离线+实时数仓全栈!
大数据-278 Spark MLib - 基础介绍 机器学习算法 梯度提升树 GBDT案例 详解
🔗 大数据模块直达链接

相关推荐
Wang's Blog2 小时前
Kafka: 生产者(Producer)核心机制
分布式·kafka
剽悍一小兔2 小时前
idea 执行测试类报错:failed to resolve org.junit.platform:junit-platform-launcher:1.8.2
java·ide·intellij-idea
与遨游于天地2 小时前
日志系统 Kafka 积压处理有效方案
经验分享·分布式·kafka
学海_无涯_苦作舟2 小时前
RabbitMQ Java Client源码解析——FrameHandler
java·rabbitmq·java-rabbitmq
毕设源码-赖学姐2 小时前
【开题答辩全过程】以 果树的生长信息管理系统为例,包含答辩的问题和答案
java·spring boot
CodeCraft Studio2 小时前
国产化PDF处理控件Spire.PDF教程:在Java快速解析PDF文本、表格、图像和元数据
java·python·pdf·pdf解析·spire.pdf·元数据解析·java pdf解析
CryptoRzz2 小时前
墨西哥股票数据 API 对接实战指南(含实时行情与 IPO 功能)
java·后端·websocket·区块链
hgz07102 小时前
Spring Boot自动配置
java·springboot