RabbitMQ快速入门 整合 SpringBoot
RabbitMQ快速入门 整合 SpringBoot
概述
大多应用中,可通过消息服务中间件来提升系统异步通信、扩展解耦能力、流量削峰
消息服务中两个重要概念:
消息代理(`message broker`)和目的地(`destination`)
当消息发送者发送消息以后,将由消息代理接管,消息代理保证消息传递到指定目的地。
消息队列主要有两种形式的目的地
1. 队列(`queue`):点对点消息通信(`point-to-point`)
2. 主题(`topic`):发布(`publish`)/订阅(`subscribe`)消息通信
RabbitMQ 架构图
概念
生产者 Producer
生产者是消息的发送方,它将消息发送到 RabbitMQ 的交换器中。
消息 Message
- 消息=消息头+消息体,根据routekey发送到指定的交换机 Exchange
- 消息头:含有各种属性 routing-key(路由键)、priority(优先级)、delivery-mode(指出该消息可能需要持久性存储)等。
消息代理 Broker
- 消息传递的中间件服务器,负责接收、存储和转发消息,作用类似邮局
- 消息存储+消息路由
- Broker = VHost1+Vhost2+Vhost3+.....
- Virtual Host = Exchange + Queue +Binding
虚拟主机 Virtual Host
逻辑分组机制,将不同的用户、队列、交换器等资源隔离开来
Virtual 即 VHost
默认目录 /
交换机 Exchange
- 绑定 routekey接收消息并发送到符合routekey 的 队列
- 常用三种类型
- dirct:Direct Exchange(直连交换器) 【单播】完全匹配路由键的队列
- fanout:Fanout Exchange(扇出交换器)【广播】消息分发所有绑定队列上,不处理路由键
- topic:Topic Exchange(主题交换器)【模式匹配】
:配置0个或者多个单词
- *:匹配一个单词
- headers:很少使用
- system:很少使用
- dirct:Direct Exchange(直连交换器) 【单播】完全匹配路由键的队列
队列 Queue
- 存储消息的容器,FIFO
- 缓冲消息+持久化
绑定 Binding
- 用于消息队列和交换器之间的关联。
- 一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表。
- Exchange 和Queue的绑定可以是多对多的关系。
连接 Connection
- 网络连接,比如一个TCP连接
信道 Channel
- 信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内的虚拟连接,AMQP 命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说建立和销毁 TCP 都是非常昂贵的开销,所以引入了信道的概念,以复用一条 TCP 连接。
消费者 Consumer
消费者是消息的接收方,它从 RabbitMQ 的队列中获取消息并进行处理。
Docker 安装 RMQ
docker run -d --restart=always --name rabbitmq -p 5671:5671 -p 5672:5672 -p 4369:43699-p25672:25672-p 15671:15671 -p 15672:15672 rabbitmq:management
后台页面收发消息
登录页面
登录的用户密码:guest/guest

登录后台首页

交换机 Exchange页面

五种交换机类型:direct、fanout、headers、topic、x-local-random

队列页面

绑定:交换机根据路由键绑定到对应的队列
Virtual Host【Exchange --> binding(route-key) 】--> Queue(route-key)
默认的虚拟主机的路径是 "/",即根目录
交换机和队列绑定

队列和交换机绑定关系

SpringBoot 整合
配置pom 文件
<!--AMQP依赖,包含RabbitMQ-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
配置application.yaml
server:
port: 8081
spring:
application:
name: rabbitmq-demo
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
virtualHost: /
# publisher-confirm-type: CORRELATED
# publisher-returns: true
# listener:
# simple:
# acknowledge-mode: manual #默认情况下消息消费者是自动确认消息的,如果要手动确认消息则需要修改确认模式为manual
# prefetch: 1 # 消费者每次从队列获取的消息数量。此属性当不设置时为:轮询分发,设置为1为:公平分发
测试类中-创建交换机
@Slf4j
@SpringBootTest
class RabbitmqDemoApplicationTests {
@Autowired
AmqpAdmin amqpAdmin;
@Test
public void createExchange() {
DirectExchange directExchange = new DirectExchange("hello-java-exchange", true, false);
amqpAdmin.declareExchange(directExchange);
log.info("Exchange[hello-java-exchange] 创建完成");
}
}
成功创建
创建队列
@Test
public void createQueue() {
Queue queue = new Queue("hello-java-queue", true, false, false);
amqpAdmin.declareQueue(queue);
log.info("Queue[hello-java-queue] 创建完成");
}
执行后成功创建

创建绑定
@Test
public void Binding() {
Binding binding = new Binding("hello-java-queue",
Binding.DestinationType.QUEUE,
"hello-java-exchange",
"hello-java", null);
amqpAdmin.declareBinding(binding);
log.info("Binding[hello-java-binding] 创建完成");
}
直连交换机【hello-java-exchange】和队列【hello-java-queue】用 routingkey 【hello-java】绑定
队列绑定

交换机绑定

发送消息【JSON消息转换器】
配置 RabbitConfig 序列化 json
根据源码
RabbitAutoConfiguration创建@Bean RabbitTemplate中的消息转换器属性MessageConverter messageConverter = new SimpleMessageConverter();说明了
RabbitMQ自动配置过程中,创建工具类【RabbitTemplate】,其中默认的消息转换器是 【SimpleMessageConverter】,我们来看下【SimpleMessageConverter】源码是如何收发消息的
SimpleMessageConverter创建消息
// 创建消息,默认使用序列化 Serializable类型发送,发送的消息实体需要实现序列化
protected Message createMessage(Object object, MessageProperties messageProperties) throws MessageConversionException {
if (object instanceof byte[] bytes) {
messageProperties.setContentType("application/octet-stream");
} else if (object instanceof String) {
try {
bytes = ((String)object).getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new MessageConversionException("failed to convert to Message content", e);
}
messageProperties.setContentType("text/plain");
messageProperties.setContentEncoding("UTF-8");
} else if (object instanceof Serializable) {
try {
bytes = SerializationUtils.serialize(object);
} catch (IllegalArgumentException e) {
throw new MessageConversionException("failed to convert to serialized Message content", e);
}
messageProperties.setContentType("application/x-java-serialized-object");
}
if (bytes != null) {
messageProperties.setContentLength((long)bytes.length);
return new Message(bytes, messageProperties);
} else {
String var10002 = this.getClass().getSimpleName();
throw new IllegalArgumentException(var10002 + " only supports String, byte[] and Serializable payloads, received: " + object.getClass().getName());
}
}
SimpleMessageConverter消费消息
public Object fromMessage(Message message) throws MessageConversionException {
Object content = null;
MessageProperties properties = message.getMessageProperties();
if (properties != null) {
String contentType = properties.getContentType();
if (contentType != null && contentType.startsWith("text")) {
String encoding = properties.getContentEncoding();
if (encoding == null) {
encoding = this.defaultCharset;
}
try {
content = new String(message.getBody(), encoding);
} catch (UnsupportedEncodingException e) {
throw new MessageConversionException("failed to convert text-based Message content", e);
}
} else if (contentType != null && contentType.equals("application/x-java-serialized-object")) {
try {
content = SerializationUtils.deserialize(this.createObjectInputStream(new ByteArrayInputStream(message.getBody())));
} catch (IllegalArgumentException | IllegalStateException | IOException e) {
throw new MessageConversionException("failed to convert serialized Message content", e);
}
}
}
if (content == null) {
content = message.getBody();
}
return content;
}
自定义消息类型转器 MessageConverter
MessageConverter的层次结构

自定义消息类型转换器
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RabbitMQConfig {
@Bean
public MessageConverter jsonMessageConverter() {
return new Jackson2JsonMessageConverter();
}
}
创建数据:订单退出原因实体对象 注意需要序列化 Serializable
@ToString
@Data
@Accessors(chain = true)
//@TableName("oms_order_return_reason")
public class OrderReturnReasonEntity implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
/**
* 退货原因名
*/
private String name;
/**
* 排序
*/
private Integer sort;
/**
* 启用状态
*/
private Integer status;
/**
* create_time
*/
private Date createTime;
}
测试类中发送消息
@Autowired
RabbitTemplate rabbitTemplate;
@Test
public void sendMessage() {
OrderReturnReasonEntity data = new OrderReturnReasonEntity();
data.setId(1L)
.setCreateTime(new Date())
.setName("测试");
rabbitTemplate.convertAndSend("hello-java-exchange", "hello-java", data);
log.info("发送消息: {}", data);
}
队列收到消息

收到消息对象

{"id":1,"name":"测试","sort":null,"status":null,"createTime":1733484472414}
接收信息
在启动类上添加 @EnableRabbit 开启 RabbitMQ
@EnableRabbit
@SpringBootApplication
public class RabbitmqDemoApplication {
public static void main(String[] args) {
SpringApplication.run(RabbitmqDemoApplication.class, args);
}
}
在需要接收消息的地方添加方法 @RabbitListerner 、@RabbitHandler
@
RabbitListerner:用在类和方法上并绑定对应的队列@
RabbitHandler:用在方法上,可以接收不同的类型的数据
@RabbitListener(queues = {"hello-java-queue"})
@Component
@Slf4j
public class OrderMQHandler {
@RabbitHandler
public void receiveOrderReturnReason(Message message, OrderReturnReasonEntity content, Channel channel) {
//消息体
byte[] body = message.getBody();
//消息头配置
MessageProperties messageProperties = message.getMessageProperties();
log.info("消息体内容:{}", content);
}
@RabbitHandler
public void receiverOrder(OrderEntity content) {
log.info("接收消息=>Order:{}", content);
}
}
成功收到OrderReturnReasonEntity对象数据
2024-12-06T22:46:37.495+08:00 INFO 15808 --- [ntContainer#0-3] c.s.rabbitmqdemo.handler.OrderMQHandler : 消息体内容:OrderReturnReasonEntity(id=1, name=测试-0, sort=null, status=null, createTime=Fri Dec 06 22:46:37 CST 2024)
成功收到OrderEntity对象数据
2024-12-06T22:46:37.522+08:00 INFO 15808 --- [ntContainer#0-3] c.s.rabbitmqdemo.handler.OrderMQHandler : 接收消息=>Order:OrderEntity(id=1, memberId=null, orderSn=null, couponId=null, createTime=Fri Dec 06 22:46:37 CST 2024, memberUsername=测试-1, totalAmount=null, payAmount=null, freightAmount=null, promotionAmount=null, integrationAmount=null, couponAmount=null, discountAmount=null, payType=null, sourceType=null, status=null, deliveryCompany=null, deliverySn=null, autoConfirmDay=null, integration=null, growth=null, billType=null, billHeader=null, billContent=null, billReceiverPhone=null, billReceiverEmail=null, receiverName=null, receiverPhone=null, receiverPostCode=null, receiverProvince=null, receiverCity=null, receiverRegion=null, receiverDetailAddress=null, note=null, confirmStatus=null, deleteStatus=null, useIntegration=null, paymentTime=null, deliveryTime=null, receiveTime=null, commentTime=null, modifyTime=null)
RabbitMQ快速入门 整合 SpringBoot的更多相关文章
- RabbitMQ(一):RabbitMQ快速入门
RabbitMQ是目前非常热门的一款消息中间件,不管是互联网大厂还是中小企业都在大量使用.作为一名合格的开发者,有必要对RabbitMQ有所了解,本文是RabbitMQ快速入门文章. RabbitMQ ...
- 中小研发团队架构实践之RabbitMQ快速入门及应用
原文:中小研发团队架构实践之RabbitMQ快速入门及应用 使用过分布式中间件的人都知道,程序员使用起来并不复杂,常用的客户端API就那么几个,比我们日常编写程序时用到的API要少得多.但是分布式中间 ...
- RabbitMQ快速入门
最近一段项目实践中大量使用了基于RabbitMQ的消息中间件,也积累的一些经验和思考,特此成文,望大家不吝赐教. 本文包括RabbitMQ基本概念.进阶概念.实践与思考等三部分,着重强调相关概念和基于 ...
- RabbitMQ快速入门python教程
摘要:HelloWorld 简介 RabbitMQ:接受消息再传递消息,可以视为一个“邮局”.发送者和接受者通过队列来进行交互,队列的大小可以视为无限的,多个发送者可以发生给一个队列,多个接收者也可以 ...
- RabbitMQ从概念到使用、从Docker安装到RabbitMQ整合Springboot【1.5w字保姆级教学】
@ 目录 一.前言 二.RabbitMQ作用 1. 异步处理 2. 应用解耦 3. 流量控制 三.RabbitMQ概念 1. RabbitMQ简介 2. 核心概念 四.JMS与AMQP比较 五.Rab ...
- RabbitMQ基础入门篇
下载安装 Erlang RabbitMQ 启动RabbitMQ管理平台插件 DOS下进入到安装目录\sbin,执行以下命令 rabbitmq-plugins enable rabbitmq_manag ...
- 消息中间件——RabbitMQ(五)快速入门生产者与消费者,SpringBoot整合RabbitMQ!
前言 本章我们来一次快速入门RabbitMQ--生产者与消费者.需要构建一个生产端与消费端的模型.什么意思呢?我们的生产者发送一条消息,投递到RabbitMQ集群也就是Broker. 我们的消费端进行 ...
- SpringBoot整合ActiveMQ快速入门
Spring Boot 具有如下特性: 为基于 Spring 的开发提供更快的入门体验 开箱即用,没有代码生成,也无需 XML 配置.同时也可以修改默认值来满足特定的需求. 提供了一些大型项目中常见的 ...
- SpringData 基于SpringBoot快速入门
SpringData 基于SpringBoot快速入门 本章通过学习SpringData 和SpringBoot 相关知识将面向服务架构(SOA)的单点登录系统(SSO)需要的代码实现.这样可以从实战 ...
- spring-data-jpa快速入门(一)——整合阿里Druid
一.概述 官网:https://projects.spring.io/spring-data-jpa/ 1.什么是spring-data-jpa Spring Data JPA, part of th ...
随机推荐
- SpringBoot系列:使用原生JDBC实现对数据库的增删改查
application.yml spring: datasource: username: root password: 123456 url: jdbc:mysql://localhost:3306 ...
- MyBatisPlus——标准数据层开发
标准数据层开发 标准数据层CRUD功能 lombok 一个java类库,提供了一组注解,简化POJO实体类开发 常用注解@Data 为当前实体类在编译期设置对应的get/set方法,无参/ ...
- 面试官:谈谈你对 IoC 和 AOP 的理解!
本文摘录自笔者开源的 Java 学习&面试指南(Github 收获146k star):JavaGuide . 这篇文章会从下面从以下几个问题展开对 IoC & AOP 的解释 什么是 ...
- .Net 6 SignalR 实际业务开发中遇到的问题及解决办法
一.SiganlR 使用的协议类型 1.websocket即时通讯协议 2.Server-Sent Events(SSE)服务器事件 3.longpolling 长轮询. 如果客户端开启协商,会按顺序 ...
- 【赵渝强老师】NoSQL数据库之Cassandra基础
一.Cassandra简介 Cassandra是一个混合型的非关系的数据库,类似于Google的BigTable.其主要功能比Dynamo (分布式的Key-Value存储系统)更丰富,但支持度却不如 ...
- 【赵渝强老师】大数据分析引擎:Presto
一.什么是Presto? 背景知识:Hive的缺点和Presto的背景 Hive使用MapReduce作为底层计算框架,是专为批处理设计的.但随着数据越来越多,使用Hive进行一个简单的数据查询可能要 ...
- AMBA总线协议(一)——一文看懂APB总线协议
0.AMBA总线概括 AMBA(Advanced Microcontroller Bus Architecture) 总线是由ARM公司提出的一种开放性的片上总线标准,它独立于处理器和工艺技术,具有高 ...
- 28. 找出字符串中第一个匹配项的下标 Golang实现
题目描述: 给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始).如果 needle 不是 hay ...
- 更强的RAG:向量数据库和知识图谱的结合
传统 RAG 的局限性 经典的 RAG 架构以向量数据库(VectorDB)为核心来检索语义相似性上下文,让大语言模型(LLM)不需要重新训练就能够获取最新的知识,其工作流如下图所示: 这一架构目前广 ...
- 1. react项目【前端】+C#【后端】从0到1
1.创建前端基础框架 1.1 前端创建 软件: 1.1.1 npx create-react-app pc ps:pc 是文件名 : 1.1.2 npm start 启动项目 2.创建后端基础框架 软 ...

