微服务——服务异步通讯RabbitMQ
前置文章
消息队列——RabbitMQ基本概念+容器化部署和简单工作模式程序_北岭山脚鼠鼠的博客-CSDN博客
消息队列——rabbitmq的不同工作模式_北岭山脚鼠鼠的博客-CSDN博客
消息队列——spring和springboot整合rabbitmq_北岭山脚鼠鼠的博客-CSDN博客
目录
Work queues 工作队列模式
案例:
在生产者端
在消费者端
结果如下
消费预取限制
发布订阅模型
Fanout Exchange(配置文件实现)
案例
消费者代码
生产者代码
Direct Exchange (注解实现)
案例
消费者代码
生产者代码
Topic Exchange
案例
消费者代码
生产者代码
消息转换器
生产者代码
JSON方式序列化
生产者代码 (jackson)
消费者代码(jackson)
总结
Work queues 工作队列模式
这里用的不是上面第三篇文章里面的定义配置类的形式。
案例:

在生产者端
队列要存在才可以上传。不然代码运行不会报错,但是消息也会不知道发到哪里去。
@Testpublic void testSendMessage2() throws InterruptedException {String queue_Name= "simple.queue";String message="hello 鼠鼠";for(int i=1;i<=50;i++)rabbitTemplate.convertAndSend(queue_Name,message+i);Thread.sleep(20);}
在消费者端
定义了两个消费者监听上面的队列,本来想三个的,但是不知道默认的交换机名字,所以弄了两个。并且根据注解的不同,第一个是可以直接创建一个队列,第二个需要队列已存在才行。
@Component
public class RabbitMQListener {//自动创建队列@RabbitListener(queuesToDeclare=@Queue("simple.queue"))public void ListenerWorkQueue1(Message message) throws InterruptedException {System.out.println("11111"+message.getBody());Thread.sleep(20);}//需要在rabbit_mq上手动创建队列,不然会报错@RabbitListener(queues="simple.queue")public void ListenerWorkQueue2(Message message) throws InterruptedException {System.out.println("22222"+message.getBody());Thread.sleep(200);}//3. 自动创建队列,Exchange 与 Queue绑定
// @RabbitListener(bindings = @QueueBinding(
// value = @Queue("simple.queue"),
// exchange = @Exchange("/") //绑定默认交换机
// ))
// public void ListenerWorkQueue3(Message message) throws InterruptedException {
// System.out.println("33333"+message.getBody());
// Thread.sleep(200);
// }
}
结果如下
两个队列轮流取消息导致反而变慢了。


消费预取限制
要指定队列才有效果。

这里就相当于指定了在simple前缀的队列上每次只能获取一条消息。
运行结果如下,大多数都交给了快的队列执行。

发布订阅模型

Fanout Exchange(配置文件实现)
消息路由到每个绑定的消息队列。
案例



消费者代码
spring读取到这个Bean之后就会向RabbitMq发请求,创建交换机,绑定队列了。
@Configuration
public class FanoutConfig {//itcast.fanout@Beanpublic FanoutExchange fanoutExchange(){return new FanoutExchange("itcast.fanout");}//fanout.queue1@Beanpublic Queue fanoutQueue1(){return new Queue("fannout.queue1");}//绑定队列1到交换机@Beanpublic Binding fanoutBinding1(Queue fanoutQueue1, FanoutExchange fanoutExchange){return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);}//fanout.queue1@Beanpublic Queue fanoutQueue2(){return new Queue("fannout.queue2");}//绑定队列2到交换机@Beanpublic Binding fanoutBinding2(Queue fanoutQueue2, FanoutExchange fanoutExchange){return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);}
}
定义两个监听用的方法
@Component
public class RabbitMQListener {
// @RabbitListener(queues="boot_queue")
// public void ListenerQueue(Message message){
// System.out.println(message);
// }//自动创建队列// @RabbitListener(queuesToDeclare=@Queue("simple.queue"))
// public void ListenerWorkQueue1(Message message) throws InterruptedException {
// System.out.println("11111"+message.getBody()+ LocalDateTime.now());
// Thread.sleep(20);
// }
//
// //需要在rabbit_mq上手动创建队列,不然会报错
// @RabbitListener(queues="simple.queue")
// public void ListenerWorkQueue2(Message message) throws InterruptedException {
// System.out.println("22222"+message.getBody()+ LocalDateTime.now());
// Thread.sleep(200);
// }//3. 自动创建队列,Exchange 与 Queue绑定
// @RabbitListener(bindings = @QueueBinding(
// value = @Queue("simple.queue"),
// exchange = @Exchange("/") //绑定默认交换机
// ))
// public void ListenerWorkQueue3(Message message) throws InterruptedException {
// System.out.println("33333"+message.getBody());
// Thread.sleep(200);
// }@RabbitListener(queuesToDeclare=@Queue("fanout.queue1"))public void ListenerFanoutQueue1(Message message) throws InterruptedException {System.out.println("11111"+message.getBody());}@RabbitListener(queuesToDeclare=@Queue("fanout.queue2"))public void ListenerFanoutQueue2(Message message) throws InterruptedException {System.out.println("22222"+message.getBody());}
}
生产者代码
@SpringBootTest
@RunWith(SpringRunner.class)
public class ProducerTest {//1.注入RabbitTemplate@Autowiredprivate RabbitTemplate rabbitTemplate;// @Test
// public void testSend(){
// rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE_NAME,"boot.haha","hello 鼠鼠");
// }// @Test
// public void testSendMessage2() throws InterruptedException {
// String queue_Name= "simple.queue";
// String message="hello 鼠鼠";
//
// for(int i=1;i<=50;i++)
// rabbitTemplate.convertAndSend(queue_Name,message+i);
// Thread.sleep(20);
// }@Testpublic void testSendFanoutExchange(){//交换机名称String exchangeName="itcast.fanout";//消息String message="hello 鼠鼠";//发送消息rabbitTemplate.convertAndSend(exchangeName,"",message);}
}
Direct Exchange (注解实现)

案例

消费者代码
@Component
public class RabbitMQListener { @RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue1"),exchange = @Exchange(name="itcast.direct" , type= ExchangeTypes.DIRECT),key={"red","blue"}))public void listenDirectQueue1(String msg){System.out.println("消费者接收到:"+msg);}@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue2"),exchange = @Exchange(name="itcast.direct" , type= ExchangeTypes.DIRECT),key={"red","yellow"}))public void listenDirectQueue2(String msg){System.out.println("消费者接收到:"+msg);}
}
生产者代码
@Testpublic void testSendDirectExchange(){//交换机名称String exchangeName="itcast.direct";//消息String message="hello 鼠鼠";//发送消息rabbitTemplate.convertAndSend(exchangeName,"blue",message);}
此条代码只有绑定了blue这个key的队列才可以收到。

换成red就是两个队列都可以收到了。

Topic Exchange

案例

消费者代码
@RabbitListener(bindings = @QueueBinding(value=@Queue(name="topic.queue1"),exchange=@Exchange(name="itcast.topic",type = ExchangeTypes.TOPIC),key="japan.#"))public void listenTopicQueue1(String msg){System.out.println("消费者接收到:"+msg);}@RabbitListener(bindings = @QueueBinding(value=@Queue(name="topic.queue2"),exchange=@Exchange(name="itcast.topic",type = ExchangeTypes.TOPIC),key="#.news"))public void listenTopicQueue2(String msg){System.out.println("消费者接收到:"+msg);}
生产者代码
@Testpublic void testSendTopicExchange(){//交换机名称String exchangeName="itcast.topic";//消息String message="北岭山脚鼠鼠横死街头,究竟是人性的沦丧还是道德的....";//发送消息rabbitTemplate.convertAndSend(exchangeName,"japan.news",message);}
两个都符合,所以都能收到。

消息转换器

定义一个队列
@Beanpublic Queue objectQueue(){return new Queue("object.queue");}
生产者代码
@Testpublic void testSendObjectQueue(){//消息Map<String,Object> msg=new HashMap<>();msg.put("name","北岭山脚鼠鼠");msg.put("age","22");//发送消息rabbitTemplate.convertAndSend("object.queue",msg);}
可以看见消息被转换成了一长串字符,content_type写着java的序列化。
效率差,安全性也差。

JSON方式序列化

声明好MessageConveter之后就可以自动覆盖默认序列化方式了。
导入一个核心依赖
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency>
生产者代码 (jackson)
修改生产者的启动类代码,加上一个Bean
@SpringBootApplication
public class ProducerApplication {public static void main(String[] args) {SpringApplication.run(ProducerApplication.class);}@Beanpublic Jackson2JsonMessageConverter messageConverter(){return new Jackson2JsonMessageConverter();}
}
启动测试类之后可以看见新的消息出现了。

消费者代码(jackson)

然后可以正常接受到消息

如果消费者不使用对应jackson解析的话,代码会报错

总结

推荐使用jackson的方式
相关文章:
微服务——服务异步通讯RabbitMQ
前置文章 消息队列——RabbitMQ基本概念容器化部署和简单工作模式程序_北岭山脚鼠鼠的博客-CSDN博客 消息队列——rabbitmq的不同工作模式_北岭山脚鼠鼠的博客-CSDN博客 消息队列——spring和springboot整合rabbitmq_北岭山脚鼠鼠的博客-CSDN博客 目录 Work queues 工作队列…...
事件冒泡、事件捕获和事件委托
原文合集地址如下,有需要的朋友可以关注 本文地址 合集地址 什么是事件冒泡、事件捕获和事件委托? 事件冒泡(Event Bubbling)、事件捕获(Event Capturing)和事件委托(Event Delegation&…...
WEB 典型安全功能说明
WEB 典型安全功能 认证Authentication 认证是指通过验证用户的身份来确认用户是否有权访问某个系统或资源。在Web安全中,认证是非常重要的一环,它可以防止未经授权的访问,保护用户的数据和系统的安全。 登录 登录是用户认证的常见方式之一…...
SQL编译优化原理
最近在团队的OLAP引擎上做了一些SQL编译优化的工作,整理到了语雀上,也顺便发在博客上了。SQL编译优化理论并不复杂,只需要掌握一些关系代数的基础就比较好理解;比较困难的在于reorder算法部分。 文章目录 基础概念关系代数等价 j…...
qt signal slots lambda
这里用到了qt的版本检测 连接 Combox的currentIndexChanged事件 emit来触发处理的事件 ,进行业务或逻辑处理 这样的写法是lambda表达式的写法,和c#中的 (obj)>{ //todo } 类同 [](int indx){ //todo } #if QT_VERSION > QT_VERSION_CHECK(5,7,0)c…...
Spring【声明式事务】
事务简介 把一组业务当成一个业务来做;要么都成功,要么都失败!事务在项目开发中,十分重要,涉及到数据一致性的问题,需要十分注意!确保完整性和一致性! 事务的ACID原则:…...
【雕爷学编程】MicroPython动手做(17)——掌控板之触摸引脚2
知识点:什么是掌控板? 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片,支持WiFi和蓝牙双模通信,可作为物联网节点,实现物联网应用。同时掌控板上集成了OLED…...
pytorch 中 view 和reshape的区别
在 PyTorch(一个流行的深度学习框架)中, reshape 和 view 都是用于改变张量(tensor)形状的方法,但它们在实现方式和使用上有一些区别。下面是它们之间的主要区别: 实现方式: reshap…...
认识数组指针
文章目录 数组指针的定义数组指针的应用 数组指针的定义 类比 整形数组——存放整形的数组 指针数组——存放指针的数组 整形指针——存放整形地址的指针 数组指针——存放数组地址的指针 深度理解 在之前我们知道:数组名表示首元素地址,但是有…...
SSM面试题-Spring容器的启动流程
解答: 1. BeanDefinitionReader读取配置文件(xml yml properties),创建BeanDefinition(存储bean的定义信息) 2. 配置文件读取成功后,将相应的配置转换成 BeanDefinition 的对象实例保存在DefaultListableBeanFactory#beanDefinitionMap 中 3. 根据配置的 BeanFacto…...
Vue 3:玩一下web前端技术(八)
前言 本章内容为VUE基础与相关技术讨论。 上一篇文章地址: Vue 3:玩一下web前端技术(七)_Lion King的博客-CSDN博客 下一篇文章地址: (暂无) 一、基础 官方文档:创建一个 Vue…...
AI绘画Stable Diffusion原理之Autoencoder-Latent
前言 传送门: stable diffusion:Git|论文 stable-diffusion-webui:Git Google Colab Notebook:Git kaggle Notebook:Git 今年AIGC实在是太火了,让人大呼许多职业即将消失,比如既能帮…...
C++核心知识点总结
学习一门新的程序设计语言得到最好方法就是练习编写程序! C基础 变量和基本类型 基本内置类型 定义解释 算术类型 整型:包括字符和布尔类型,bool、char、wchar_t、char16_t、char32_t、short、int、long、long long、 浮点型:…...
echart折线图,调节折线点和y轴的间距(亲测可用)
options代码: options {tooltip: {trigger: axis, //坐标轴触发,主要在柱状图,折线图等会使用类目轴的图表中使用。},xAxis: {type: category,//类目轴,适用于离散的类目数据,为该类型时必须通过 data 设置类目数据。…...
Power BI-云端报表定时刷新--ODBC、MySQL、Oracle等其他本地数据源的刷新(二)
ODBC数据源 一些小众的数据源无法直接连接,需要通过微软系统自带的应用“ODBC数据源”连接。 1.首次使用应安装对应数据库的ODBC驱动程序,Mysql的ODBC驱动需要手动安装 2.在web服务中进行数据源的配置 Mysql数据源 1.Powerbi与Gateway第一次连SQL…...
redis 淘汰策略和持久化
文章目录 一、淘汰策略1.1 背景1.2 淘汰策略 二、持久化2.1 AOF日志2.1.1 AOF配置2.1.2 AOF策略2.1.3 AOF缺点2.1.4 AOF Rewrite2.1.5 AOF Rewrite配置2.1.6 AOF Rewrite缺点2.1.7 fork进程时的写时复制2.1.8 大key对持久化的影响 2.2 RDB快照2.2.1 RDB配置2.2.2 RDB缺点 2.3 混…...
Redis学习路线(6)—— Redis的分布式锁
一、分布式锁的模型 (一)悲观锁: 认为线程安全问题一定会发生,因此在操作数据之前先获取锁,确保线程串行执行。例如Synchronized、Lock都属于悲观锁。 优点: 简单粗暴缺点: 性能略低 &#x…...
一、创建自己的docker python容器环境;支持新增python包并更新容器;离线打包、加载image
1、创建自己的docker python容器环境 参考:https://blog.csdn.net/weixin_42357472/article/details/118991485 首先写Dockfile,注意不要有txt等后缀 Dockfile # 使用 Python 3.9 镜像作为基础 FROM python:3.9# 设置工作目录 WORKDIR /app# 复制当前…...
【Git】git企业开发命令整理,以及注意点
1.git企业开发过程 业务的分支大概有以下几个: master:代码随时可能上线 develop:代码最新 feature/xxx:实际业务开发分支 release/xxx:预发布分支 fix:修复bug分支 过程大概是这样的: 首…...
使用Django自带的后台管理系统进行数据库管理的实例
Django自带的后台管理系统主要用来对数据库进行操作和管理。它是Django框架的一个强大功能,可以让你快速创建一个管理界面,用于管理你的应用程序的数据模型。 使用Django后台管理系统,你可以轻松地进行以下操作: 数据库管理&…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
CSS3相关知识点
CSS3相关知识点 CSS3私有前缀私有前缀私有前缀存在的意义常见浏览器的私有前缀 CSS3基本语法CSS3 新增长度单位CSS3 新增颜色设置方式CSS3 新增选择器CSS3 新增盒模型相关属性box-sizing 怪异盒模型resize调整盒子大小box-shadow 盒子阴影opacity 不透明度 CSS3 新增背景属性ba…...
Easy Excel
Easy Excel 一、依赖引入二、基本使用1. 定义实体类(导入/导出共用)2. 写 Excel3. 读 Excel 三、常用注解说明(完整列表)四、进阶:自定义转换器(Converter) 其它自定义转换器没生效 Easy Excel在…...
基于Java项目的Karate API测试
Karate 实现了可以只编写Feature 文件进行测试,但是对于熟悉Java语言的开发或是测试人员,可以通过编程方式集成 Karate 丰富的自动化和数据断言功能。 本篇快速介绍在Java Maven项目中编写和运行测试的示例。 创建Maven项目 最简单的创建项目的方式就是创建一个目录,里面…...
【threejs】每天一个小案例讲解:创建基本的3D场景
代码仓 GitHub - TiffanyHoo/three_practices: Learning three.js together! 可自行clone,无需安装依赖,直接liver-server运行/直接打开chapter01中的html文件 运行效果图 知识要点 核心三要素 场景(Scene) 使用 THREE.Scene(…...
C/Python/Go示例 | Socket Programing与RPC
Socket Programming介绍 Computer networking这个领域围绕着两台电脑或者同一台电脑内的不同进程之间的数据传输和信息交流,会涉及到许多有意思的话题,诸如怎么确保对方能收到信息,怎么应对数据丢失、被污染或者顺序混乱,怎么提高…...
