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.128
    port: 5672
    virtual-host: /
    username: rabbitmq
    password: 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 {

    /**
     * 声明交换机
     */
    @Bean
    public FanoutExchange fanoutExchange() {
        return new FanoutExchange("star.fanout");
    }

    /**
     * 第1个队列
     */
    @Bean
    public Queue fanoutQueue1(){
        return new Queue("fanout.queue1");
    }

    /**
     * 绑定队列1和交换机
     */
    @Bean
    public Binding bindingQueue1(Queue fanoutQueue1, FanoutExchange fanoutExchange){
        return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);
    }

    /**
     * 第2个队列
     */
    @Bean
    public Queue fanoutQueue2(){
        return new Queue("fanout.queue2");
    }

    /**
     * 绑定队列2和交换机
     */
    @Bean
    public 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学习笔记

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

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

相关文章

白酒:产地与白酒品牌形象的建设与推广

云仓酒庄豪迈白酒作为中国白酒市场中的知名品牌&#xff0c;其产地与品牌形象的建设与推广对于提升品牌竞争力和市场份额具有重要意义。产地作为白酒品质和特色的重要标志&#xff0c;对于品牌形象的塑造和推广具有关键作用。 首先&#xff0c;云仓酒庄豪迈白酒的产地是其品质和…

AI降痕工具使用指南:如何有效降低AIGC疑似度

随着人工智能技术的突飞猛进&#xff0c;AI生成内容&#xff08;AIGC&#xff09;已被广泛用于学术论文撰写中&#xff0c;提高效率同时也带来了原创性的挑战。面对日益严格的学术审查&#xff0c;一个突出的问题是&#xff1a;使用AI代写的论文能否通过内容检测&#xff1f;因…

第二证券股票杠杆:4分钟直线涨停!这一赛道,AH股集体爆发!

今日早盘&#xff0c;A股继续小幅震动收拾&#xff0c;首要股指涨跌互现&#xff0c;两市个股跌多涨少&#xff0c;成交有萎缩的趋势。 盘面上&#xff0c;医药、中字头、旅游、房地产等板块相对活跃&#xff0c;混合实践、玻璃基板、AI手机PC、光刻机等板块跌幅居前。 “中字…

活动投票小程序源码系统 礼物道具活动多多 前后端分离 带完整的安装代码包以及搭建教程

系统概述 在当今数字化快速发展的时代&#xff0c;小程序已成为连接用户与商家、内容与服务的重要桥梁。特别是活动投票类小程序&#xff0c;因其便捷性、互动性和参与性&#xff0c;受到了广大用户的热烈追捧。为了满足市场对高质量、易操作的活动投票小程序的需求&#xff0…

别慌!不知道如何处理#开头的字符串时,需要先了解一下什么是NCR

最近进行接口测试时抓包发现请求响应中有类似下面这些字符 起初试图对这些编码尝试各种decoder操作来一探其真身&#xff0c;遗憾的是均已失败告终&#xff08;后来发现&#xff0c;这些编码可以在浏览器中正常显示&#xff09;。最后得知这种奇怪的编码格式并不是编码,而是一种…

ClickHouse 实现用户画像(标签)系统实践

文章目录 前言用户画像概述用户画像系统介绍用户画像系统的需求描述用户画像系统的需求分析用户画像系统的架构 关键技术实现&#xff08;Clickhouse SQL&#xff09;分析阶段运营阶段 基于ClickHouse的用户画像系统的优点 前言 本文介绍一个ClickHouse应用案例—用户画像系统…

AI工具:解锁智能时代办公自动化的新篇章

工欲善其事&#xff0c;必先利其器。 随着AI技术与各个行业或细分场景的深度融合&#xff0c;日常工作可使用的AI工具呈现出井喷式发展的趋势&#xff0c;AI工具的类别也从最初的AI文本生成、AI绘画工具&#xff0c;逐渐扩展到AI思维导图工具、AI流程图工具、AI生成PPT工具、AI…

AIGC| 有手就行的AI绘画教程!Midjourney+Stable Diffusion 结合!全程干货,速来学习!

大家好&#xff0c;我是画画的小强 AI绘画工具的出现&#xff0c; 让设计岗的同事更会画画了&#xff0c; 还让策划/制片/三维/后期/运营……也能“画”一画了。 今天小强就教一教大伙&#xff0c;萌新小白都能迅速上手的AI绘画教程&#xff0c; 从零开始&#xff0c;产出…

静态网页实现-人脸识别-案例(web)

&#x1f933;人脸识别&#xff08;web) 基于开源大模型&#xff0c;将人脸识别功能整合到网页中&#xff0c;提供用户友好的界面和强大的功能。 核心功能 人脸轮廓识别&#xff1a; 通过深度学习算法&#xff0c;精确识别人脸的轮廓&#xff0c;包括眼睛、鼻子、嘴巴等关键部…

Java18+​App端采用uniapp+开发工具 idea hbuilder智能上门家政系统源码,一站式家政服务平台开发家政服务

Java18​App端采用uniapp开发工具 idea hbuilder智能上门家政系统源码&#xff0c;一站式家政服务平台开发 家政服务 家政服务是一个专为家政服务人员设计的平台&#xff0c;该平台旨在提供便捷、高效的工作机会&#xff0c;同时确保服务质量和客户体验。 以下是关于家政服务师…

【耗时十个小时】程序员最趁手的SVM算法,学完你会哭着感谢努力的自己!

❤ 纯 干 货 ❤ 在这之前咱们已经接触了 各个算法的优缺点的总结&#xff0c;以及8个回归类算法、7个正则化算法的总结、5 个集成算法模型的全部总结&#xff01; 感兴趣的可以翻到之前看看~ 咱们今天就大概一起学习一下关于SVM的方方面面。 线性支持向量机 非线性支持向量…

干货 | SDR RFSoC技术框图大放送(附资源)

软件无线电(SDR) 本文参考《Software Defined Radio with Zynq UltraScale RFSoc》&#xff0c;全文共744页。需要的可以给公众号 迪普微科技 发送“SDR”。

动态规划——打家劫舍问题

198. 打家劫舍 问题描述 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给定一…

MathorCup挑战赛获奖名单公示,第九届研讨会及颁奖典礼即将举行

近日&#xff0c;备受瞩目的2024年第十四届MathorCup高校数学建模挑战赛圆满落幕&#xff0c;竞赛组委会于近日公示了获奖名单初稿。本届竞赛自2024年4月12日至16日举行&#xff0c;吸引了来自全国740所高校的9119支队伍踊跃参与&#xff0c;其中包括本科生、研究生、专科生及教…

Java流程控制习题--打印三角形及debug运用

1.打印三角形 使用for循环的嵌套进行运算&#xff0c;思考代码实现的思维方式 2.debug可显示代码每一步的运行步骤&#xff0c;使我们更好的了解代码的运行&#xff0c; debug使用方法&#xff1a;在代码的左侧排序处单机&#xff0c;在点击右上角的蜘蛛图标即可

springboot+elementui健康饮食系统

此系统是springboot健康饮食管理平台 得简化版&#xff0c;适合期末大作业 系统包括 管理员端和用户端 1.用户端注册即可登录到用户端&#xff0c;用户端包括首页轮播图&#xff0c;以及个人中心&#xff0c;个人信息修改&#xff0c;头像修改&#xff0c;后台根据用户信息&am…

liunx配置网络的命令

liunx配置网络的命令 文章目录 liunx配置网络的命令ifconfig命令查看路由表信息netstat命令ss命令lsof命令ping 命令nslookup命令 ifconfig命令 ifconfig:显示正在工作的网卡&#xff0c;启动的设备 ifconfig -a 展示所有设备 ens33: flags4163<UP,BROADCAST,RUNNING,MUL…

Flutter开发效率提升1000%,Flutter Quick教程之定义Api(四)

现在我们来讲讲&#xff0c;如何建立Api 响应数据的变量。 这个变量&#xff0c;本质上就是对根据json数据生成model的引用。 这个name就是引用名。 这个path&#xff0c;就是引用的Model Data里面的具体字段&#xff0c;在实际操作过程中&#xff0c;校验是由右边的json数据…

Pikachu靶场下载、配置

目录 下载 配置 新版小蓝皮 搭建网站 搭建数据库 初始化靶场 旧版小绿皮 配置数据库 配置网站 下载 GitHub下载地址&#xff1a; 百度网盘&#xff1a;https://pan.baidu.com/s/1j2WpdLvwAbmpAH76d_yitw?pwdwf8j 提取码&#xff1a;wf8j 迅雷链接&#xff1a;http…

LLC开关电源开发:第三节,LLC电路原理图及开环仿真

LLC开关电源开发&#xff1a;第三节&#xff0c;LLC电路原理图 第三节&#xff0c;LLC电路原理图文章目录 一、开发板指标二、原理图简介1.LLC主功率电路2.输入滤波电路3.烧录口及复位电路4.DSP供电电路5.输出采样电路6.DSP外围电路7.指示灯电路8.调压滑动变阻器电路9.隔离驱动…