14. Springboot集成RabbitMQ

目录

1、前言

2、什么是RabbitMQ

3、安装RabbitMQ

4、Springboot集成RabbitMQ

4.1、添加依赖

4.2、添加配置

4.3、添加controller,作为生产者

4.4、设置生产者消息确认CallBack

4.5、添加Consumer,作为消费者

4.6、启动程序,访问


1、前言

消息队列(Message Queue,简称 MQ)是一种异步的消息传递中间件,它解耦了应用程序之间的通信。应用程序可以将消息发送到队列,而无需知道谁会接收这些消息。接收应用程序可以从队列中检索消息,而无需知道谁发送了这些消息。消息队列是一种重要的中间件,它可以帮助应用程序之间进行异步、可靠、可扩展的通信。常见的消息队列中间件有ActiveMQ,RabbitMQ,Kafka......今天我们就来介绍RabbitMQ。

2、什么是RabbitMQ

RabbitMQ 是一个开源的消息队列服务器,它实现了 AMQP (高级消息队列协议) 标准。AMQP 是一种应用层协议,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。

AMQP :Advanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。

RabbitMQ 的主要特点包括:

  • 高性能:RabbitMQ 能够处理大量的消息,并提供低延迟的性能。
  • 可靠性:RabbitMQ 提供持久化消息存储,确保消息不会丢失。
  • 可扩展性:RabbitMQ 可以轻松扩展以满足不断增长的需求。
  • 灵活性:RabbitMQ 支持多种编程语言和客户端,并提供丰富的功能和配置选项。

RabbitMQ 的常见应用场景包括:

  • 分布式系统:RabbitMQ 可以用于在分布式系统中进行异步通信。
  • 异步处理:RabbitMQ 可以用于异步处理任务,提高系统的性能和效率。
  • 消息队列:RabbitMQ 可以用于实现消息队列,例如任务队列、发布/订阅队列等。
  • 消息通知:RabbitMQ 可以用于发送消息通知,例如电子邮件或短信。

3、安装RabbitMQ

由于RabbitMQ是一个由 Erlang 语言开发的 AMQP 的开源实现。所以在安装RabbitMQ前需要先安装Erlang环境。

Erlang下载地址:Downloads - Erlang/OTP

RabbitMQ下载地址:Installing RabbitMQ | RabbitMQ

先安装Erlang,在安装RabbitMQ。安装工程相对简单,无脑下一步即可。

安装完RabbitMQ后,打开cmd窗口,进入RabbitMQ的安装目录的sbin下,我的目录是:

D:\RabbitMQ Server\rabbitmq_server-3.13.0\sbin

然后输入以下命令安装一下插件:

rabbitmq-plugins enable rabbitmq_management

提示以下这个就是安装成功。

验证RabbitMQ是否安装成功,输入以下命令:

rabbitmqctl status

这时候,直接访问http://127.0.0.1:15672就可以看到RabbitMQ的管理页面了,RabbitMQ默认端口为15672,默认的管理页面账号密码均为guest。

登录后,就可以看到一个初始的管理界面:

4、Springboot集成RabbitMQ

4.1、添加依赖

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>springboot-rabbitmq</artifactId><version>0.0.1-SNAPSHOT</version><name>springboot-rabbitmq</name><description>springboot-rabbitmq</description><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.24</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

4.2、添加配置

# rabbitmq连接配置信息
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest# 确保消息在未被队列接收时返回
spring.rabbitmq.publisher-returns=true
# 发布消息成功到交换器后会触发回调方法
spring.rabbitmq.publisher-confirm-type=correlated

4.3、添加controller,作为生产者

新建controller,用于发送消息。

package com.example.springbootrabbitmq.controller;import com.example.springbootrabbitmq.config.MqProducerCallBack;
import jakarta.annotation.Resource;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("push/message")
public class PushMessageController {@Resourceprivate RabbitTemplate rabbitTemplate;@Resourceprivate MqProducerCallBack mqProducerCallBack;@GetMapping("test")public String sendMessage() {// correlationData:对象内部只有一个 id 属性,用来表示当前消息的唯一性。CorrelationData correlationData = new CorrelationData("id_" + System.currentTimeMillis());// 消息确认和返回回调rabbitTemplate.setConfirmCallback(mqProducerCallBack);rabbitTemplate.setReturnsCallback(mqProducerCallBack);// 消息发送rabbitTemplate.convertAndSend("my-queue", "hello world", message -> {message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);return message;}, correlationData);return "publisher success...";}
}

4.4、设置生产者消息确认CallBack

package com.example.springbootrabbitmq.config;import cn.hutool.json.JSONUtil;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;@Component
public class MqProducerCallBack implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnsCallback {/*** correlationData:对象内部只有一个 id 属性,用来表示当前消息的唯一性。* ack:消息投递到broker 的状态,true成功,false失败。* cause:投递失败的原因。*/@Overridepublic void confirm(CorrelationData correlationData, boolean ack, String cause) {if (!ack) {System.err.println("消息ID=" + correlationData.getId() + "投递失败,失败原因:" + cause);} else {System.out.println("消息投递收到确认,correlationData=" + correlationData.getId());}}@Overridepublic void returnedMessage(ReturnedMessage returnedMessage) {System.out.println("返回消息结果:" + JSONUtil.toJsonStr(returnedMessage));}}

4.5、添加Consumer,作为消费者

package com.example.springbootrabbitmq.consumer;import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;import java.io.IOException;@Component
public class PushMessageConsumer {/*** basicAck:表示成功确认,使用此回执方法后,消息会被rabbitmq broker 删除。* void basicAck(long deliveryTag, boolean multiple)* deliveryTag:表示消息投递序号,每次消费消息或者消息重新投递后,deliveryTag都会增加。手动消息确认模式下,我们可以对指定deliveryTag的消息进行ack、nack、reject等操作。* multiple:是否批量确认,值为 true 则会一次性 ack所有小于当前消息 deliveryTag 的消息。* */@RabbitListener(queuesToDeclare = @Queue(value = "my-queue"))@RabbitHandlerpublic void consume(String msg, Channel channel, Message message) throws IOException {try {System.out.println("消费者收到消息:" + msg);channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);System.out.println("deliveryTag:" + message.getMessageProperties().getDeliveryTag());System.out.println("redelivered:" + message.getMessageProperties().getRedelivered());} catch (Exception e) {if (message.getMessageProperties().getRedelivered()) {System.err.println("消息已重复处理失败,拒绝再次接收!");/*** 拒绝消息,requeue=false 表示不再重新入队,如果配置了死信队列则进入死信队列* basicReject:拒绝消息,与basicNack区别在于不能进行批量操作,其他用法很相似。* deliveryTag:表示消息投递序号。* requeue:值为 true 消息将重新入队列。*/channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);} else {System.out.println("消息即将再次返回队列处理!");/*** requeue为是否重新回到队列,true重新入队* deliveryTag:表示消息投递序号。* multiple:是否批量确认。* requeue:值为 true 消息将重新入队列。*/channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);}}}}

4.6、启动程序,访问

浏览器访问:http://localhost:8080/push/message/test 模拟消息进行推送。

查看控制台,发现消费者正常打印出了消费信息。

打开RabbitMQ管理控制台,可以发现我们的消息队列my-queue信息。

既可以查看消息队列的装填,消息投递情况等。

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

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

相关文章

【C++】类和对象(四千字解析超完整附实例!!!不看会后悔!!!)

新学期开始了&#xff0c;c课程逐渐深入&#xff0c;今天来了解一下c的类和对象中的封装与数据的初始化和清理&#xff01; PS.本博客参考b站up黑马程序员的相关课程&#xff0c;老师讲得非常非常好&#xff01; 封装 封装是C面向对象三大特性之一 1.封装的意义一&#xff1…

国家中英文名称、国家代码(地区代码)、国家域名、经纬度

因为要做世界地图对世界国家的标点&#xff0c;搜索使用到了世界各个国家的地理位置信息&#xff0c;此处做备份与学习。资源地址&#xff08;免费&#xff09; export default {"阿尔巴尼亚": {"m_longitude": "19.809","m_latitude&quo…

聚类分析|基于层次的聚类方法及其Python实现

聚类分析|基于层次的聚类方法及其Python实现 0. 基于层次的聚类方法1. 簇间距离度量方法1.1 最小距离1.2 最大距离1.3 平均距离1.4 中心法1.5 离差平方和 2. 基于层次的聚类算法2.1 凝聚&#xff08;Agglomerative&#xff09;2.3 分裂&#xff08;Divisive&#xff09; 3. 基于…

JavaScript 学习日记(1)---初识JavaScript

初识JavaScript 文章目录 初识JavaScript一、JavaScript 是什么?二、java 和JavaScript 的关系三、JavaScript 的组成四、JS的基本输入输出 ---> 单行注释五、js变量基本概念六、js基本数据类型七、js转义字符八、js类型转换九、运算符 END! 一、JavaScript 是什么? 我们…

沪漂8年回郑州三年如何走上创业之路

大家好&#xff0c;我是大牛&#xff0c;目前人在郑州。 现在标签是&#xff1a; 创业者&#x1f697;&#x1f438; (注册有自己的公司&#xff0c;主要是为了自己的产品和接外包项目)独立开发者&#x1f468;&#x1f3fb;&#x1f4bb; (有自己的小项目)数字游民&…

干货分享之反射笔记

入门级笔记-反射 一、利用反射破泛型集合二、Student类三、获取构造器的演示和使用1.getConstructors只能获取当前运行时类的被public修饰的构造器2.getDeclaredConstructors:获取运行时类的全部修饰符的构造器3.获取指定的构造器3.1得到空构造器3.2得到两个参数的有参构造器&a…

Quartus II仿真出现错误

ModelSim executable not found in D:/intelFPGA/18.0/quartus/bin64/modelsim_ase/win32aloem/ Error. 找不到modelsim地址&#xff0c;原来是我下载了.exe,但没有双击启动安装ase文件夹呀&#xff01;&#xff01;&#xff01;&#xff01;晕&#xff0c;服了我自己

常见测试技术都有哪些?

测试技术是用于评估系统或组件的方法&#xff0c;目的是发现它是否满足给定的要求。系统测试有助于识别缺口、错误&#xff0c;或与实际需求不同的任何类型的缺失需求。测试技术是测试团队根据给定的需求评估已开发软件所使用的最佳实践。这些技术可以确保产品或软件的整体质量…

前端面试拼图-数据结构与算法(二)

摘要&#xff1a;最近&#xff0c;看了下慕课2周刷完n道面试题&#xff0c;记录下... 1. 求一个二叉搜索树的第k小值 二叉树(Binary Tree) 是一棵树 每个节点最多两个子节点 树节点的数据结构{value, left?, right?} 二叉树的遍历 前序遍历&#xff1a;root→left→right 中…

视觉轮速滤波融合1讲:理论推导

视觉轮速滤波融合理论推导 文章目录 视觉轮速滤波融合理论推导1 坐标系2 轮速计2.1 运动学模型2.2 外参 3 状态和协方差矩阵3.1 状态3.2 协方差矩阵 4 Wheel Propagation4.1 连续运动学4.2 离散积分4.2.1 状态均值递推4.2.2 协方差递推 5 Visual update5.1 视觉残差与雅可比5.2…

【C语言】【Leetcode】70. 爬楼梯

文章目录 题目思路&#xff1a;简单递归 > 动态规划 题目 链接: link 思路&#xff1a;简单递归 > 动态规划 这题类似于斐波那契数列的算法&#xff0c;结果其实就是到达前一步和到达前两步的方法之和&#xff0c;一直递归到n1和n2时就行了&#xff0c;但是这种算法有个…

今天聊聊Docker

在数字化时代&#xff0c;软件应用的开发和部署变得越来越复杂。环境配置、依赖管理、版本控制等问题给开发者带来了不小的挑战。而Docker作为一种容器化技术&#xff0c;正以其独特的优势成为解决这些问题的利器。本文将介绍Docker的基本概念、优势以及应用场景&#xff0c;帮…

C++基础之继承续(十六)

一.基类与派生类之间的转换 可以把派生类赋值给基类可以把基类引用绑定派生类对象可以把基类指针指向派生类对象 #include <iostream>using std::cin; using std::cout; using std::endl;//基类与派生类相互转化 class Base { private:int _x; public:Base(int x0):_x(…

Amuse .NET application for stable diffusion

Amuse github地址&#xff1a;https://github.com/tianleiwu/Amuse .NET application for stable diffusion, Leveraging OnnxStack, Amuse seamlessly integrates many StableDiffusion capabilities all within the .NET eco-system Welcome to Amuse! Amuse is a profes…

CAPL - 如何实现弹窗提示和弹窗操作(续)

目录 函数介绍 openPanel closePanel 代码示例 1、简单的打开关闭panel面板

自动驾驶-如何进行多传感器的融合

自动驾驶-如何进行多传感器的融合 附赠自动驾驶学习资料和量产经验&#xff1a;链接 引言 自动驾驶中主要使用的感知传感器是摄像头和激光雷达&#xff0c;这两种模态的数据都可以进行目标检测和语义分割并用于自动驾驶中&#xff0c;但是如果只使用单一的传感器进行上述工作…

文献速递:文献速递:基于SAM的医学图像分割--SAM-Med3D

Title 题目 SAM-Med3D 01 文献速递介绍 医学图像分析已成为现代医疗保健不可或缺的基石&#xff0c;辅助诊断、治疗计划和进一步的医学研究]。在这一领域中最重要的挑战之一是精确分割体积医学图像。尽管众多方法在一系列目标上展现了值得称赞的有效性&#xff0c;但现有的…

C/C++ 语言中的 ​if...else if...else 语句

C/C 语言中的 ​if...else if...else 语句 1. if statement2. if...else statement3. if...else if...else statementReferences 1. if statement The syntax of the if statement is: if (condition) {// body of if statement }The code inside { } is the body of the if …

javaScript——BFS结合队列求迷宫最短路径

这里推荐先去看下B站这个老师讲的BFS迷宫问题&#xff0c;只用看前五分钟就能懂用BFS队列实现的原理。[POJ] 3984 迷宫问题 BFS_哔哩哔哩_bilibili 问题描述&#xff1a;由m*n的矩阵构成了一个迷宫&#xff0c; 矩阵中为1的元素表示障碍物&#xff0c;不能走&#xff0c;为0表示…

AcWing 830. 单调栈

解题思路 对于将要入栈的元素来说&#xff0c;在对栈进行更新后&#xff08;即弹出了所有比自己大的元素&#xff09;&#xff0c;此时栈顶元素就是数组中左侧第一个比自己小的元素&#xff1b; 对于将要入栈的元素来说&#xff0c;在对栈进行更新后&#xff08;即弹出了所有比…