RabbitMQ学习笔记(二)SpringAMQP的使用、消息转换器

2024-06-04 13:20

本文主要是介绍RabbitMQ学习笔记(二)SpringAMQP的使用、消息转换器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 前言
  • 3 SpringAMQP
    • 3.1 介绍
    • 3.2 简单队列模型
    • 3.3 工作队列模型
    • 3.4 发布/订阅模型
      • 3.4.1 Fanout广播模型
      • 3.4.2 Direct定向模型
      • 3.4.3 Topic通配符模型
    • 3.5 消息转换器

前言

RabbitMQ学习笔记(一)RabbitMQ部署、5种队列模型

3 SpringAMQP

3.1 介绍

AMQP(Advanced Message Queuing Protocol),是一个应用程序之间传递业务消息的标准高级消息队列协议。基于此协议的客户端与消息中间件可传递消息,并不受不同的开发语言等条件的限制。

SpringAMQP是基于AMQP协议定义的一套RabbitMQ模板,并且利用SpringBoot对其实现了自动装配,使用起来非常方便。SpringAmqp的官方地址:https://spring.io/projects/spring-amqp。

SpringAMQP主要提供了三个功能:

  • 自动声明队列、交换机及其绑定关系
  • 基于注解的监听器模式,异步接收消息
  • 封装了RabbitTemplate工具,用于发送消息

3.2 简单队列模型

  • 1)引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
  • 2)在application.yml文件中配置RabbitMQ
spring:rabbitmq:host: 192.168.153.128port: 5672virtual-host: /username: rabbitmqpassword: 123321
  • 3)利用RabbitTemplate实现消息发送
@Autowired
private RabbitTemplate rabbitTemplate;@Test
public void testSimpleQueue() {// 队列名称String queueName = "simple.queue";// 消息String message = "hello, spring amqp!";// 发送消息rabbitTemplate.convertAndSend(queueName, message);
}

执行以上单元测试,在RabbitMQ管理页面查看队列中的消息:

  • 4)利用RabbitListener实现消息接收
@Component
public class SpringRabbitListener {@RabbitListener(queues = "simple.queue")public void listenSimpleQueueMessage(String msg) throws InterruptedException {System.out.println("spring 消费者接收到消息:【" + msg + "】");}
}
  • 5)测试结果

3.3 工作队列模型

工作队列模型即让多个消费者绑定到一个队列,共同消费队列中的消息。

  • 1)利用RabbitTemplate和循环实现消息批量发送
@Autowired
private RabbitTemplate rabbitTemplate;@Test
public void testWorkQueue() {// 队列名称String queueName = "work.queue";// 发送消息String message = "hello, work queue ";for (int i = 0; i < 50; i++) {rabbitTemplate.convertAndSend(queueName, message + i);}
}

执行以上单元测试,在RabbitMQ管理页面查看队列中的消息:

  • 2)利用RabbitListener实现消息接收,模拟工作队列
@Component
public class SpringRabbitListener {@RabbitListener(queues = "work.queue")public void listenWorkQueueMessage1(String msg) {System.out.println("work.queue监听器1:" + msg);}@RabbitListener(queues = "work.queue")public void listenWorkQueueMessage2(String msg) {System.out.println("work.queue监听器2:" + msg);}
}
  • 3)测试结果

3.4 发布/订阅模型

由上图可知,发布/订阅模型包含的角色如下:

  • Publisher:生产者,但其消息不再直接发送到队列中,而是发给exchange(交换机)。
  • Exchange:交换机。一方面,接收生产者发送的消息。另一方面,决定如何处理消息,例如递交给某个特别队列、递交给所有队列、或是将消息丢弃。到底如何操作,取决于Exchange的类型。Exchange有以下3种类型:
    • Fanout:广播,将消息发送给所有绑定到交换机的队列。
    • Direct:定向,把消息发送符合指定routing key的队列。
    • Topic:通配符,把消息发送给符合routing pattern(路由模式)的队列。
  • Consumer:消费者,与其他模型一样。
  • Queue:消息队列,与其他模型一样。

需要注意的是,Exchange(交换机)只负责转发消息,不具备存储消息的能力,因此如果没有任何队列与Exchange绑定,或者没有符合路由规则的队列,那么消息会丢失!

3.4.1 Fanout广播模型

在Fanout广播模型中,Exchange(交换机)会将消息发送给所有绑定到交换机的队列。

  • 1)声明交换机和队列,及其绑定关系
@Configuration
public class FanoutConfig {/*** 声明交换机*/@Beanpublic FanoutExchange fanoutExchange() {return new FanoutExchange("star.fanout");}/*** 第1个队列*/@Beanpublic Queue fanoutQueue1(){return new Queue("fanout.queue1");}/*** 绑定队列1和交换机*/@Beanpublic Binding bindingQueue1(Queue fanoutQueue1, FanoutExchange fanoutExchange){return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);}/*** 第2个队列*/@Beanpublic Queue fanoutQueue2(){return new Queue("fanout.queue2");}/*** 绑定队列2和交换机*/@Beanpublic Binding bindingQueue2(Queue fanoutQueue2, FanoutExchange fanoutExchange){return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);}
}
  • 2)利用RabbitTemplate发送消息到交换机
@Autowired
private RabbitTemplate rabbitTemplate;@Test
public void testFanoutExchange() {// 队列名称String exchangeName = "star.fanout";// 消息String message = "hello, fanout!";rabbitTemplate.convertAndSend(exchangeName, "", message);
}
  • 3)利用RabbitListener接收消息
@RabbitListener(queues = "fanout.queue1")
public void listenFanoutQueue1(String msg) {System.out.println("消费者1接收到Fanout消息:【" + msg + "】");
}@RabbitListener(queues = "fanout.queue2")
public void listenFanoutQueue2(String msg) {System.out.println("消费者2接收到Fanout消息:【" + msg + "】");
}
  • 4)测试结果

3.4.2 Direct定向模型

在Direct定向模型中,Exchange(交换机)会把消息发送符合指定routing key的队列。

因此,交换机与队列与的绑定,不再是任意绑定,而是要指定一个RoutingKey(路由key);生产者在向Exchange发送消息时,也必须指定消息的RoutingKey

只有队列的RoutingKey与消息的RoutingKey完全一致时,才会接收到消息。

  • 1)声明交换机和队列,及其绑定关系与RoutingKey

在Fanout广播模型的案例中,使用的是@Bean的方式声明队列和交换机,比较麻烦。Spring还提供了基于注解方式来声明:

@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue1"),exchange = @Exchange(name = "star.direct", type = ExchangeTypes.DIRECT),key = {"red", "blue"}
))
public void listenDirectQueue1(String msg){System.out.println("消费者1接收到Direct的消息:【" + msg + "】");
}@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue2"),exchange = @Exchange(name = "star.direct", type = ExchangeTypes.DIRECT),key = {"red", "yellow"}
))
public void listenDirectQueue2(String msg){System.out.println("消费者2接收到Direct的消息:【" + msg + "】");
}
  • 2)利用RabbitTemplate发送消息到交换机
@Autowired
private RabbitTemplate rabbitTemplate;@Test
public void testDirectExchange() {// 队列名称String exchangeName = "star.direct";// 消息String message = "新的风暴已经出现!";rabbitTemplate.convertAndSend(exchangeName, "yellow", message);
}
  • 3)测试结果

3.4.3 Topic通配符模型

Topic通配符模型和Direct定向模型一样,都是可以根据RoutingKey把消息路由到不同的队列,只不过Topic通配符模型的RoutingKey可以使用通配符!

Routingkey一般都是有一个或多个单词组成,多个单词之间以.分割,而通配符规则如下:

  • #:匹配一个或多个词
  • *:匹配恰好1个词

例如:

  • item.#:能够匹配item.insert.user 或者 item.insert

  • item.*:只能匹配item.insert

  • 1)声明交换机和队列,及其绑定关系与RoutingKey

@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "topic.queue1"),exchange = @Exchange(name = "star.topic", type = ExchangeTypes.TOPIC),key = {"item.#"}
))
public void listenTopicQueue1(String msg){System.out.println("消费者1接收到Topic的消息:【" + msg + "】");
}@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "topic.queue2"),exchange = @Exchange(name = "star.topic", type = ExchangeTypes.TOPIC),key = {"item.*"}
))
public void listenTopicQueue2(String msg){System.out.println("消费者2接收到Topic的消息:【" + msg + "】");
}
  • 2)利用RabbitTemplate发送消息到交换机
@Autowired
private RabbitTemplate rabbitTemplate;@Test
public void testTopicExchange() {String exchangeName = "star.topic";String message = "新增用户!";rabbitTemplate.convertAndSend(exchangeName, "item.insert.user", message);String message2 = "新增***!";rabbitTemplate.convertAndSend(exchangeName, "item.insert", message2);
}
  • 3)测试结果

3.5 消息转换器

在调用RabbitTemplate的convertAndSend()方法时,Spring会把发送的消息序列化为字节发送给MQ,接收消息时还会把字节反序列化为Java对象。

默认情况下Spring采用的序列化方式是JDK序列化。而这种方式存在下列问题:数据体积过大、有安全漏洞、可读性差。

例如执行以下单元测试:

@Test
public void testSendMap() throws InterruptedException {Map<String,Object> msg = new HashMap<>();msg.put("name", "Jack");msg.put("age", 21);rabbitTemplate.convertAndSend("simple.queue","", msg);
}

在RabbitMQ管理页面查看消息:

显然,可读性非常差。JDK序列化方式并不好用。而要使可读性更高,可以使用JSON方式来做序列化和反序列化。

  • 1)引入依赖
<dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-xml</artifactId><version>2.9.10</version>
</dependency>
  • 2)配置消息转换器,在启动类中添加一个Bean
@Bean
public MessageConverter jsonMessageConverter(){return new Jackson2JsonMessageConverter();
}
  • 3)再次测试

本节完,更多内容请查阅分类专栏:微服务学习笔记

感兴趣的读者还可以查阅我的另外几个专栏:

  • SpringBoot源码解读与原理分析
  • MyBatis3源码深度解析
  • Redis从入门到精通
  • MyBatisPlus详解
  • SpringCloud学习笔记

这篇关于RabbitMQ学习笔记(二)SpringAMQP的使用、消息转换器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1030197

相关文章

Spring IoC 容器的使用详解(最新整理)

《SpringIoC容器的使用详解(最新整理)》文章介绍了Spring框架中的应用分层思想与IoC容器原理,通过分层解耦业务逻辑、数据访问等模块,IoC容器利用@Component注解管理Bean... 目录1. 应用分层2. IoC 的介绍3. IoC 容器的使用3.1. bean 的存储3.2. 方法注

Python内置函数之classmethod函数使用详解

《Python内置函数之classmethod函数使用详解》:本文主要介绍Python内置函数之classmethod函数使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录1. 类方法定义与基本语法2. 类方法 vs 实例方法 vs 静态方法3. 核心特性与用法(1编程客

Linux中压缩、网络传输与系统监控工具的使用完整指南

《Linux中压缩、网络传输与系统监控工具的使用完整指南》在Linux系统管理中,压缩与传输工具是数据备份和远程协作的桥梁,而系统监控工具则是保障服务器稳定运行的眼睛,下面小编就来和大家详细介绍一下它... 目录引言一、压缩与解压:数据存储与传输的优化核心1. zip/unzip:通用压缩格式的便捷操作2.

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互

Python中注释使用方法举例详解

《Python中注释使用方法举例详解》在Python编程语言中注释是必不可少的一部分,它有助于提高代码的可读性和维护性,:本文主要介绍Python中注释使用方法的相关资料,需要的朋友可以参考下... 目录一、前言二、什么是注释?示例:三、单行注释语法:以 China编程# 开头,后面的内容为注释内容示例:示例:四

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

ModelMapper基本使用和常见场景示例详解

《ModelMapper基本使用和常见场景示例详解》ModelMapper是Java对象映射库,支持自动映射、自定义规则、集合转换及高级配置(如匹配策略、转换器),可集成SpringBoot,减少样板... 目录1. 添加依赖2. 基本用法示例:简单对象映射3. 自定义映射规则4. 集合映射5. 高级配置匹

Spring 框架之Springfox使用详解

《Spring框架之Springfox使用详解》Springfox是Spring框架的API文档工具,集成Swagger规范,自动生成文档并支持多语言/版本,模块化设计便于扩展,但存在版本兼容性、性... 目录核心功能工作原理模块化设计使用示例注意事项优缺点优点缺点总结适用场景建议总结Springfox 是

在Spring Boot中集成RabbitMQ的实战记录

《在SpringBoot中集成RabbitMQ的实战记录》本文介绍SpringBoot集成RabbitMQ的步骤,涵盖配置连接、消息发送与接收,并对比两种定义Exchange与队列的方式:手动声明(... 目录前言准备工作1. 安装 RabbitMQ2. 消息发送者(Producer)配置1. 创建 Spr

嵌入式数据库SQLite 3配置使用讲解

《嵌入式数据库SQLite3配置使用讲解》本文强调嵌入式项目中SQLite3数据库的重要性,因其零配置、轻量级、跨平台及事务处理特性,可保障数据溯源与责任明确,详细讲解安装配置、基础语法及SQLit... 目录0、惨痛教训1、SQLite3环境配置(1)、下载安装SQLite库(2)、解压下载的文件(3)、