创建SpringBoot和RabbitMQ的整合项目

文章目录

  • 创建SpringBoot和RabbitMQ的整合项目
    • 首先快速创建一个maven项目
    • 引入SpringBoot整合rabbitMQ的依赖
    • 在src/main目录下创建resources目录并引入配置文件
    • 写消息发送者MessageSender
    • 写消息接收者MessageReceiver
    • 写RabbitMQConfig配置类
    • 写SpringBoot启动主类
    • CommandLineRunner接口的作用
    • 启动程序 查看效果
    • 注意要点
      • 15672和5672的区别
      • 消息发送的队列怎么找
    • 我们的消息发送者和消息接收者可以只开启一个
      • 只开启消息发送者先存一些消息到消息队列
      • 只开启消息接收者从消息队列里面读取消息
    • 接下来我们来看一下RabbitMQ中怎么控制一个线程一次消费的消息数,主要是看下concurrency关键属性

创建SpringBoot和RabbitMQ的整合项目

首先快速创建一个maven项目

如下图:
在这里插入图片描述

引入SpringBoot整合rabbitMQ的依赖

如下图:
在这里插入图片描述
这里要SpringBoot和RabbitMQ整合的依赖对应的就是spring-boot-starter-amqp,那么amqp是什么意思呢?是Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,是面向消息的中间件设计。比如RabbitMQ消息中间件使用的就是这个协议。
因为我们要启动服务,因此需要有tomcat服务器,因此这里还要引入spring-boot-starter-web模块依赖,因为SpringBoot自带的tomcat服务器在web模块里面。

<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>org.example</groupId><artifactId>rabbitMQ</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><name>rabbitMQ</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.7</version></parent><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>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency></dependencies>
</project>

在src/main目录下创建resources目录并引入配置文件

如下图:
在这里插入图片描述

写消息发送者MessageSender

如下图:
在这里插入图片描述

/*** @author xuan* @create 2024/4/25*/
@Component
public class MessageSender {@Autowiredprivate AmqpTemplate rabbitTemplate;public void sendMessage(String exchange, String routingKey, Object message) {rabbitTemplate.convertAndSend(exchange, routingKey, message);}
}

写消息接收者MessageReceiver

如下图:
在这里插入图片描述

/*** @author xuan* @create 2024/4/25*/
@Component
public class MessageReceiver {@RabbitListener(queues = "test.queue")public void handleMessage(Object message) {System.out.println("Received message: " + message);}
}

写RabbitMQConfig配置类

如下图:
在这里插入图片描述

/*** @author xuan* @create 2024/4/25*/
@Configuration
public class RabbitMQConfig {@Beanpublic DirectExchange testExchange() {return new DirectExchange("test.exchange");}@Beanpublic Queue testQueue() {return new Queue("test.queue");}@Beanpublic Binding testBinding() {return BindingBuilder.bind(testQueue()).to(testExchange()).with("test.routingKey");}
}

写SpringBoot启动主类

如下图:
在这里插入图片描述

/*** @author xuan* @create 2024/4/25*/
@SpringBootApplication
public class Application implements CommandLineRunner {@Autowiredprivate MessageSender messageSender;public static void main(String[] args) {SpringApplication.run(Application.class, args);}@Overridepublic void run(String... args) throws Exception {messageSender.sendMessage("test.exchange", "test.routingKey", "Hello, RabbitMQ!");}
}

CommandLineRunner接口的作用

从上面的SpringBoot启动类可以看到,它实现了CommandLineRunner接口,实现了这个接口中的抽象方法run,那么CommandLineRunner接口又什么作用呢?它主要是用在SpringBoot的启动主类上的,主要作用是在SpringBoot应用程序启动之后执行一些任务,比如:

  • 数据初始化:加载初始数据到数据库或其他存储系统中。
  • 发送通知:向用户或系统发送启动通知,例如通过邮件或消息队列。
  • 执行检查:进行应用程序启动前的检查,如数据库连接检查、文件系统检查等。

比如我们上面的主类在成功启动SpringBoot的应用程序之后 就会给RabbitMQ消息队列发送一个消息。

启动程序 查看效果

启动主类之后 控制台输出如下图:
在这里插入图片描述
这里我们主要看消息体Body的内容,可以发现是Hello RabbitMQ。后面是消息的一些属性 类似如我们的http协议中的request请求头的信息,包括消息的内容类型了,消息的内容编码了,消息的长度了等信息。

可以发现我们这里测试成功了。

注意要点

15672和5672的区别

RabbitMQ前端管理界面使用的端口号是15672,比如我们启动rabbitmq之后,在浏览器中输入127.0.0.1:15672可以进入rabbitmq的前端页面管理器中进行相关操作,如下图:
在这里插入图片描述
但是后端服务器的rabbitmq在电脑上启动的端口号是5672,如下图:
在这里插入图片描述
这两个端口号特别容易搞错,千万要注意,如果配置文件里的端口号写15672,那么我们的idea里面的java程序就连接不上我们本地已经启动的rabbitmq服务器了。

消息发送的队列怎么找

通过RabbitMQ中的交换机Exchange,和路由RouteingKey可以唯一的定位到一个消息队列Queue,如下图:
在这里插入图片描述
在这里插入图片描述

因此我们代码里面发送者发送消息的时候,一定要指定使用的交换机和使用的路由,但不用指定使用的队列,因为有交换机和路由之后就会自动的映射到使用的队列了,看下代码如下图:
在这里插入图片描述
但是我们需要通过一个配置类配置一下 需要告诉java程序,如下图:
在这里插入图片描述
然后接收者接收消息的时候 可以直接指定test.queue队列,就可以自动的去这个队列中取出消息了。不用写交换机和路由的具体信息。下面看下接收者的处理 如下图:
在这里插入图片描述

但是我觉得RabbitMQ应该是会有线程安全问题的,比如说因为目前看来同一个队列 两个不同的线程都是可以访问的,那这样的话有共享资源问题 就肯定会出现线程安全问题。

我们的消息发送者和消息接收者可以只开启一个

只开启消息发送者先存一些消息到消息队列

比如我们可以先用消息发送者往RabbitMQ的消息队列test.queue里面发送三条消息,此时注意关闭消息接收者,以免接收者直接读取队列里面的消息,我们在页面上就看不到效果了,如下图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

只开启消息接收者从消息队列里面读取消息

接下来我们把消息发送者关了,把消息接收者打开,去消费队列里面的消息,如下图:
在这里插入图片描述
在这里插入图片描述
看下启动应用程序之后的效果 如下图:
在这里插入图片描述

接下来我们来看一下RabbitMQ中怎么控制一个线程一次消费的消息数,主要是看下concurrency关键属性

通过concurrency属性来控制线程从队列中一次性读取的消息个数。如果我们把属性concurrency的值设置为1 那么就表示一个线程一次性会从队列里面读取一条消息;如果把这个值设置成3 那么就表示一个线程一次性会从队列里面读取3条消息;concurrency的书写位置如下图:
在这里插入图片描述
据我的观察,RabbitMQ内部应该有线程安全机制,就是在当前线程读取消费队列消息没有完成的时候,另外的线程是不能消费队列消息的。

现在我们模拟两个线程,而我们具体的模拟方式其实是重新复制一个项目,然后改下端口号为8081,接着我们把给队列发送消息的代码注释掉 只开启接收者从消息队列里面读取消息 过程如下图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

上面是我们模拟的第一个线程,其实也就是copy一个相同的项目 改下端口号 启动的时候就是不同的线程了。

然后启动第二个线程,发送6条消息到消息队列中,如下图:
在这里插入图片描述
那么这个时候呢?线程一就会先读取消息队列的第一条消息,线程二此时会在线程一后面排队,当线程一处理完消息之后,线程二会去读取消息队列里面的消息,然后线程一读取…。因此正常情况的输出是 其中一个应用程序中 输出的是编号1,3,5的消息,另外一个应用程序中输出的是编号2,4,6的消息。如下图:
在这里插入图片描述
在这里插入图片描述
确实是正常的。

现在我们把concurrency线程一次性最多读取的消息个数改成4,看下控制台输出结果,如下图:
在这里插入图片描述
在这里插入图片描述
可以看到第一个线程一次性会读取消息队列的前四条消息,而第二个线程本来也会读取四条 但是队列中只剩两条消息,因此第二个线程就一次性的读取两条消息了。
但是有个线程安全问题。就是你会发现第一个线程虽然读取的确实是队列里面的前四条消息,但是呢?消费消息的时候却不是按队列里面添加消息的顺序,这可能就会出现问题了。比如假如说队列里面按照先后顺序添加了两条消息,1穿装,2脱装。但是线程读取消息之后 先消费处理的可能是2脱装,那是不是就会出现问题了?因为你玩家身上现在根本就没有装备 你要怎么脱呢?因此当concurrency设置的值超过1的时候都可能会出现消息消费顺序有误的问题。

因此我们如果想要保证消费的消息严格的按照队列里面添加的消息顺序来执行,那么必须要把concurrency设置成1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/829749.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【黑马点评Redis——002商户查询缓存】

1. 商户查询缓存 2. 知识储备和课程内容 2.1 什么是缓存 缓存是数据交换的缓冲区&#xff0c;是存贮数据的临时地方&#xff0c;一般读写性能较高。 浏览器缓存应用层缓存数据库缓存CPU缓存磁盘缓存 缓存的作用&#xff1a; 降低后端负载提高读写效率&#xff0c;降低响应…

B站无限评论暴力截留协议及教程

B站无限评论暴力截留协议及教程 B站无限评论暴力截留协议及教程&#xff0c;需要抓CK &#xff0c;教程里面有讲如何抓取 网盘自动获取 链接&#xff1a;https://pan.baidu.com/s/1lpzKPim76qettahxvxtjaQ?pwd0b8x 提取码&#xff1a;0b8x

springboot路劲映射

般情况下&#xff0c;使用了页面模板后&#xff0c;用户需要通过控制器才能访问页面。有一些页面需要在控制器中加载数据&#xff0c;然后渲染&#xff0c;才能显示出来;还有一些页面在控制器中不需要加载数据&#xff0c;只是完成简单的跳转&#xff0c;对于这种页面&#xff…

C++:week1:C语言基础

文章目录 (一) C语言概述1.预处理指令&#xff1a;宏定义、宏函数2.生成可执行程序的过程3.进程与虚拟内存空间 (二) 格式化输入输出1.变量及命名2.格式化输入输出、输入输出模型(1)CPU、内存、外部设备的速度矛盾(2)printf(3)scanf 3.代码即注释4.程序出错的原因、调试程序5.其…

提示词优化的自动化探索:Automated Prompt Engineering

编者按&#xff1a; 作者在尝试教授母亲使用 LLM 完成工作任务时&#xff0c;意识到提示词的优化并不像想象中简单。提示词的自动优化对于经验并不丰富的提示词撰写者很有价值&#xff0c;他们没有足够的经验去调整和改进提供给模型的提示词&#xff0c;这引发了对自动化提示词…

C++学习之指针和引用

指针 指针是一个变量&#xff0c;其值为另一个变量的地址&#xff0c;即&#xff0c;内存位置的直接地址。就像其他变量或常量一样&#xff0c;您必须在使用指针存储其他变量地址之前&#xff0c;对其进行声明。指针变量声明的一般形式为&#xff1a; type *var-name; 在这里…

kotlin 编写一个简单的天气预报app (七)使用material design

一、优化思路 对之前的天气预报的app进行了优化&#xff0c;原先的天气预报程序逻辑是这样的。 使用text和button组合了一个输入城市&#xff0c;并请求openweathermap对应数据&#xff0c;并显示的功能。 但是搜索城市的时候&#xff0c;可能会有错误&#xff0c;比如大小写…

steam打不开没反应 steam客户端启动不了一直无响应的解决方法

steam打不开没反应 steam客户端启动不了一直无响应的解决方法 steam这个平台想必各位游戏爱好者们肯定不会陌生&#xff0c;作为全球最大的游戏服务平台&#xff0c;steam不仅为玩家们提供了全面的游戏服务&#xff0c;还经常给玩家们提供各种游戏优惠&#xff0c;并且每年四…

【综述】DSP处理器芯片

文章目录 TI DSP C2000系列 TMS320F28003X 典型应用 开发工具链 参考资料 TI DSP TI C2000系列 控制领域 TI C5000系列 通信领域 TI C6000系列 图像领域 C2000系列 第三代集成了C28浮点DSP内核&#xff0c;采用了65nm工艺&#xff08;上一代180nm&#xff09; 第四代正在…

无人零售与传统便利店的竞争优势

无人零售与传统便利店的竞争优势 成本控制 • 无人零售 显著降低了人力成本&#xff0c;无需支付店员薪资和相关福利&#xff0c;且通过智能化管理减少能源消耗与维护费用&#xff0c;尤其在高租金和高人流区域效益突出。 • 传统便利店 则承担较高的人员开支&#xff0c;…

chrome 查看版本安装路径、cmd命令行启动浏览器

chrome 查看版本安装路径 浏览器输入 chrome://version/cmd命令行启动浏览器 "C:\Program Files\Google\Chrome\Application\chrome.exe" www.baidu.com

恒峰智慧科技—高扬程水泵:解决远距离输水难题的新选择!

在森林消防领域&#xff0c;水泵是一个至关重要的设备。它的主要功能是将水源输送到火灾现场&#xff0c;为消防人员提供足够的水源进行灭火。然而&#xff0c;传统的水泵往往面临着距离限制的问题&#xff0c;这对于远距离输水来说是一个巨大的挑战。幸运的是&#xff0c;高扬…

Jenkins构建触发器-Git hook自动触发构建

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 Jenkins是一个开源…

《苍穹外卖》Day10部分知识点记录

一、Spring Task 介绍 Spring Task是Spring框架提供的任务调度工具&#xff0c;可以按照约定的时间自动执行某个代码逻辑。 定位&#xff1a;定时任务框架 作用&#xff1a;定时自动执行某段Java代码 应用场景&#xff1a;只要是需要定时处理的场景都可以使用Spring Task …

2024腾讯游戏安全技术竞赛-机器学习赛道

决赛赛题链接https://gss.tencent.com/competition/2024/doc/2024%E8%85%BE%E8%AE%AF%E6%B8%B8%E6%88%8F%E5%AE%89%E5%85%A8%E6%8A%80%E6%9C%AF%E7%AB%9E%E8%B5%9B-%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0-%E5%86%B3%E8%B5%9B.zip 今年的题目是游戏跨语言恶意内容识别 ,题目比较…

技术速递|利用 Redis 使 AI 驱动的 .NET 应用程序更加一致和智能

作者&#xff1a;Catherine Wang 排版&#xff1a;Alan Wang Redis 是一种流行的内存数据存储&#xff0c;可用于解决构建和扩展智能应用程序的关键挑战。在本文中&#xff0c;你将了解如何使用 Redis 的 Azure 缓存来提高使用 Azure OpenAI 的应用程序的效率。 Redis 的 Azur…

西电超算使用方法-简易版

一、引言 西电超算不错&#xff0c;我很喜欢。本文仅供自己学习使用。 二、环境搭建 搭建环境需要有一些依赖库&#xff0c;但是其实西电超算说明手册并没有写的非常清楚。因此&#xff0c;这次实战演示一下&#xff0c;写一个运行sh文件脚本并提交作业。 1、选择GPU还是CP…

AI赋能分层模式,解构未来,智领风潮

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 &#x1f680; 转载自热榜文章&#x1f525;&#xff1a;探索设计模式的魅力&#xff1a;AI赋能分…

人脸识别概念解析

目录 1. 概述 2. 人脸检测 3. 人脸跟踪 4. 质量评价 5. 活体检测 6. 特征提取 7. 人脸验证 8. 人脸辨识 1. 概述 人脸识别在我们的生活中随处可见&#xff0c;例如在大楼门禁系统中&#xff0c;它取代了传统的门禁卡或密码&#xff0c;提高了进出的便捷性和安全性。在商…

【Linux】基础指令

文章目录 基础指令1. pwd 指令2. cd 指令3. ls 指令4. touch 指令5. mkdir 指令6. rmdir 和 rm 指令7. man 指令8. cp 指令9. mv 指令10. cat 指令11. more 和 less 指令12. head 和 tail 指令13. date 指令14. cal 指令15. find 指令16. grep 指令18. zip 和 unzip 指令19. ta…