若依 (RuoYi-Vue) 整合 RabbitMQ 完整实战指南(含源码 + 踩坑解决方案)
📖 导读
本文基于 RuoYi-Vue 前后端分离框架,手把手完成 RabbitMQ 主题交换机 + 生产者消费者完整整合,包含全套可直接复制源码、完整业务流转流程、本地测试步骤,同时整理开发过程中 5 个高频报错及根治方案。适配 Spring AMQP3.1.x、RabbitMQ4.3.2,新手可直接复刻,快速掌握消息队列异步解耦、流量削峰核心能力。
一、RabbitMQ 整体业务流程
1.1 消息完整流转五步流程
- 前端发起请求:浏览器访问测试接口
/test/mq/send,进入 MqTestController; - 控制器调用生产者:封装订单业务消息对象,注入生产者发送方法,立刻给前端返回成功提示(异步不阻塞);
- 生产者投递消息:RabbitTemplate 将实体序列化为 JSON,发送至
order_exchange主题交换机; - 交换机路由分发:根据路由键
order.create匹配绑定关系,消息存入order_queue队列; - 消费者监听消费:@RabbitListener 持续监听队列,自动反序列化消息执行业务逻辑,处理完成自动 ACK 删除消息。
核心特点:生产与消费完全异步解耦,前端无需等待后端复杂业务执行,大幅提升接口响应速度。
1.2 架构流转示意图
plaintext
┌─────────────┐
│ 用户/浏览器 │
└──────┬──────┘
│ HTTP GET /test/mq/send
↓
┌─────────────────────────────────┐
│ MqTestController (Controller层) │
│ - 创建 OrderMessage 对象 │
│ - 调用 OrderProducer │
│ - 立即返回响应给用户 │
└────────────────────────────────┘
│ 调用 sendOrderMessage()
↓
─────────────────────────────────┐
│ OrderProducer (生产者) │
│ - 使用 RabbitTemplate │
│ - 序列化消息为 JSON │
│ - 发送到 order_exchange 交换机 │
────────────┬────────────────────┘
│ 交换机路由
↓
─────────────────────────────────┐
│ RabbitMQ Server │
│ ┌──────────────────────────┐ │
│ │ order_exchange (交换机) │ │
│ │ 路由键: order.create │ │
│ └──────────┬───────────────┘ │
│ │ │
│ ↓ │
│ ┌──────────────────────────┐ │
│ │ order_queue (队列) │ │
│ │ 存储待消费的消息 │ │
│ └──────────┬───────────────┘ │
└────────────┬────────────────────┘
│ 消费者监听
↓
─────────────────────────────────┐
│ OrderConsumer (消费者) │
│ - @RabbitListener 监听队列 │
│ - 自动反序列化 JSON 为对象 │
│ - 执行业务逻辑 │
│ - 发送 ACK 确认 │
└─────────────────────────────────┘
1.3 核心组件通俗对照表
表格
| 技术术语 | 生活类比 | 代码对应类 / 变量 | 核心作用 |
|---|---|---|---|
| 生产者 | 寄件人 | OrderProducer | 封装业务消息并投递至 MQ |
| 消息 | 快递包裹 | OrderMessage | 承载订单、商品等业务数据 |
| 交换机 | 快递分拣中心 | order_exchange | 根据路由键分发消息 |
| 路由键 | 快递地址标签 | order.create | 绑定交换机与队列的匹配标识 |
| 队列 | 快递货架 | order_queue | 临时存储待消费消息 |
| 消费者 | 快递派送员 | OrderConsumer | 拉取消息执行业务逻辑 |
| ACK 确认 | 签收回执 | 自动触发 | 告知 MQ 消息处理完成,删除消息 |
二、项目目录结构
plaintext
ruoyi-system/
├── src/main/java/com/ruoyi/system/mq/
│ ├── config/
│ │ └── RabbitMQConfig.java # MQ交换机、队列、转换器配置
│ ├── message/
│ │ └── OrderMessage.java # 消息实体类
│ ├── producer/
│ │ └── OrderProducer.java # 消息生产者
│ └── consumer/
│ └── OrderConsumer.java # 消息消费者
ruoyi-admin/
├── src/main/java/com/ruoyi/web/controller/test/
│ └── MqTestController.java # 测试接口控制器
├── src/main/resources/
│ └── application.yml # RabbitMQ连接配置
三、完整源码实现
3.1 application.yml 连接配置
yaml
spring:
rabbitmq:
host: localhost # RabbitMQ服务地址
port: 5672 # AMQP通信端口(管理后台15672区分)
username: guest
password: guest
virtual-host: /
listener:
simple:
acknowledge-mode: auto # 自动消息确认
concurrency: 1 # 初始消费线程
max-concurrency: 10 # 最大并发消费线程
配置说明:
- 生产环境务必修改 guest 默认账号密码,提升安全性;
- concurrency、max-concurrency 可根据业务消息并发量调整;
- auto 自动 ACK:消费方法执行无异常则自动告知 MQ 删除消息。
3.2 RabbitMQConfig 核心配置类
java
package com.ruoyi.system.mq.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.support.converter.DefaultJackson2JavaTypeMapper;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitMQConfig {
// 1. 声明主题交换机
@Bean
public TopicExchange orderExchange() {
// 参数:交换机名称、持久化、不自动删除
return new TopicExchange("order_exchange", true, false);
}
// 2. 声明消息队列
@Bean
public Queue orderQueue() {
// 参数:队列名、持久化、非独占、消费者断开自动删除队列
return new Queue("order_queue", true, false, true);
}
// 3. 绑定交换机与队列,指定路由键
@Bean
public Binding bindingOrder() {
return BindingBuilder.bind(orderQueue()).to(orderExchange()).with("order.create");
}
// 4. JSON消息转换器(解决反序列化安全报错)
@Bean
public Jackson2JsonMessageConverter messageConverter() {
Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter();
// 配置可信实体包白名单,规避高版本AMQP安全限制
DefaultJackson2JavaTypeMapper typeMapper = new DefaultJackson2JavaTypeMapper();
typeMapper.setTrustedPackages("com.ruoyi.system.mq.message");
converter.setJavaTypeMapper(typeMapper);
return converter;
}
}
3.3 消息实体 OrderMessage.java
java
package com.ruoyi.system.mq.message;
import java.io.Serializable;
public class OrderMessage implements Serializable {
private static final long serialVersionUID = 1L;
private String orderId; // 订单编号
private String productName; // 商品名称
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
@Override
public String toString() {
return "OrderMessage{" +
"orderId='" + orderId + '\'' +
", productName='" + productName + '\'' +
'}';
}
}
3.4 生产者 OrderProducer.java
java
package com.ruoyi.system.mq.producer;
import com.ruoyi.system.mq.message.OrderMessage;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class OrderProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送订单消息
* @param message 订单消息实体
*/
public void sendOrderMessage(OrderMessage message) {
// 参数:交换机名称、路由键、消息对象
rabbitTemplate.convertAndSend("order_exchange", "order.create", message);
}
}
3.5 消费者 OrderConsumer.java
java
运行
package com.ruoyi.system.mq.consumer;
import com.ruoyi.system.mq.message.OrderMessage;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class OrderConsumer {
// 监听指定队列
@RabbitListener(queues = "order_queue")
public void handleOrderMessage(OrderMessage message) {
System.out.println("【消费者】收到订单消息:" + message);
// 此处编写业务逻辑:扣库存、发通知、记录日志等
}
}
3.6 测试控制器 MqTestController.java
java
package com.ruoyi.web.controller.test;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.system.mq.message.OrderMessage;
import com.ruoyi.system.mq.producer.OrderProducer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/test/mq")
public class MqTestController {
@Autowired
private OrderProducer orderProducer;
@GetMapping("/send")
@Anonymous // 若依免登录注解
public String sendMessage() {
// 封装测试消息
OrderMessage msg = new OrderMessage();
msg.setOrderId("ORD202607060001");
msg.setProductName("MacBook Pro 16寸");
// 发送消息
orderProducer.sendOrderMessage(msg);
return "消息发送成功!查看后端控制台消费日志";
}
}
四、完整测试使用流程
4.1 前置环境准备
- 启动 RabbitMQ 服务
bash
# Windows查看服务
net start | findstr RabbitMQ
# 未启动则执行
net start RabbitMQ
- 开启管理后台插件
bash
cd RabbitMQ安装目录/sbin
rabbitmq-plugins enable rabbitmq_management
# 重启服务生效
net stop RabbitMQ
net start RabbitMQ
访问管理后台:http://localhost:15672,账号密码 guest/guest。
4.2 启动若依项目
执行项目根目录ry.bat启动后端,观察日志出现 RabbitMQ 连接成功提示: Connection established to RabbitMQ at localhost:5672
4.3 发送消息两种方式
- 浏览器访问:
http://localhost:8080/test/mq/send,页面返回发送成功; - curl 命令调用:
base
curl http://localhost:8080/test/mq/send
4.4 验证消费结果
- 后端控制台输出日志:
【消费者】收到订单消息:OrderMessage{orderId='ORD202607060001', productName='MacBook Pro 16寸'} - RabbitMQ 后台队列
order_queueReady 消息数变为 0,代表消费完成; - 查看消息原始 JSON 数据(后台 Get Messages):
json
{
"__TypeId__": "com.ruoyi.system.mq.message.OrderMessage",
"orderId": "ORD202607060001",
"productName": "MacBook Pro 16寸"
}
4.5 批量测试命令
Windows CMD 批量发送 10 条消息:
bash
for /l %i in (1,1,10) do curl http://localhost:8080/test/mq/send
五、开发高频报错与解决方案
问题 1:接口 401 认证失败
报错:请求访问:/test/mq/send,认证失败,无法访问系统资源 原因:若依默认所有接口需要登录,测试接口未放行 解决:接口方法添加@Anonymous注解,导入对应包com.ruoyi.common.annotation.Anonymous。
问题 2:反序列化 SecurityException 安全异常
报错:Attempt to deserialize unauthorized class xxx 原因:Spring AMQP2.10 + 新增反序列化白名单安全机制 解决:配置 Jackson2JsonMessageConverter 并设置可信包,参考 RabbitMQConfig 代码。
问题 3:消息格式转换异常 MessageConversionException
报错:Cannot convert byte[] to OrderMessage,contentType=application/x-java-serialized-object 原因:队列残留旧 Java 序列化消息,新代码使用 JSON 转换器格式不兼容 解决:队列构造第四个参数设置autoDelete=true,重启项目自动清空旧消息;或后台手动 Purge 队列。
问题 4:RabbitMQ 连接拒绝 Connection refused: connect
原因:RabbitMQ 未启动、yml 端口写成 15672(管理端口) 解决:确认服务运行,spring.rabbitmq.port 固定为 5672。
问题 5:Jackson2JsonMessageConverter 废弃警告
提示:deprecated since version 4.0 解决:无需删除转换器,搭配 DefaultJackson2JavaTypeMapper 配置即可消除警告,官方推荐过渡方案。
六、部署 & 排查检查清单
6.1 启动前自检
- RabbitMQ 服务正常运行,管理后台可登录;
- application.yml MQ 连接地址、端口、账号无误;
- 实体类放入可信包路径,转换器配置完整;
- 测试接口添加
@Anonymous免登录注解。
6.2 测试成功判定标准
- 接口访问返回消息发送成功;
- 控制台打印消费者日志;
- RabbitMQ 队列无堆积消息;
- 无任何异常堆栈报错。
6.3 常见故障快速排查
- 消息发送成功无消费日志:查看应用是否有反序列化异常、消费者是否在线;
- 消息大量堆积 Ready>0:消费者未启动、业务代码阻塞、抛出异常未处理;
- 交换机 / 队列不存在:重启项目,@Bean 配置会自动声明资源。
七、进阶拓展方向
- 手动 ACK 确认:关闭 auto 自动确认,手动控制消息重试、死信;
- 死信队列 DLQ:消费失败消息转入死信队列,定时重试;
- 生产者确认机制:Publisher-Confirm 保障消息可靠投递;
- 延迟队列:实现订单超时取消、定时通知;
- MQ 集群高可用:镜像队列、负载均衡;
- 监控告警:队列积压、消费速率监控。
八、总结
本文完整实现若依框架 RabbitMQ 基础消息收发,覆盖配置、实体、生产者、消费者、测试接口全套代码,同时解决开发中 5 个核心坑点。 消息队列核心价值:
- 异步解耦:前端无需等待复杂业务,提升接口响应;
- 流量削峰:高并发请求缓冲,避免数据库瞬时压垮;
- 可靠异步:订单、通知、日志等非实时业务最佳实践。 整套代码可直接复制到项目运行,适配日常开发、毕业设计、企业项目开发使用。
文档适配版本: RuoYi-Vue 3.9.2 | RabbitMQ 4.3.2 | Spring AMQP 3.1.x
更多推荐
所有评论(0)