创建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 {
    @Autowired
    private 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 {
    @Bean
    public DirectExchange testExchange() {
        return new DirectExchange("test.exchange");
    }

    @Bean
    public Queue testQueue() {
        return new Queue("test.queue");
    }

    @Bean
    public Binding testBinding() {
        return BindingBuilder.bind(testQueue()).to(testExchange()).with("test.routingKey");
    }
}

写SpringBoot启动主类

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

/**
 * @author xuan
 * @create 2024/4/25
 */
@SpringBootApplication
public class Application implements CommandLineRunner {
    @Autowired
    private MessageSender messageSender;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    public 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.mfbz.cn/a/580228.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

决策树模型示例

通过5个条件判定一件事情是否会发生&#xff0c;5个条件对这件事情是否发生的影响力不同&#xff0c;计算每个条件对这件事情发生的影响力多大&#xff0c;写一个决策树模型pytorch程序,最后打印5个条件分别的影响力。 一 决策树模型是一种非参数监督学习方法&#xff0c;主要…

Java高阶私房菜:JVM垃圾回收机制及算法原理探究

目录 垃圾回收机制 什么是垃圾回收机制 JVM的自动垃圾回收机制 垃圾回收机制的关键知识点 初步了解判断方法-引用计数法 GCRoot和可达性分析算法 什么是可达性分析算法 什么是GC Root 对象回收的关键知识点 标记对象可回收就一定会被回收吗&#xff1f; 可达性分析算…

使用R语言进行简单的因子分析

在本文中&#xff0c;将介绍如何使用R语言进行因子分析&#xff0c;并通过一个示例演示整个过程。因子分析是一种多元统计分析方法&#xff0c;用于探索变量之间的潜在结构和关系。R语言提供了丰富的统计工具和包&#xff0c;使因子分析的实现变得简单而高效。 准备工作 首先…

c++中的链表list的模拟实现

拖更了半个月&#xff0c;我终于来填c的坑啦。上次我们说的vetcor不知道小伙伴还记得多少呢&#xff1f;今天我们要讲list的模拟实现。 目录 架构结点list表的结构 构造函数尾插push_back()尾删pop_back()计算个数&#xff1a;size()判断空empty()※迭代器问题普通迭代器迭代器…

数据结构:实验六:图的操作

一、 实验目的 &#xff08;1&#xff09;掌握图的邻接矩阵和邻接表存储结构。 &#xff08;2&#xff09;熟练图的邻接表的基本运算。 &#xff08;3&#xff09;加深图的深度优先遍历算法和广度优先遍历算法的理解 二、 实验要求 有下图所示的带权有向图及其对应的邻…

【Python时序预测系列】麻雀算法(SSA)优化LSTM实现单变量时间序列预测(源码)

这是我的第269篇原创文章。 一、引言 麻雀算法&#xff08;Sparrow Search Algorithm&#xff0c;SSA&#xff09;是一种基于麻雀群体行为的算法&#xff0c;它可以用来优化深度学习模型中的参数。在优化LSTM模型时&#xff0c;可以通过麻雀算法来调整LSTM的参数&#xff0c;以…

亚马逊测评的目的是什么?

测评的目的&#xff1a;店铺销量、留评 特别是新品&#xff0c;一个产品销量很低也没什么评价的产品&#xff0c;很难说服真实买家们&#xff0c;因为同类目还有其他的选择&#xff0c;不管是谁都不愿意当小白鼠的&#xff0c;而且打造爆款&#xff0c;提升产品权重这些都离不…

【华为】SVI接口实验配置

【华为】SVI接口实验配置 拓扑实验要求设备核心交换机PCPC1PC2 查看VLAN验证 配置文档 拓扑 实验要求 一台三层交换机&#xff0c;两台PC PC1 和 PC2 静态获取地址&#xff0c;并处于不同VLAN 然后PC的网关是处在三层交换机LSW1身上&#xff0c;不同VLAN就是处在不同网段&…

Jenkins - macOS 上安装

文章目录 关于 JenkinsmacOS 上安装 Jenkins方式一&#xff1a;brew方式二&#xff1a;tomcat Jenkins war 关于 Jenkins 官网上下载Jenkins并将其安装到持续集成服务器 https://jenkins.io/download/ macOS 上安装 Jenkins 现在本 macOS 上测试 https://www.jenkins.io/do…

HarmonyOS 应用开发——入门

首先当然是华为的官方文档了&#xff0c;要认真学习: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/start-overview-0000001478061421-V2 不想花时间看&#xff0c;可以看我下面总结的干货&#xff0c;哈哈 第一个问题&#xff1a;stage架构和fa架构的区…

MySql 导出导入(备份还原)

1&#xff0c;导出备份 要导出MySQL数据库中的数据&#xff0c;使用mysqldump命令。假设要导出名为mydatabase的数据库到名为backup.sql的文件中&#xff1a; mysqldump -u 用户名 -p 数据库名 > backup.sql 参数说明&#xff1a; -u mysql用户名称 -p 执行后会要求输入…

文献阅读:全皮层原位测序揭示了输入依赖区域的身份

文献介绍 「文献题目」 Whole-cortex in situ sequencing reveals input-dependent area identity 「研究团队」 Anthony M. Zador&#xff08;美国冷泉港实验室&#xff09; 「发表时间」 2024-04-24 「发表期刊」 Nature 「影响因子」 64.8 「DOI」 10.1038/s41586-024-0…

LeetCode39题: 组合总和(原创)

【题目描述】 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以按 任意顺序 返回这些组合。candidates 中的 同一个 数字可以 无限制重复…

回归预测 | Matlab实现NGO-ESN北方苍鹰算法优化回声状态网络多输入单输出回归预测

回归预测 | Matlab实现NGO-ESN北方苍鹰算法优化回声状态网络多输入单输出回归预测 目录 回归预测 | Matlab实现NGO-ESN北方苍鹰算法优化回声状态网络多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现NGO-ESN北方苍鹰算法优化回声状态网络…

C++(Qt)软件调试---crashpad捕获崩溃(19)

C(Qt)软件调试—crashpad捕获崩溃&#xff08;19&#xff09; 文章目录 C(Qt)软件调试---crashpad捕获崩溃&#xff08;19&#xff09;1、概述2、资源地址3、配置环境4、解决报错5、测试代码6、测试结果7、Qt中使用crashpad 更多精彩内容&#x1f449;个人内容分类汇总 &#x…

mysql 开启远程连接

登录到mysql mysql -uroot -p 打开mysql数据库并查询user表 use mysql; select user, host from user;更改需要远程连接数据库为任何ip 可以连接&#xff0c; 并刷新系统权限相关的表 update user set host% where hostlocalhost and userroot; flush privileges;

测评与广告双管齐下:敦煌网卖家如何结合自养号实现快速出单

敦煌网作为中国领先的B2B跨境电商平台&#xff0c;为卖家提供了广阔的市场和丰富的资源&#xff0c;但为何有些卖家却难以获得订单呢?下面的内容中&#xff0c;帮助卖家快速出单。 一、如何快速出单? 1、优化产品详情页&#xff1a;产品详情页是吸引买家下单的关键页面。卖…

Shell脚本编写-猜测当前系统是哪个发行版

1、编写脚本 该脚本会确定当前系统中可用的包管理器。同时还以已安装的软件包管理器为指导&#xff0c;猜测当前系统是基于哪个 Linux 发行版。 #!/bin/bash #检查当前系统的可用包管理器&#xff0c;以安装的软件包管理器为指导&#xff0c;猜测当前的系统是基于哪个Linux发行…

顺序表常用操作实现算法

查找操作 插入操作 删除操作 小结 参考附录模拟代码&#xff1a; #include <iostream> const int maxn200; //顺序表 typedef struct{//定义静态类型 int num[maxn];// 装数数组 int len;//记录长度 }sqlist; typedef struct{//定义动态类型 int *num;int len; }sqlist…

XYCTF 2024

本博客仅为记录解题的过程&#xff01; MISC game google识图 XYCTF{Papers Please} 熊博士 XYCTF{liu_ye_mei_you_xiao_jj} 疯狂大杂烩&#xff01;九转功成 在远古时期&#xff0c;修仙过程被分为&#xff1a;炼气、筑基、结丹、元婴、化神、炼虚、合体、大乘、渡劫等九…