Springboot整合RabbitMQ并使用
1、Springboot整合RabbitMQ
1、引入场景启动器
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
引入AMQP场景启动器之后,RabbitAutoConfiguration就会自动生效。然后会给容器中自动配置了RabbitTemplate、AmqpAdmin、CachingConnectionFactory、RabbitMessagingTemplate等来方便使用AMQP。
2、在yml中配置spring.rabbitmq相关信息
spring:rabbitmq:host: 192.168.56.10port: 5672username: adminpassword: adminvirtual-host: my_vhost
2、简单使用
2.1 创建交换机(Exchange)、队列(Queue)和建立绑定关系(Binding)
@SpringBootTest
public class AmqpAdminTest {@Autowiredprivate AmqpAdmin amqpAdmin;/*** 1、如何创建Exchange、Queue、Binding* 1)、使用AmqpAdmin进行创建*/@Testpublic void creatExchange() {//创建 名为 itcxc.java.direct 的交换机DirectExchange directExchange = new DirectExchange("itcxc.java.direct");amqpAdmin.declareExchange(directExchange);}@Testpublic void creatQueue() {//创建名为 itcxc.java 的队列Queue queue = new Queue("itcxc.java");amqpAdmin.declareQueue(queue);}@Testpublic void creatBinding() {//创建绑定关系 将队列itcxc.java绑定到交换机itcxc.java.direct,routingKey为itcxc.javaBinding binding = new Binding("itcxc.java", Binding.DestinationType.QUEUE,"itcxc.java.direct","itcxc.java",null);amqpAdmin.declareBinding(binding);}
}
2.1.1 交换机类型:

direct:会将消息发送给路由键必须完全匹配的队列中。
fanout:会将消息发送给所有绑定的队列中,不管路由键是否匹配。
topic:主体模式其实就是在路由模式的基础上,支持了对key的通配符匹配(星号以及井号),以满足更加复杂的消息分发场景。(#匹配零个或者多个单词,*匹配一个单词,每个单词用.分割)
2.2 发送消息
@SpringBootTest
public class RabbitTemplateTest {@Autowiredprivate RabbitTemplate rabbitTemplate;/*** 2、如何发消息* 1)、使用rabbitTemplate发送消息*/@Testpublic void sendMessageTest(){OrderReturnReasonEntity orderReturnReasonEntity = new OrderReturnReasonEntity();orderReturnReasonEntity.setId(1L);orderReturnReasonEntity.setName("哈哈");orderReturnReasonEntity.setCreateTime(new Date());//1、发送消息// 默认情况下,如果发送的消息是一个对象,我们会使用序列化机制,将对象写出去,对象必须实现Serializable接口// 但是我们可以通过向容器中注入Jackson2JsonMessageConverter转换器将序列化机制改为转JSONrabbitTemplate.convertAndSend("itcxc.java.direct","itcxc.java", orderReturnReasonEntity);}
}
2.2.1 替换消息系列化方式
通过观看RabbitTemplate的源码发现,我们在默认情况下消息系列化方式是JDK序列化方式。那么我们发送的消息如果是一个对象时,这个对象就必须实现Serializable接口。


如何使用转JSON的方式序列化消息呢?
通过观察RabbitAutoConfiguration源码发现,在创建RabbitTemplate的时候,会从容器中拿消息序列化器(MessageConverter)。

所以我们想要将转JSON的方式序列化消息,只需要给容器中放一个Jackson2JsonMessageConverter就可以了
@Component
public class GulimallRabbitMqConfig {/*** 消息转换器 指定消息转换的方式为转为JSON* @return*/@Beanpublic MessageConverter messageConverter(){return new Jackson2JsonMessageConverter();}}
2.3 获取消息
2.3.1 在启动类或者配置类上添加@EnableRabbit注解
使用@RabbitListener必须开启@EnableRabbit,如果没有使用@RabbitListener可以不添加@EnableRabbit注解。
2.3.2 添加@RabbitListener
@RabbitListener:可以标注在类和方法上 (监听哪些队列)
@RabbitHandler:只能标注在方法上 (重载区别不同的消息)
@Service
public class RabbitListeners {/*** queues:声明需要监听的所有队列** 接收参数的类型:* 1、org.springframework.amqp.core.Message* 2、直接写原来发送的消息类型* 3、Channel 当前传送数据的通道** @param message*/@RabbitListener(queues = {"itcxc.java"})public void receiveMessage(Message message, OrderReturnReasonEntity orderReturnReasonEntity,Channel channel){System.out.println("接收到的消息为:" + orderReturnReasonEntity);}
}
现在有一个情况,就是我们给同一个消息对象发送的消息是有可能不是同一个类型的。例如:
@Test
public void sendMq(){for (int i = 0; i < 10; i++) {if (i % 2 == 0){OrderReturnReasonEntity orderReturnReasonEntity = new OrderReturnReasonEntity();orderReturnReasonEntity.setId(1L);orderReturnReasonEntity.setName("哈哈");orderReturnReasonEntity.setCreateTime(new Date());rabbitTemplate.convertAndSend("itcxc.java.direct","itcxc.java", orderReturnReasonEntity);} else {OrderEntity orderEntity = new OrderEntity();orderEntity.setOrderSn(UUID.randomUUID().toString());rabbitTemplate.convertAndSend("itcxc.java.direct","itcxc.java", orderEntity);}}
}
在这个情况下如果我们还是用原来的方式监听消息的话,就会使发送的消息类型为OrderEntity的消息丢失。

这个时候我们就可以,将@RabbitListener标注在类上,然后@RabbitHandler标注在方法上
@Service
@RabbitListener(queues = {"itcxc.java"})
public class RabbitListeners {/*** queues:声明需要监听的所有队列** 接收参数的类型:* 1、org.springframework.amqp.core.Message* 2、直接写原来发送的消息类型* 3、Channel 当前传送数据的通道** @param message*/@RabbitHandlerpublic void receiveMessage(Message message, OrderReturnReasonEntity orderReturnReasonEntity,Channel channel){System.out.println("接收到的消息为:" + orderReturnReasonEntity);}@RabbitHandlerpublic void receiveMessage(OrderEntity orderEntity){System.out.println("接收到的消息为:" + orderEntity);}
}

3、消息的可靠传递
3.1 发送端确认
为什么会丢失消息?
- 在发送消息到服务端的时候,有可能因为网络等等问题,没有将消息发送到服务端。
- 在
交换机(Exchange)通过路由键将消息发送给队列(Queue)的时候有可能没有找到相应的队列(Queue),而默认情况下是将消息直接丢弃的。
3.1.1 开启confirm和return机制
spring:rabbitmq:# 消息发送到broker后的回调 publisher-confirm-type: correlated# 没有设置mandatory时生效publisher-returns: true# mandatory的优先级高于publisher-returns,只要设置了mandatory,publisher-returns就失效了template:mandatory: true
我翻看源码可以发现mandatory的优先级高于publisher-returns,只要设置了mandatory,publisher-returns就失效了。


但是经过测试,我发现mandatory,只有在publisher-confirm-type、publisher-returns至少有一个设置才会生效。如果mandatory、publisher-returns同时存在的话,则mandatory优先级高于publisher-returns。
3.1.2 添加回调方法
@Component
@RequiredArgsConstructor
public class RabbitMqCallback {private final RabbitTemplate rabbitTemplate;/*** RabbitMqCallback 创建完成之后,执行这个方法* @return*/@PostConstructpublic RabbitTemplate initCallback() {/*** 需要设置spring.rabbitmq.publisher-confirm-type=correlated* 消息发broker成功回调:发送到broker的exchange是否正确找到* correlationData:当前消息的唯一关联数据(这个是消息的唯一ID)* ack:消息是否发送成功* cause:失败的原因,成功则返回null*/rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {System.out.println("setConfirmCallback 消息数据:" + correlationData);if (Objects.nonNull(correlationData)) {System.out.println("setConfirmCallback 消息数据:" + correlationData.getReturnedMessage());}System.out.println("setConfirmCallback 消息确认:" + ack);System.out.println("setConfirmCallback 原因:" + cause);System.out.println("-----------------------------------");});/*** 需要设置spring.rabbitmq.template.mandatory=true或spring.rabbitmq.publisher-returns=true 才会有回调* 消息路由回调:从交换器路由到队列是否正确发送* message:投递失败消息的详细消息* replyCode:回应码* replyText:回应信息* exchange:当时这个消息发送给的交换器* routingKey:当时这个消息发送用的路由键*/rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {System.out.println("setReturnCallback 消息:" + message);System.out.println("setReturnCallback 回应码:" + replyCode);System.out.println("setReturnCallback 回应信息:" + replyText);System.out.println("setReturnCallback 交换器:" + exchange);System.out.println("setReturnCallback 路由键:" + routingKey);System.out.println("-----------------------------------");});return rabbitTemplate;}
}
这样我们就可以知道哪些消息发送成功,哪些消息发送失败了,然后就可以做出相应的处理。
3.2 消费端确认
为什么会丢失消息?
默认情况下只要收到消息,客户端会自动确认,然后服务端就会移除这个消息。由于客户端会一次性接收很多的消息。
在这个情况下,就有可能我们接收了10个消息,只处理了前面2个消息,然后服务宕机了,这样就会使得我们有8个消息丢失。
3.2.1 设置ACK应答机制为手动
spring:rabbitmq:# 设置ACK应答机制为手动listener:simple:acknowledge-mode: manual
手动模式,只要我们没有明确的告诉MQ,消息被签收(没有ACK),消息就是一直处于unacked状态,即使客户端宕机了,消息也不会丢失,会重新变为ready,下次有新的客户端连接进来就发给新的客户端。
3.2.2 处理完消息之后手动应答
@RabbitListener(queues = {"itcxc.java"})public void receiveMessage(Message message, OrderReturnReasonEntity orderReturnReasonEntity,Channel channel) throws IOException {//deliveryTag通道(channel)内自增的long deliveryTag = message.getMessageProperties().getDeliveryTag();System.out.println("方法一deliveryTag为"+deliveryTag+"接收到的消息为:" + orderReturnReasonEntity);//确认签收参数说明(deliveryTag,是否批量签收)channel.basicAck(deliveryTag,false);//拒绝签收参数说明(deliveryTag,是否批量签收,是否放回队列中)//channel.basicNack(deliveryTag,false,true);}
相关文章:
Springboot整合RabbitMQ并使用
1、Springboot整合RabbitMQ 1、引入场景启动器 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId> </dependency>引入AMQP场景启动器之后,RabbitAutoConfiguratio…...
Java中方法引用(引用静态方法、引用成员方法(引用其他类的成员方法、引用本类的成员方法、引用父类的成员方法)、引用构造方法、其他调用方式、小练习)
方法引用:把已经存在的方法拿过来用,当作函数式接口中抽象方法的方法体 我们前面学到Arrays工具类中的sort方法,当我们需要指定排序规则时,需要传递Comparator接口的实现类对象,我们之前使用匿名内部类类的形式作为参…...
整理了100道关于Python基础知识的练习题,记得收藏~
实例1.数字组合 题目: 有四个数字:1、2、3、4,能组成多少个互不相同且无重复数字的三位数?各是多少? 程序分析: 遍历全部可能,把有重复的剃掉。 total0 for i in range(1,5):for j in range(…...
OSG三维渲染引擎编程学习之七十七:“第七章:OSG场景图形交互” 之 “7.8 场景交互”
目录 第七章 OSG场景图形交互 7.8 场景交互 7.8.1 osgGA库 7.8.2 事件消息处理 7.8.3 程序抓图示例...
797.差分
输入一个长度为 n的整数序列。 接下来输入 m个操作,每个操作包含三个整数 l,r,c,表示将序列中 [l,r] 之间的每个数加上 c。 请你输出进行完所有操作后的序列。 输入格式 第一行包含两个整数 n和 m。 第二行包含 n个整数,表示整数序列。 …...
为什么说要慎用BeanUtils,因为性能真的拉跨
1 背景之前在专栏中讲过“不推荐使用属性拷贝工具”,推荐直接定义转换类和方法使用 IDEA 插件自动填充 get / set 函数。不推荐的主要理由是:有些属性拷贝工具性能有点差有些属性拷贝工具有“BUG”使用属性拷贝工具容易存在一些隐患(后面例子…...
【项目设计】高并发内存池(六)[细节优化+测试]
🎇C学习历程:入门 博客主页:一起去看日落吗持续分享博主的C学习历程博主的能力有限,出现错误希望大家不吝赐教分享给大家一句我很喜欢的话: 也许你现在做的事情,暂时看不到成果,但不要忘记&…...
同模块设置不同应用主题方案
有时候公司内部会有不同应用但是有部分模块功能一样,只根据应用角色有些细节逻辑区分的场景。这时候往往采用模块化采用以应用至不同的APP。如果APP主题不一致,该如果解决。 方案: 在不同应用的config.gradle 下面根据不同应用定义不同的a…...
centos7 安装 hyperf
PHP > 7.4 Swoole PHP 扩展 > 4.5,并关闭了 Short Name OpenSSL PHP 扩展 JSON PHP 扩展 PDO PHP 扩展 Redis PHP 扩展 Protobuf PHP 扩展 composer create-project hyperf/hyperf-skeleton 推荐安装项 全部选n php.ini [swoole] extens…...
RZ/G2UL核心板-40℃低温启动测试
1. 测试对象HD-G2UL-EVM基于HD-G2UL-CORE工业级核心板设计,一路千兆网口、一路CAN-bus、 3路TTL UART、LCD、WiFi、CSI 摄像头接口等,接口丰富,适用于工业现场应用需求,亦方便用户评估核心板及CPU的性能。HD-G2UL-CORE系列工业级核…...
PyQt5可视化 7 饼图和柱状图实操案例 ①Qt项目的创建
目录 一、新建Qt项目 二、添加组件和布局 三、添加资源 1. 新建资源文件 2. 添加图标资源 四、frameHead 1. toolBtnGenData 2. toolBtnCounting 3. comboTheme 4. comboAnimation 5. Horizontal Spacer 6. toolBtnQuit 7. 设置toolBtnQuit的功能 8. frameHead的…...
0104路径搜索和单点路径-无向图-数据结构和算法(Java)
文章目录2 单点路径2.1 API2.2 算法实现后记2 单点路径 单点路径。给定一幅图和一个起点s,回答“从s到给定的目的顶点v是否存在一条路径?如果有,找出这条路径。”等类似问题。 2.1 API 单点路径问题在图的处理邻域中十分重要。根据标准设计…...
Maxscale读写分离实施文档
Maxscale介绍 MaxScale是maridb开发的一个mysql数据中间件,其配置简单,能够实现读写分离,并且可以根据主从状态实现写库的自动切换。 使用Maxscale无需对业务代码进行修改,其自带的读写分离模块,能够解析SQL语句&…...
websocket实现一个简单聊天框
websoket在客户端的使用 事件:open/message/error/close 方法:send/close var socket new WebSocket(url)// 服务连接成功时触发 socket.addEventListener(open, function() {console.log("连接成功了") })// 主动给websocket发消息 socket…...
Docker-安装应用
一、安装Tomcat 注意:新版Tomcat安装之后启动访问会出现404 修改:删除原有的webapps目录,修改webapps.dist为webapps 免修改版本:billygoo/tomcat8-jdk8 二、安装Mysql 1、安装 拉取镜像 docker pull mysql:5.7 运行镜像…...
Web3中的营销:如何在2023年获得优势
Mar. 2022, Daniel在过去的一年里,让人们对你的Web3项目或协议感兴趣已经变得越来越有挑战性。许多曾经充满希望的项目因为各种不同的原因,都在熊市中倒下了。然而,那些迄今为止幸存下来的项目都有一个共同点:强大的社区。Web3营销…...
Java中==和equals区别
文章目录Java中和equals区别1. Integer中和equals的问题1.1 Integer类型且不是通过new创建的比较1.2 手动new Integer()创建的比较1.3 Integer和int比较2. String中和equals的问题3. DemoJava中和equals区别 equals是方法,是运算符: 如果比较的对象是基…...
计算机科学导论笔记(三)
五、计算机组成 计算机组成部件可以分为三大类(子系统):中央处理单元(CPU)、主存储器和输入/输出子系统。 5.1 中央处理单元(CPU) 中央处理单元用于数据的运算,分为算术逻辑单元&a…...
Stream——数字类型的字符串排序
文章目录前言什么是数字类型的字符串一个简单的坑demo拯救坑代码对象集合中的数字类型排序(有坑)对象集合中的数字类型排序 解决扩展将数字类型字符串数组转换为Integer集合总结前言 想到给数据进行排序,一开始头脑中想到的就是sorted(),本篇文章重点说…...
.NET 8 预览版 1 发布!
.NET 8 是一个长期支持(LTS) 版本。这篇文章涵盖了推动增强功能优先级排序和选择开发的主要主题和目标。.NET 8 预览版和发布候选版本将每月交付一次。像往常一样,最终版本将在 11 月的某个时候在 .NET Conf 上发布。 .NET 版本包括产品、库、运行时和工具…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
