【RabbitMQ】Spring Boot 结合 RabbitMQ 完成应用间的通信


🔥个人主页: 中草药
🔥专栏:【中间件】企业级中间件剖析
Spring 框架与 RabbitMQ 的整合主要通过 Spring AMQP(Advanced Message Queuing Protocol)模块实现,提供了便捷的消息队列开发能力。

引入依赖
<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><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.amqp</groupId><artifactId>spring-rabbit-test</artifactId><scope>test</scope></dependency></dependencies>
配置
#配置RabbitMQ的基本信息
spring:rabbitmq:host: 110.41.51.65port: 15673 #默认为5672username: studypassword: studyvirtual-host: bite #默认值为#或者以下这种方式rabbitmq:addresses: #amqp://username:password@Ip:port/virtual-host
一、工作队列模式(Work Queue)
场景:多个消费者共享一个队列,消息被轮询分发(Round-Robin),用于任务分发和负载均衡(如耗时任务处理)。
producer
@RestController
@RequestMapping("/producer")
public class ProducerController {@Autowiredprivate RabbitTemplate rabbitTemplate;@RequestMapping("/work")public String work(){//使用内置交换机 RoutingKey 和队列名称一致for (int i = 0; i < 10; i++) {rabbitTemplate.convertAndSend("", Constants.WORK_QUEUE,"Hello World"+i);}return "OK";}
}
@RabbitListener 是 Spring 框架中用于监听 RabbitMQ 队列的注解,通过使用这个注解,可以定义一个方法,以便从 RabbitMQ 队列中接收消息(相当于消费者)。该注解支持多种参数类型,这些参数类型代表了从 RabbitMQ 接收到的消息和相关信息。
以下是一些常用的参数类型:
String:返回消息的内容。Message(org.springframework.amqp.core.Message):Spring AMQP 的 Message 类,返回原始的消息体以及消息的属性,如消息 ID、内容、队列信息等。Channel(com.rabbitmq.client.Channel):RabbitMQ 的通道对象,可以用于进行更高级的操作,如手动确认消息 。
@Component
public class WorkListener {@RabbitListener(queues = Constants.WORK_QUEUE)public void queueListener1(Message message, Channel channel) {System.out.println("Listener1:["+Constants.WORK_QUEUE+"]"+message+",channel:"+channel);}@RabbitListener(queues = Constants.WORK_QUEUE)public void queueListener2(String message) {System.out.println("Listener2:["+Constants.WORK_QUEUE+"]"+message);}
}
观察控制台

轮询分发:默认按顺序将消息分发给不同消费者。
二、发布订阅模式(Publish/Subscribe)
场景:消息广播到所有绑定的队列(如日志广播、事件通知),使用 Fanout 交换机。
声明使用交换机和队列 并绑定
@Configuration
public class RabbitMQConfig {@Bean("fanoutQueue1")public Queue funoutQueue1() {return QueueBuilder.durable(Constants.FUNOUT_QUEUE1).build();}@Bean("fanoutQueue2")public Queue funoutQueue2() {return QueueBuilder.durable(Constants.FUNOUT_QUEUE2).build();}@Bean("funoutExchange")public FanoutExchange funoutExchange(){return ExchangeBuilder.fanoutExchange(Constants.FUNOUT_EXCHANGE).durable(true).build();}@Bean("funoutQueueBinding1")public Binding funoutQueueBinding1(@Qualifier("fanoutQueue1") Queue queue,@Qualifier("funoutExchange") FanoutExchange funoutExchange){return BindingBuilder.bind(queue).to(funoutExchange);}@Bean("funoutQueueBinding2")public Binding funoutQueueBinding2(@Qualifier("fanoutQueue2") Queue queue,@Qualifier("funoutExchange") FanoutExchange funoutExchange){return BindingBuilder.bind(queue).to(funoutExchange);}
}
producer
@RestController
@RequestMapping("/producer")
public class ProducerController {@Autowiredprivate RabbitTemplate rabbitTemplate;@RequestMapping("/funout")public String funout(){rabbitTemplate.convertAndSend(Constants.FUNOUT_EXCHANGE,"","Hello Spring funout");return "OK";}
}
listener
@Component
public class FunoutListener {@RabbitListener(queues = Constants.FUNOUT_QUEUE1)public void queueListener1(String message) {System.out.println("Listener1:["+Constants.FUNOUT_QUEUE1+"]"+message);}@RabbitListener(queues = Constants.FUNOUT_QUEUE2)public void queueListener2(String message) {System.out.println("Listener2:["+Constants.FUNOUT_QUEUE2+"]"+message);}
}
在实际开发之中,一个 listener 监听一个 queue
三、路由模式(Routing)
场景:根据 路由键(Routing Key) 精准匹配,将消息发送到指定队列,使用 Direct 交换机。
声明使用交换机和队列 并绑定
@Configuration
public class RabbitMQConfig {//direct@Bean("directQueue1")public Queue directQueue1() {return QueueBuilder.durable(Constants.DIRECT_QUEUE1).build();}@Bean("directQueue2")public Queue directQueue2() {return QueueBuilder.durable(Constants.DIRECT_QUEUE2).build();}@Bean("directExchange")public DirectExchange directExchange(){return ExchangeBuilder.directExchange(Constants.DIRECT_EXCHANGE).durable(true).build();}@Bean("directQueueBinding1")public Binding directQueueBinding1(@Qualifier("directQueue1") Queue queue,@Qualifier("directExchange") DirectExchange directExchange){return BindingBuilder.bind(queue).to(directExchange).with("orange");}@Bean("directQueueBinding2")public Binding directQueueBinding2(@Qualifier("directQueue2") Queue queue,@Qualifier("directExchange") DirectExchange directExchange){return BindingBuilder.bind(queue).to(directExchange).with("black");}@Bean("directQueueBinding3")public Binding directQueueBinding3(@Qualifier("directQueue2") Queue queue,@Qualifier("directExchange") DirectExchange directExchange){return BindingBuilder.bind(queue).to(directExchange).with("orange");}
}
producer
@RestController
@RequestMapping("/producer")
public class ProducerController {@Autowiredprivate RabbitTemplate rabbitTemplate;@RequestMapping("/direct/{routingKey}")public String direct(@PathVariable String routingKey){rabbitTemplate.convertAndSend(Constants.DIRECT_EXCHANGE,routingKey,"Hello Spring direct "+routingKey);return "direct OK";}
}
listener
@Component
public class DirectListener {@RabbitListener(queues = Constants.DIRECT_QUEUE1)public void queueListener1(String message) {System.out.println("Listener1:["+Constants.DIRECT_QUEUE1+"]"+message);}@RabbitListener(queues = Constants.DIRECT_QUEUE2)public void queueListener2(String message) {System.out.println("Listener2:["+Constants.DIRECT_QUEUE2+"]"+message);}
}
如果某一个队列即绑定了black和orange,将会分别发送到队列

四、通配符模式(Topics)
场景:根据路由键的 通配符规则 匹配队列,使用 Topic 交换机,支持 *(匹配一个单词)和 #(匹配多个单词)。
Topics 和 Routing 模式的区别是:
- topics 模式使用的交换机类型为 topic (Routing 模式使用的交换机类型为 direct)
- topic 类型的交换机在匹配规则上进行了扩展,Binding Key 支持通配符匹配
声明使用交换机和队列 并绑定
@Configuration
public class RabbitMQConfig {//TOPIC@Bean("topicExchange")public TopicExchange topicExchange(){return ExchangeBuilder.topicExchange(Constants.TOPIC_EXCHANGE).durable(true).build();}@Bean("topicQueue1")public Queue topicQueue1(){return QueueBuilder.durable(Constants.TOPIC_QUEUE1).build();}@Bean("topicQueue2")public Queue topicQueue2(){return QueueBuilder.durable(Constants.TOPIC_QUEUE2).build();}@Bean("topicQueueBinding1")public Binding topicQueueBinding1(@Qualifier("topicExchange")TopicExchange topicExchange,@Qualifier("topicQueue1") Queue topicQueue){return BindingBuilder.bind(topicQueue).to(topicExchange()).with("*.orange.*");}@Bean("topicQueueBinding2")public Binding topicQueueBinding2(@Qualifier("topicExchange")TopicExchange topicExchange,@Qualifier("topicQueue2") Queue topicQueue){return BindingBuilder.bind(topicQueue).to(topicExchange).with("*.*.rabbit");}@Bean("topicQueueBinding3")public Binding topicQueueBinding3(@Qualifier("topicExchange")TopicExchange topicExchange,@Qualifier("topicQueue2") Queue topicQueue){return BindingBuilder.bind(topicQueue).to(topicExchange).with("lazy.#");}
}
producer
@RestController
@RequestMapping("/producer")
public class ProducerController {@Autowiredprivate RabbitTemplate rabbitTemplate;@RequestMapping("/topic/{routingKey}")public String topic(@PathVariable String routingKey){rabbitTemplate.convertAndSend(Constants.TOPIC_EXCHANGE,routingKey,"Hello Spring topic "+routingKey);return "topic OK";}
}
listener
@Component
public class TopicListener {@RabbitListener(queues = Constants.TOPIC_QUEUE1)public void queueListener1(String message) {System.out.println("Listener1:["+Constants.TOPIC_QUEUE1+"]"+message);}@RabbitListener(queues = Constants.TOPIC_QUEUE2)public void queueListener2(String message) {System.out.println("Listener2:["+Constants.TOPIC_QUEUE2+"]"+message);}
}
五、完成应用通信
SpringBoot 整合 RabbitMQ 实现应用通信是微服务/分布式系统中常见的异步解耦方案。
以此图为实例

订单系统
@Configuration
public class RabbitMQConfig {@Bean("orderQueue")public Queue orderQueue() {return QueueBuilder.durable("order.create").build();}
}@RestController
@RequestMapping("/order")
public class OrderController {@Autowiredprivate RabbitTemplate rabbitTemplate;@RequestMapping("/create")public String create(){rabbitTemplate.convertAndSend("","order.create","订单信息,订单ID:"+ UUID.randomUUID());//这里仅仅是模拟演示,实际的下单操作比较复杂,包括参数的校验,数据库存储等等 业务代码省略return "下单成功";}
}
物流系统
@Component
@RabbitListener(queues = "order.create")
public class OrderListener {@RabbitHandler//该注解根据所识别的数据类型不同自动分配不同的方法public void handleOrder(String orderInfo) {System.out.println("接收到新的订单消息:"+orderInfo);//接收到订单消息后,进行相应的业务出路 代码省略}@RabbitHandler//在此处为方便演示我们将order-service 让此项目应用//正确的做法是将OrderInfo抽取出来单独作为一个包,两个service都引用这个包public void handleOrder2(OrderInfo orderInfo) {System.out.println("接收到新的订单消息:"+orderInfo);}
}
@RabbitHandler 注解用于标记方法,这些方法会根据消息的类型来处理接收到的消息。当一个消息监听器容器接收到消息时,它会根据消息的类型选择合适的 @RabbitHandler 注解的方法来处理该消息。
测试结果

当在发送的是一个对象时,为保证对象的可读性,我们要保证对象可被序列化,且通过 Jackson2JsonMessageConverter 将其从原生序列化改为Json格式
@Configuration
public class RabbitMQConfig {@Beanpublic Jackson2JsonMessageConverter messageConverter() {return new Jackson2JsonMessageConverter();}@Beanpublic RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);rabbitTemplate.setMessageConverter(messageConverter());return rabbitTemplate;}
}
对于Listener,为保证同样具有解读json的能力,也应该去加上相同的配置
@Data
public class OrderInfo implements Serializable {//实现序列化接口private String orderId;private String name;
}
可观察结果

对时间的慷慨,就等于慢性自杀。——奥斯特洛夫斯基
🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀
以上,就是本期的全部内容啦,若有错误疏忽希望各位大佬及时指出💐
制作不易,希望能对各位提供微小的帮助,可否留下你免费的赞呢🌸
相关文章:
【RabbitMQ】Spring Boot 结合 RabbitMQ 完成应用间的通信
🔥个人主页: 中草药 🔥专栏:【中间件】企业级中间件剖析 Spring 框架与 RabbitMQ 的整合主要通过 Spring AMQP(Advanced Message Queuing Protocol)模块实现,提供了便捷的消息队列开发能力。 引…...
Pytorch系列教程:可视化Pytorch模型训练过程
深度学习和理解训练过程中的学习和进步机制对于优化性能、诊断欠拟合或过拟合等问题至关重要。将训练过程可视化的过程为学习的动态提供了有价值的见解,使我们能够做出合理的决策。训练进度必须可视化的两种方法是:使用Matplotlib和Tensor Board。在本文…...
electron+vue+webview内嵌网页并注入js
vue内嵌网页可以使用iframe实现内嵌网页,但是只能通过postMessage间接通信,在electron环境下,vue可以直接使用webview来内嵌网页,支持 executeJavaScript、postMessage、send 等丰富的通信机制。 使用 webview的优势 性能更佳&…...
利用OpenResty拦截SQL注入
需求 客户的一个老项目被相关部门检测不安全,报告为sql注入。不想改代码,改项目,所以想到利用nginx去做一些数据校验拦截。也就是前端传一些用于sql注入的非法字符或者数据库的关键字这些,都给拦截掉,从而实现拦截sql…...
CAD文件转换为STL
AutoCAD与STL格式简介 AutoCAD软件是由美国欧特克有限公司(Autodesk)出品的一款自动计算机辅助设计软件,可以用于绘制二维制图和基本三维设计,通过它无需懂得编程,即可自动制图,因此它在全球广泛使用&…...
78_Pandasagg()和aggregate()的用法
78_Pandasagg()和aggregate()的用法 通过使用pandas.DataFrame和Series的agg()或aggregate()方法,可以对行或列同时应用多个操作进行聚合。agg()是aggregate()的别名,二者用法相同。 pandas.DataFrame.agg — pandas 2.1.3 文档 pandas.Series.agg —…...
QT:串口上位机
创建工程 布局UI界面 设置名称 设置数据 设置波特率 波特率默认9600 设置数据位 数据位默认8 设置停止位 设置校验位 调整串口设置、接收设置、发送设置为Group Box 修改配置 QT core gui serialport 代码详解 mianwindow.h 首先在mianwindow.h当中定义一个串口指…...
C++跨平台开发环境搭建全指南:工具链选型与性能优化实战
C跨平台开发环境搭建全指南:工具链选型与性能优化实战 目录 开发环境搭建工具链选型性能优化实战常见问题排查 开发环境搭建 操作系统环境准备 Windows# 安装Visual Studio Build Tools choco install visualstudio2022buildtools choco install cmake --instal…...
数据批处理(队列方式)
数据批处理(队列方式) public class DataProcessor {private static final int THREAD_COUNT 4;private static final int QUEUE_SIZE 10;private LinkedBlockingQueue<Data> queue new LinkedBlockingQueue<>(QUEUE_SIZE);public DataP…...
win32汇编环境,网络编程入门之二
;运行效果 ;win32汇编环境,网络编程入门之二 ;本教程在前一教程的基础上,研究一下如何得到服务器的返回的信息 ;正常的逻辑是连接上了,然后我发送什么,它返回什么,但是这有一个很尴尬的问题。 ;就是如何表现出来。因为网络可能有延…...
MATLAB—从入门到精通的第二天
在第一天的学习中,我们掌握了 MATLAB 的安装配置、基础语法、变量管理和运算符的使用。本文将深入讲解 控制结构(嵌套 if、switch)、循环类型 和 向量操作,帮助读者进一步掌握 MATLAB 的核心编程技能。 1. 条件语句进阶 1.1 嵌套…...
【认识OpenThread协议】
OpenThread 是一种基于 IPv6 、IEEE 802.15.4 标准的低功耗无线 Mesh 网络协议,主要用于智能家居、物联网设备等场景。它的设计目标是实现设备之间的高效通信、低功耗运行和高可靠性。 OpenThread官方文档 ① 特性 低功耗: 适合电池供电的设备。 Mesh 网络: 支持多…...
驱动开发系列46 - Linux 显卡KMD驱动代码分析(七)- 显存管理
目录 一:概述 二:应用程序和UMD调用栈 三:KMD 显存分配和和映射过程 一:概述 显存管理是图形驱动程序中至关重要的一部分,涉及到从用户空间(UMD,User Mode Driver)到内核空间(KMD,Kernel Mode Driver)的显存分配和管理。本文将首先梳理从一个 OpenGL 应…...
MATLAB代码开发实战:从入门到高效应用
一、MATLAB生态系统的核心优势 (扩展原有内容,增加行业数据) MATLAB在全球工程领域的市场占有率已达67%(2024年IEEE统计),其核心优势体现在: 矩阵运算速度比传统编程快3-5倍包含22个专业工具箱…...
为什么 NFS 不适合作为 TDengine 的数据存储
NFS NFS 是一种分布式文件系统,允许多台计算机通过网络共享文件。其具有以下优点: 共享存储: 多个数据库实例可以共享同一个 NFS 目录,适合分布式数据库或集群环境。灵活性: 数据存储可以集中管理,便于备份和迁移。成本低: 利用…...
办公常用自动化工具
自动化办公工具说明文档 代码全部在底部。 文件批量重命名工具 (file_renamer.py) 功能概述 file_renamer.py 是一个用于批量重命名文件的工具,可以根据自定义规则为文件重命名,支持按日期、序号、原文件名等格式进行命名。 主要功能 支持按文件类…...
字节跳动 —— 建筑物组合(滑动窗口+溢出问题)
原题描述: 题目精炼: 给定N个建筑物的位置和一个距离D,选取3个建筑物作为埋伏点,找出所有可能的建筑物组合,使得每组中的建筑物之间的最大距离不超过D。最后,输出不同埋伏方案的数量并对99997867取模。 识…...
开源数字人模型Heygem
一、Heygem是什么 Heygem 是硅基智能推出的开源数字人模型,专为 Windows 系统设计。基于先进的AI技术,仅需1秒视频或1张照片,能在30秒内完成数字人形象和声音克隆,在60秒内合成4K超高清视频。Heygem支持多语言输出、多表情动作&a…...
Linux远程工具SecureCRT下载安装和使用
SecureCRT下载安装和使用 SecureCRT是一款功能强大的终端仿真软件,它支持SSH、Telnet等多种协议,可以连接和管理基于Unix和Windows的远程主机和网络设备。SecureCRT提供了语法高亮、多标签页管理、会话管理、脚本编辑等便捷功能,安全性高、操…...
从前端视角理解消息队列:核心问题与实战指南
消息队列(Message Queue)是现代分布式系统的核心组件之一,它在前后端协作、系统解耦、流量削峰等场景中发挥着重要作用。本文从前端开发者视角出发,解析消息队列的关键问题,并结合实际场景给出解决方案。 一、为什么要…...
Android 线程池实战指南:高效管理多线程任务
在 Android 开发中,线程池的使用非常重要,尤其是在需要处理大量异步任务时。线程池可以有效地管理线程资源,避免频繁创建和销毁线程带来的性能开销。以下是线程池的使用方法和最佳实践。 1. 线程池的基本使用 (1)创建线…...
CentOS7下安装MongoDB
步骤 1:创建 MongoDB Yum 仓库文件 你需要创建一个 MongoDB 的 Yum 仓库配置文件,以便从官方源下载 MongoDB。打开终端并使用以下命令创建并编辑该文件: sudo vi /etc/yum.repos.d/mongodb-org-7.0.repo 在打开的文件中,输入以下…...
江科大51单片机笔记【15】直流电机驱动(PWM)
写在前言 此为博主自学江科大51单片机(B站)的笔记,方便后续重温知识 在后面的章节中,为了防止篇幅过长和易于查找,我把一个小节分成两部分来发,上章节主要是关于本节课的硬件介绍、电路图、原理图等理论…...
【网络协议详解】——QOS技术(学习笔记)
目录 QoS简介 QoS产生的背景 QoS服务模型 基于DiffServ模型的QoS组成 MQC简介 MQC三要素 MQC配置流程 优先级映射配置(DiffServ域模式) 优先级映射概述 优先级映射原理描述 优先级映射 PHB行为 流量监管、流量整形和接口限速简介 流量监管 流量整形 接口限速…...
【工具使用】IDEA 社区版如何创建 Spring Boot 项目(详细教程)
IDEA 社区版如何创建 Spring Boot 项目(详细教程) Spring Boot 以其简洁、高效的特性,成为 Java 开发的主流框架之一。虽然 IntelliJ IDEA 专业版提供了Spring Boot 项目向导,但 社区版(Community Edition)…...
基于Prometheus+Grafana的Deepseek性能监控实战
文章目录 1. 为什么需要专门的大模型监控?2. 技术栈组成2.1 vLLM(推理引擎层)2.2 Prometheus(监控采集层)2.3 Grafana(数据可视化平台)3. 监控系统架构4. 实施步骤4.1 启动DeepSeek-R1模型4.2 部署 Prometheus4.2.1 拉取镜像4.2.2 编写配置文件4.2.3 启动容器4.3 部署 G…...
Spring学习笔记:工厂模式与反射机制实现解耦
1.什么是Spring? spring是一个开源轻量级的java开发应用框架,可以简化企业级应用开发 轻量级 1.轻量级(对于运行环境没有额外要求) 2.代码移植性高(不需要实现额外接口) JavaEE的解决方案 Spring更像是一种解决方案,对于控制层,它有Spring…...
pytest数据库测试文章推荐
参考链接: 第一部分:http://alextechrants.blogspot.fi/2013/08/unit-testing-sqlalchemy-apps.html第二部分:http://alextechrants.blogspot.fi/2014/01/unit-testing-sqlalchemy-apps-part-2.html...
vue3 二次封装uni-ui中的组件,并且组件中有 v-model 的解决方法
在使用uniappvue3开发中, 使用了uni-ui的组件,但是我们也需要自定义组件,比如我要自定一个picker 的组件, 是在 uni-data-picker 组件的基础上进行封装的 父组件中的代码 <classesselect :selectclass"selectclass"…...
探索高性能AI识别和边缘计算 | NVIDIA Jetson Orin Nano 8GB 开发套件的全面测评
随着边缘计算和人工智能技术的迅速发展,性能强大的嵌入式AI开发板成为开发者和企业关注的焦点。NVIDIA近期推出的Jetson Orin Nano 8GB开发套件,凭借其40 TOPS算力、高效的Ampere架构GPU以及出色的边缘AI能力,引起了广泛关注。本文将从配置性…...
