当前位置: 首页 > news >正文

Springboot整合RabbitMQ并使用

1、Springboot整合RabbitMQ

1、引入场景启动器

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

引入AMQP场景启动器之后,RabbitAutoConfiguration就会自动生效。然后会给容器中自动配置了RabbitTemplateAmqpAdminCachingConnectionFactoryRabbitMessagingTemplate等来方便使用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,只要设置了mandatorypublisher-returns就失效了。

在这里插入图片描述
在这里插入图片描述
但是经过测试,我发现mandatory,只有在publisher-confirm-typepublisher-returns至少有一个设置才会生效。如果mandatorypublisher-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场景启动器之后&#xff0c;RabbitAutoConfiguratio…...

Java中方法引用(引用静态方法、引用成员方法(引用其他类的成员方法、引用本类的成员方法、引用父类的成员方法)、引用构造方法、其他调用方式、小练习)

方法引用&#xff1a;把已经存在的方法拿过来用&#xff0c;当作函数式接口中抽象方法的方法体 我们前面学到Arrays工具类中的sort方法&#xff0c;当我们需要指定排序规则时&#xff0c;需要传递Comparator接口的实现类对象&#xff0c;我们之前使用匿名内部类类的形式作为参…...

整理了100道关于Python基础知识的练习题,记得收藏~

实例1.数字组合 题目&#xff1a; 有四个数字&#xff1a;1、2、3、4&#xff0c;能组成多少个互不相同且无重复数字的三位数&#xff1f;各是多少&#xff1f; 程序分析&#xff1a; 遍历全部可能&#xff0c;把有重复的剃掉。 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个操作&#xff0c;每个操作包含三个整数 l,r,c&#xff0c;表示将序列中 [l,r] 之间的每个数加上 c。 请你输出进行完所有操作后的序列。 输入格式 第一行包含两个整数 n和 m。 第二行包含 n个整数&#xff0c;表示整数序列。 …...

为什么说要慎用BeanUtils,因为性能真的拉跨

1 背景之前在专栏中讲过“不推荐使用属性拷贝工具”&#xff0c;推荐直接定义转换类和方法使用 IDEA 插件自动填充 get / set 函数。不推荐的主要理由是&#xff1a;有些属性拷贝工具性能有点差有些属性拷贝工具有“BUG”使用属性拷贝工具容易存在一些隐患&#xff08;后面例子…...

【项目设计】高并发内存池(六)[细节优化+测试]

&#x1f387;C学习历程&#xff1a;入门 博客主页&#xff1a;一起去看日落吗持续分享博主的C学习历程博主的能力有限&#xff0c;出现错误希望大家不吝赐教分享给大家一句我很喜欢的话&#xff1a; 也许你现在做的事情&#xff0c;暂时看不到成果&#xff0c;但不要忘记&…...

同模块设置不同应用主题方案

有时候公司内部会有不同应用但是有部分模块功能一样&#xff0c;只根据应用角色有些细节逻辑区分的场景。这时候往往采用模块化采用以应用至不同的APP。如果APP主题不一致&#xff0c;该如果解决。 方案&#xff1a; 在不同应用的config.gradle 下面根据不同应用定义不同的a…...

centos7 安装 hyperf

​​​​​​PHP > 7.4 Swoole PHP 扩展 > 4.5&#xff0c;并关闭了 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工业级核心板设计&#xff0c;一路千兆网口、一路CAN-bus、 3路TTL UART、LCD、WiFi、CSI 摄像头接口等&#xff0c;接口丰富&#xff0c;适用于工业现场应用需求&#xff0c;亦方便用户评估核心板及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&#xff0c;回答“从s到给定的目的顶点v是否存在一条路径&#xff1f;如果有&#xff0c;找出这条路径。”等类似问题。 2.1 API 单点路径问题在图的处理邻域中十分重要。根据标准设计…...

Maxscale读写分离实施文档

Maxscale介绍 MaxScale是maridb开发的一个mysql数据中间件&#xff0c;其配置简单&#xff0c;能够实现读写分离&#xff0c;并且可以根据主从状态实现写库的自动切换。 使用Maxscale无需对业务代码进行修改&#xff0c;其自带的读写分离模块&#xff0c;能够解析SQL语句&…...

websocket实现一个简单聊天框

websoket在客户端的使用 事件&#xff1a;open/message/error/close 方法&#xff1a;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在过去的一年里&#xff0c;让人们对你的Web3项目或协议感兴趣已经变得越来越有挑战性。许多曾经充满希望的项目因为各种不同的原因&#xff0c;都在熊市中倒下了。然而&#xff0c;那些迄今为止幸存下来的项目都有一个共同点&#xff1a;强大的社区。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是方法&#xff0c;是运算符&#xff1a; 如果比较的对象是基…...

计算机科学导论笔记(三)

五、计算机组成 计算机组成部件可以分为三大类&#xff08;子系统&#xff09;&#xff1a;中央处理单元&#xff08;CPU&#xff09;、主存储器和输入/输出子系统。 5.1 中央处理单元&#xff08;CPU&#xff09; 中央处理单元用于数据的运算&#xff0c;分为算术逻辑单元&a…...

Stream——数字类型的字符串排序

文章目录前言什么是数字类型的字符串一个简单的坑demo拯救坑代码对象集合中的数字类型排序(有坑)对象集合中的数字类型排序 解决扩展将数字类型字符串数组转换为Integer集合总结前言 想到给数据进行排序&#xff0c;一开始头脑中想到的就是sorted()&#xff0c;本篇文章重点说…...

.NET 8 预览版 1 发布!

.NET 8 是一个长期支持(LTS) 版本。这篇文章涵盖了推动增强功能优先级排序和选择开发的主要主题和目标。.NET 8 预览版和发布候选版本将每月交付一次。像往常一样&#xff0c;最终版本将在 11 月的某个时候在 .NET Conf 上发布。 .NET 版本包括产品、库、运行时和工具&#xf…...

Zotero PDF Translate插件深度解析:全面解决自动翻译失效的技术方案

Zotero PDF Translate插件深度解析&#xff1a;全面解决自动翻译失效的技术方案 【免费下载链接】zotero-pdf-translate 支持将PDF、EPub、网页内容、元数据、注释和笔记翻译为目标语言&#xff0c;并且兼容20多种翻译服务。 项目地址: https://gitcode.com/gh_mirrors/zo/zo…...

歌词滚动姬:从零开始制作专业LRC歌词的终极指南

歌词滚动姬&#xff1a;从零开始制作专业LRC歌词的终极指南 【免费下载链接】lrc-maker 歌词滚动姬&#xff5c;可能是你所能见到的最好用的歌词制作工具 项目地址: https://gitcode.com/gh_mirrors/lr/lrc-maker 你是否曾经为喜爱的歌曲制作歌词时&#xff0c;因为时间…...

文墨共鸣详细步骤:为文墨共鸣添加PDF上传与段落级语义比对功能扩展

文墨共鸣详细步骤&#xff1a;为文墨共鸣添加PDF上传与段落级语义比对功能扩展 1. 项目概述与功能扩展 文墨共鸣是一个将深度学习算法与传统水墨美学相结合的语义相似度分析系统。原本系统支持文本输入比对&#xff0c;本次扩展新增了两个重要功能&#xff1a; PDF文档上传解…...

Wireshark实战:如何用ARP协议抓包分析局域网通信(附常见问题排查)

Wireshark深度解析&#xff1a;ARP协议抓包实战与网络故障排查指南 在中小型企业网络运维中&#xff0c;ARP协议引发的通信问题往往是最隐蔽却又最频繁的故障源。想象这样一个场景&#xff1a;财务部的打印机突然无法连接&#xff0c;市场部的共享文件夹时断时续&#xff0c;而…...

Symfony Translation错误处理终极指南:7个实用异常处理技巧

Symfony Translation错误处理终极指南&#xff1a;7个实用异常处理技巧 【免费下载链接】translation symfony/translation: 是一个用于 PHP 的翻译库&#xff0c;支持多种消息源和翻译格式&#xff0c;可以用于构建多语言的 Web 应用程序和 API。 项目地址: https://gitcode…...

M2LOrder服务高可用部署架构:基于Kubernetes的容器编排方案

M2LOrder服务高可用部署架构&#xff1a;基于Kubernetes的容器编排方案 最近在星图GPU平台上折腾M2LOrder服务的部署&#xff0c;发现单实例运行虽然简单&#xff0c;但一遇到流量高峰或者节点故障&#xff0c;服务就很容易挂掉&#xff0c;严重影响稳定性。对于生产环境来说&…...

从提示词到交响曲:一文读懂AI音乐生成的技术、应用与未来

从提示词到交响曲&#xff1a;一文读懂AI音乐生成的技术、应用与未来 引言 想象一下&#xff0c;只需在输入框里键入“一段激昂的中国风电子游戏Boss战音乐”&#xff0c;几分钟后&#xff0c;一段融合了琵琶、电吉他、密集鼓点与磅礴管弦乐的完整配乐便跃然耳畔。这不再是科…...

Dify向量检索效果差?不是Embedding问题,是Rerank架构缺陷!资深MLOps架构师带你手绘6层重排序决策流图

第一章&#xff1a;Dify向量检索效果差的真相溯源Dify 默认采用的向量检索机制看似开箱即用&#xff0c;但实际在中文长文本、领域术语密集或语义歧义显著的场景中常出现召回率低、相关性错位等问题。其根源并非模型能力不足&#xff0c;而是多个隐性配置与数据处理环节协同失配…...

StructBERT零样本分类-中文-base开源镜像部署:低成本GPU显存优化方案(<3GB)

StructBERT零样本分类-中文-base开源镜像部署&#xff1a;低成本GPU显存优化方案&#xff08;<3GB&#xff09; 你是不是也遇到过这样的烦恼&#xff1f;手头有一堆中文文本需要快速分类——可能是用户评论、新闻稿件&#xff0c;或者是客服对话——但既没有现成的标签数据…...

seo搜索引擎排名影响因素主要有

好的&#xff0c;以下是一些主要的SEO搜索引擎排名影响因素&#xff1a; 关键词密度和分布&#xff1a;关键词在网页中的使用频率和分布是影响搜索引擎排名的因素之一。关键词密度的合适范围是2%-8%&#xff0c;一般来说&#xff0c;保持在5%-7%的关键词密度是比较理想的。关键…...