SpringBoot整合RabbitMQ学习笔记

news2024/12/27 12:02:29

SpringBoot整合RabbitMQ学习笔记

以下三种类型的消息,生产者和消费者需各自启动一个服务,模拟生产者服务发送消息,消费者服务监听消息,分布式开发。

一 Fanout类型信息

在这里插入图片描述
在这里插入图片描述

  1. . RabbitMQ创建交换机和队列
    在RabbitMQ控制台,新建交换机hmall.fanout,新建两个队列,fanout.queue1和fanout.queue2,并将连个队列和交换机进行绑定即可。
    操作如下图所示:
    一下操作可以通过代码实现,具体参考配置类
    (1)创建队列
    在这里插入图片描述

(2)创建交换机
在这里插入图片描述
(3)绑定
在这里插入图片描述2. 代码实现
(1)引入依赖

<dependency>
	<groupId>org.springframework.book</groupId>
	<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

(2)配置MQ配置信息

spring:
	rabbitmq:
		host: 192.168.150.101 #主机ip
		port: 5672 #端口
		virtual-host: /hmall #虚拟主机
		username: hmall #用户名
		password: 123 #密码
		exchange: hmall.fanout
		producer:
			queue1: fanout.queue1
		

(3)声明队列和交换机配置类

@Component
public class FanoutConfg{

	@Value("${spring.rabbitmq.exchange}")
	private String exchange
	@Value("${spring.rabbitmq.producer.queue1}")
	private String queueName1
	// 声明fanout交换机
	@Bean
	public FanoutExchange fanoutExchange(){
		return new FanoutExchange(exchanage);
	}
	// 声明队列
	@Bean
	public Queue fanoutQueue1(){
		return new Queue(queueName1);
	}
	//绑定队列和交换机
	@Bean
	public Binding bindingQueue1(Queue fanoutQueue1,FanoutExchange fanoutExchange){
		return BindingBuilder,build(fanoutQueue1).to(fanoutExchange);
	}
}

(4)生产者

@Component
public class RabbitMqProduce {
	@Autowired
	private RabbitTemplate rabbitTemplete;
	@value("${spring.rabbitmq.producer.queue})
	private String queueName;
	/**
	* 入参说明:
	* 第一个参数:queueName:队列名称
	* 第二个参数:路由键,fanout类型不需要路由键
	* 第三个参数:msg 消息题内容
	*/
	public void send(String msg){
		
		rabbitTemplete.covertAndSend(queueName,null,msg);
	}

}

(4)消费者

@Component
public class RabbitMqListener {
	
	@RabbitListener(queues="${spring.rabbitmq.producer.queue}")
	public void counsume(String msg){
		System.out.pringln("消费者收到 fanout.queue队列发的消息",msg);
	}
}

(5)测试类

@SpringBootTest
public class SpringBootTest{
	@AUtowired
	private RabbitMqProduce producer;
	
	@Test
	public void testSendFanoutMsg(){
		producer.send("fanout类型发送消息!!!");
	}
}

二 direct类型发送消息在这里插入图片描述

在这里插入图片描述

  1. 控制台操作
    (1)交换机和队列的创建参考fanout的操作
    (2)绑定:与fanout不同的是 给交换机绑定队列的同时需要指定路由键,如下图所示:
    在这里插入图片描述
  2. 代码实现
    (1)依赖引入参考fanout类型的消息
    (2)mq消息配置
spring:
	rabbitmq:
		host: 192.168.150.101 #主机ip
		port: 5672 #端口
		virtual-host: /hmall #虚拟主机
		username: hmall #用户名
		password: 123 #密码
		exchange: hmall.direct
		producer:
			queue1: direct.queue1
			queue2: direct.queue2
			routingKey1: red
			routingKey2: red2
		

(3)MQ配置类
以下配置可以在消费者注解上实现

@Component
public class RabbitMqConfig {
	@Autowired
	private RabbitTemplate rabbitTemplete;

	@value("${spring.rabbitmq.producer.exchange}")
	private String exchange;
	
	@value("${spring.rabbitmq.producer.queue1}")
	private String queueName1;
	
	@value("${spring.rabbitmq.producer.queue2}")
	private String queueName2;
	
	@value("${spring.rabbitmq.producer.routingKey1}")
	private String routingKey1;

	@value("${spring.rabbitmq.producer.routingKey2}")
	private String routingKey2;

	// 创建交换机
	@Bean("directExchange")
	public Exchange getExchange(){
		return ExchangeBuilder
		.topicExchange(exchange) // 交换机类型,交换机名称
		.durable(true) //ture为持久化,存到磁盘,false存到内存
		.build();
	}
	// 创建队列
	@Bean("directQueue1")
	public Queue getDirectQueue1(){
		retuen new Queue(queueName1);
	}

	// 交换机绑定队列
	@bean
	public Binging bindDirectQueue1(@Qualifier("directExchange") Exchange exchange,@Qualifier("directQueue1") Queue queue){
		return BindingBuilder
		.bind(queue)
		.to(exchange)
		.with(routingKey1)
		.noargs();	
	}


	// 创建队列
	@Bean("directQueue2")
	public Queue getDirectQueue2(){
		retuen new Queue(queueName2);
	}

	// 交换机绑定队列
	@bean
	public Binging bindDirectQueue2(@Qualifier("directExchange") Exchange exchange,@Qualifier("directQueue2") Queue queue){
		return BindingBuilder
		.bind(queue)
		.to(exchange)
		.with(routingKey2)
		.noargs();	
	}

}

(4)生产者发送消息

@Component
public class RabbitMqProduce {
	@Autowired
	private RabbitTemplate rabbitTemplete;
	
	@value("${spring.rabbitmq.producer.queue1})
	private String queueName1;
	@value("${spring.rabbitmq.producer.queue2})
	private String queueName2;

	@value("${spring.rabbitmq.producer.routingKey2})
	private String routingKey1;

	@value("${spring.rabbitmq.producer.routingKey1})
	private String routingKey2;
	/**
	* 入参说明:
	* 第一个参数:queueName:队列名称
	* 第二个参数:路由键,fanout类型不需要路由键
	* 第三个参数:msg 消息题内容
	*/
	public void sendQueue1(String msg){
		
		rabbitTemplete.covertAndSend(queueName1,routingKey1,msg);
	}
	public void sendQueue2(String msg){
		
		rabbitTemplete.covertAndSend(queueName2,routingKey2,msg);
	}


}

(5)消费者监听消息
第一种:已经编写了配置类

@Component
public class RabbitMqListener {
	
	@RabbitListener(queues="${spring.rabbitmq.producer.queue1}")
	public void counsume(String msg){
		System.out.pringln("消费者收到 direct.queue1队列发的消息",msg);
	}
	@RabbitListener(queues="${spring.rabbitmq.producer.queue2}")
	public void counsume(String msg){
		System.out.pringln("消费者收到 direct.queue2队列发的消息",msg);
	}
}

第二种:在注解上配置交换机和队列以及路由键

@Component
public class RabbitMqListener {
	
	@RabbitListener(bindings = 
	@QueueBinding(
		value = Queue(name="${spring.rabbitmq.producer.queue1}",durable="true"),
		exchange = @Exchange(name="${spring.rabbitmq.producer.exchange)",type=ExchangeType.DIRECT),
		key = {"${spring.rabbitmq.producer.routingKey1}","${spring.rabbitmq.producer.routingKey2}"}	
	))
	public void counsume(String msg){
		System.out.pringln("消费者收到 direct.queue1队列发的消息",msg);
	}
		@RabbitListener(bindings = 
	@QueueBinding(
		value = Queue(name="${spring.rabbitmq.producer.queue2}",durable="true"),
		exchange = @Exchange(name="${spring.rabbitmq.producer.exchange)",type=ExchangeType.DIRECT),
		key = {"${spring.rabbitmq.producer.routingKey1}","${spring.rabbitmq.producer.routingKey2}"}	
	))
	public void counsume(String msg){
		System.out.pringln("消费者收到 direct.queue2队列发的消息",msg);
	}
}

(6)测试类

@SpringBootTest
public class SpringBootTest{
	@AUtowired
	private RabbitMqProduce producer;
	
	@Test
	public void testSendDirectMsg(){
		producer.send("direct类型发送消息!!!");
	}
}

三 Topic类型消息

在这里插入图片描述
在这里插入图片描述

  1. 控制台操作
    参考前面的创建交换机,队列,以及绑定关系操作
  2. 代码实现
    (1)依赖引入参考fanout类型的消息
    (2)mq消息配置
    路由键使用通配符进行匹配,#代表多个,*代表一个
spring:
	rabbitmq:
		host: 192.168.150.101 #主机ip
		port: 5672 #端口
		virtual-host: /hmall #虚拟主机
		username: hmall #用户名
		password: 123 #密码
		exchange: hmall.topic
		producer:
			queue1: topic.queue1
			queue2: topic.queue2
			routingKey1: china.#
			routingKey2: #.news
		

(3)MQ配置类

@Component
public class RabbitMqConfig {
	@Autowired
	private RabbitTemplate rabbitTemplete;

	@value("${spring.rabbitmq.producer.exchange}")
	private String exchange;
	
	@value("${spring.rabbitmq.producer.queue1}")
	private String queueName1;
	
	@value("${spring.rabbitmq.producer.queue2}")
	private String queueName2;
	
	@value("${spring.rabbitmq.producer.routingKey1}")
	private String routingKey1;

	@value("${spring.rabbitmq.producer.routingKey2}")
	private String routingKey2;

	// 创建交换机
	@Bean("topicExchange")
	public Exchange getExchange(){
		return ExchangeBuilder
		.topicExchange(exchange) // 交换机类型,交换机名称
		.durable(true) //ture为持久化,存到磁盘,false存到内存
		.build();
	}
	// 创建队列
	@Bean("topicQueue1")
	public Queue getDirectQueue1(){
		retuen new Queue(queueName1);
	}

	// 交换机绑定队列
	@bean
	public Binging bindDirectQueue1(@Qualifier("topicExchange") Exchange exchange,@Qualifier("topicQueue1") Queue queue){
		return BindingBuilder
		.bind(queue)
		.to(exchange)
		.with(routingKey1)
		.noargs();	
	}


	// 创建队列
	@Bean("topicQueue2")
	public Queue getDirectQueue2(){
		retuen new Queue(queueName2);
	}

	// 交换机绑定队列
	@bean
	public Binging bindDirectQueue2(@Qualifier("topicExchange") Exchange exchange,@Qualifier("topicQueue2") Queue queue){
		return BindingBuilder
		.bind(queue)
		.to(exchange)
		.with(routingKey2)
		.noargs();	
	}

}

(4)生产者发送消息

@Component
public class RabbitMqProduce {
	@Autowired
	private RabbitTemplate rabbitTemplete;
	
	@value("${spring.rabbitmq.producer.queue1})
	private String queueName1;
	@value("${spring.rabbitmq.producer.queue2})
	private String queueName2;

	@value("${spring.rabbitmq.producer.routingKey2})
	private String routingKey1;

	@value("${spring.rabbitmq.producer.routingKey1})
	private String routingKey2;
	/**
	* 入参说明:
	* 第一个参数:queueName:队列名称
	* 第二个参数:路由键,fanout类型不需要路由键
	* 第三个参数:msg 消息题内容
	*/
	public void sendQueue1(String msg){
		
		rabbitTemplete.covertAndSend(queueName1,routingKey1,msg);
	}
	public void sendQueue2(String msg){
		
		rabbitTemplete.covertAndSend(queueName2,routingKey2,msg);
	}


}

(5)消费者监听消息

@Component
public class RabbitMqListener {
	
	@RabbitListener(queues="${spring.rabbitmq.producer.queue1}")
	public void counsume(String msg){
		System.out.pringln("消费者收到 topic.queue1队列发的消息",msg);
	}
	@RabbitListener(queues="${spring.rabbitmq.producer.queue2}")
	public void counsume(String msg){
		System.out.pringln("消费者收到 topic.queue2队列发的消息",msg);
	}
}

(6)测试类

@SpringBootTest
public class SpringBootTest{
	@AUtowired
	private RabbitMqProduce producer;
	
	@Test
	public void testSendDirectMsg(){
		producer.send("direct类型发送消息!!!");
	}
}

四 消息转换器

MQ会把消息体变成字节码
在这里插入图片描述
解决办法:使用消息转换器,实现如下:

  1. 在生产者和消费者两个服务引入依赖
<dependency>
	<groupId>com.fasterxml.jackson</groupId>
	<artifactId>jasckson-databind</artifactId>
</dependency>
  1. 在生产者和消费者两个服务编写消息转换器配置
@Component
public class JacksonMessageConvertor{
	@Bean
	public MessageCoverter jacksonMessageConvertor(){
		return new Jackson2JsonMessageConverter();
	}
}
  1. 消息体
    对于生产者来说,是map类型的,则生成者接收的时候也是map类型
    例如:
@Component
public class RabbitMqListener {
	
	@RabbitListener(queues="${spring.rabbitmq.producer.queue1}")
	public void counsume(Map<String,Objecct> msg){
		System.out.pringln("消费者收到 topic.queue1队列发的消息",msg);
	}
	
}

五 案例演示

支付服务支付成功后通知交易服务进行后续操作
在这里插入图片描述
生产者和消费者两个服务都需要进行1,2,3步骤

  1. 添加依赖
<!--mq依赖-->
<dependency>
	<groupId>org.springframework.book</groupId>
	<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!--消息转换器依赖-->
<dependency>
	<groupId>com.fasterxml.jackson</groupId>
	<artifactId>jasckson-databind</artifactId>
</dependency>
  1. 添加MQ配置信息
spring:
	rabbitmq:
		host: 192.168.150.101 #主机ip
		port: 5672 #端口
		virtual-host: /hmall #虚拟主机
		username: hmall #用户名
		password: 123 #密码
		exchange: pay.topic
		queue: mark.order.pay.queue
		routKingKey: pay.success
		
  1. 消息转换器配置类
@Component
public class JacksonMessageConvertor{
	@Bean
	public MessageCoverter jacksonMessageConvertor(){
		return new Jackson2JsonMessageConverter();
	}
}
  1. 生产者
    (1)生产者的配置
@Component
public class Rabbitroducer {
	@Autowired
	private RabbitTemplate rabbitTemplete;
	
	@value("${spring.rabbitmq.queue})
	private String queueName;

	@value("${spring.rabbitmq.routingKey})
	private String routingKey;

	/**
	* 入参说明:
	* 第一个参数:queueName:队列名称
	* 第二个参数:路由键,fanout类型不需要路由键
	* 第三个参数:msg 消息题内容
	*/
	public void sendMsg(String msg){
		// 发送消息
		rabbitTemplete.covertAndSend(queueName,routingKey, msg);
	}
}

(2)业务代码支付成功发送消息

public class payOrderServiceImpl impletement PayOrderService{
	@Autowrid
	private RabbitProducer payProducer;
	@Overirid
	@Transactional(rollback = Exception.class)
	public void payOrder(PayOrderDto payOrder){
		// 一些列操作最终交易成功
		// 发送消息通知
		try{
			payProducer.send(payOrder.getId());
		}catch(AmqpException e){
			log.error("交易成功,发送消息异常:{}",e.getMessages(););
		}
	}
}
  1. 消费者
@Component
public class PaySatusListener {

	@Autowired
	private OrderService orderService;
	
	@RabbitListener(bindings = 
	@QueueBinding(
		value = Queue(name="${spring.rabbitmq.queue}",durable="true"),
		exchange = @Exchange(name="${spring.rabbitmq.exchange)",type=ExchangeType.TOPIC),
		key = {"${spring.rabbitmq.routingKey}"}	
	))
	public void listenOrderPay(Long orderId){
		//标记订单为已支付
		orderService.markOrderPaySuccess(orderId);
	}
		
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

飞书开发学习笔记(三)-利用python开发调试云文档和电子表格

飞书开发学习笔记(三)-利用python开发调试云文档和电子表格 一.建立Python飞书开发环境 首先还是进入开放平台下的API调试台 飞书开放平台&#xff1a;https://open.feishu.cn/app?langzh-CN 以获取"我的空间"下的文件清单为例&#xff0c;通过获取飞书API调试台提…

展开一个结构加法等式

4a6 4a8 - - - - - 1 - 1 - - - 1 - 1 - - 1 - - 1 - - 1 - - 1 - - - - 在5-1的方向上具体展开4a64a8 25 19 19 19 19 19 19 19 25 19 19 19 19 19 19 19 1 10 10 10 10 10 10 10 1 10 10 10 10 10 10 10 …

矩阵等价和向量组等价的一些问题

什么是向量组&#xff1f;答&#xff1a;向量组是由若干同维数的列向量&#xff08;或同维数的行向量&#xff09;组成的集合。什么是向量组等价&#xff1f;答&#xff1a;两个向量组&#xff0c;各自拼成矩阵A和B&#xff0c;向量组等价就是三秩相等&#xff0c;即r&#xff…

如何发布自己的golang库

如何发布自己的golang库 1、在 github/gitee 上创建一个 public 仓库&#xff0c;仓库名与 go 库名一致&#xff0c;然后将该仓库 clone 到本地。 本文这里使用 gitee。 $ git clone https://gitee.com/zsx242030/goutil.git2、进入项目文件夹&#xff0c;进行初始化。 $ go…

【unity实战】实现类似英雄联盟的buff系统

文章目录 先来看看最终效果前言开始BUFF系统加几个BUFF测试1. 逐层消失&#xff0c;升级不重置剩余时间的BUFF2. 一次性全部消失&#xff0c;升级重置剩余时间的BUFF3. 永久BUFF&#xff0c;类似被动BUFF4. 负面BUFF&#xff0c;根据当前BUFF等级计算每秒收到伤害值&#xff0c…

Docker Stack部署应用详解+Tomcat项目部署详细实战

Docker Stack 部署应用 概述 单机模式下&#xff0c;可以使用 Docker Compose 来编排多个服务。Docker Swarm 只能实现对单个服务的简单部署。而Docker Stack 只需对已有的 docker-compose.yml 配置文件稍加改造就可以完成 Docker 集群环境下的多服务编排。 stack是一组共享…

Pyhotn: Mac安装selenium没有chromedriver-114以上及chromedriver无法挪到/usr/bin目录下的问题

1.0 安装selenium 终端输入&#xff1a; pip install selenium 查看版本&#xff1a; pip show selenium2.0 安装chromedriver 查看chrome版本 网上大多数是&#xff0c;基本到114就停了。 https://registry.npmmirror.com/binary.html?pathchromedriver/ 各种搜索&#…

Blender基础操作:面操作细分、整体切分、挤出、内插、尖分、融并、切割、面的法向、填充等

目录 1. 面操作&#xff1a;进入‘面选择’模式&#xff0c;选择一个面 2. 面的挤出 3. 内插面 4. 尖分面 5. 面的切割 6. 面的法向normal 7. 填充面 8. X-Ray透视 1. 面操作&#xff1a; 进入“面选择”模式&#xff0c;选择一个面 4种操作手段&#xff1a; 菜单 工…

四、数据库系统

数据库系统&#xff08;Database System&#xff09;&#xff0c;是由数据库及其管理软件组成的系统。数据库系统是为适应数据处理的需要而发展起来的一种较为理想的数据处理系统&#xff0c;也是一个为实际可运行的存储、维护和应用系统提供数据的软件系统&#xff0c;是存储介…

Redis01-缓存击穿、穿透和雪崩

目录 开场白-追命3连 使用场景 01缓存穿透场景与方案 02布隆过滤器 03缓存击穿场景与方案 04缓存雪崩场景与方案 开场白-追命3连 看你项目中有说用到Redis&#xff0c;都是哪些场景使用了Redis呢&#xff1f; 如果发生了缓存穿透、击穿、雪崩如何应对呢&#xff1f;缓存…

研读论文之Image Quality-aware Diagnosis via Meta-knowledge Co-embedding

研读论文之 Image Quality-aware Diagnosis via Meta-knowledge Co-embedding 前言一、简介二、主要内容2.1. 图像退化2.2. 图像质量感知诊断(IQAD)2.3. 元知识协同嵌入网络(MKCNet) 三、实现过程3.1. IQAD问题3.2. 元知识协同嵌入网络 (MKCNet)3.2.1功能3.2.2优化策略3.2.3 Ta…

轻信息服务展示预约小程序的内容是什么

预约几乎是适应所有经营商家的&#xff0c;可以提升客户服务/产品获取度、锁客及便捷性需求&#xff0c;同时也利于提升商家整体经营效率&#xff0c;无论获客还是留存线索都有很高帮助。 尤其对线下服务实体店来说&#xff0c;需要预约形式将客户引流到店&#xff0c;传统商家…

考研数学(数二)核心要点(极限)

前言 okey&#xff0c;今天难得有时间那就稍微整理一下数学部分的内容。注意&#xff0c;本文仅适用于考研冲刺阶段&#xff0c;对知识点进行复习使用。前提是你已经知道了相关知识点&#xff0c;我这里只是把我认为比较重要的&#xff0c;我自己总结的内容给出来&#xff0c;…

基于机器学习的学生成绩预测

学生成绩预测是一个基于回归问题的流行数据科学案例研究。对于数据科学初学者来说&#xff0c;这是一个很好的回归问题&#xff0c;因为它很容易解决和理解。本文中&#xff0c;将带你通过使用Python的机器学习来完成学生成绩预测的任务。 学生成绩预测&#xff08;案例研究&a…

本地idea远程调试服务器程序

本文主要介绍idea本地调试远程服务器程序的方式。相信很多同行跟我一样&#xff0c;在最初接触公司项目的时候&#xff0c;遇到测试提出的缺陷&#xff0c;往往会在本地进行调试、替换jar包远程调试等方式&#xff0c;本地调试往往会导致数据和环境不一致的问题使得问题无法复现…

机器学习领域经典书籍推荐

机器学习领域经典书籍 1. 数据挖掘概念与技术2. 机器学习3. 统计学习方法4. 深度学习5. 动手学深度学习&#xff08;PyTorch版&#xff09; 1. 数据挖掘概念与技术 原名: Data Mining&#xff1a;Concepts and Techniques&#xff0c;Third Edition 作者: &#xff08;美&#…

Solidity入门第一步之数据类型

各种类型介绍 数值类型(Value Type)&#xff1a;包括布尔型(bool)&#xff0c;整数型(int、uint、uint256)等等&#xff0c;这类变量赋值时候直接传递数值。引用类型(Reference Type)&#xff1a;包括数组和结构体&#xff0c;这类变量占空间大&#xff0c;赋值时候直接传递地…

Leetcode—707.设计链表【中等】

2023每日刷题&#xff08;十七&#xff09; Leetcode—707.设计链表 设计单链表实现代码 typedef struct Node {int val;struct Node* next; } MyLinkedList;MyLinkedList* myLinkedListCreate() {MyLinkedList* mList (MyLinkedList *)malloc(sizeof(MyLinkedList));mList-…

chroot

1.chroot技术 在Linux系统中&#xff0c;系统默认的目录结构都是以/&#xff0c;即根(root)开始的。而在使用chroot之后&#xff0c;进程的系统目录结构将以指定的位置作为根(/)位置。chroot实际作用就是将进程描述符中struct fs_struct中的root的值设置为选定的目录。 在经过…

深度学习之基于Yolov5人体姿态摔倒识别分析报警系统(GUI界面)

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 系统设计概述&#xff1a; 传感器采集&#xff1a;通过在场景中布置摄像头或红外传感器等设备&#xff0c;采集人体…