我做了个 AI 文档阅读神器,免费开源!
诔士写镣一、关于RabbitMQ回调机制知识点补充: https://www.cnblogs.com/Mr-Keep/p/19140274在 RabbitMQ 中生产者发送消息后有可能遇到以下几种情况消息成功投递到交换机Exchange消息未能成功投递到交换机Exchange消息成功进入交换机但无法路由到队列Queue如果生产者端没有回调确认机制就可能出现严重的数据不一致举例 Redis 已经增加点赞数但消息并未真正进入 MQ数据库后续也无法更新就出现了 “缓存超前、数据库缺失” 的问题。为了解决这种问题Spring AMQP 提供了RabbitTemplate.setConfirmCallback()RabbitTemplate.setReturnsCallback()来捕获和处理消息投递的成功与失败。但是在复杂系统中不同的业务消息例如“下单”、“扣库存”、“发积分”在投递失败时需要采取不同的补偿逻辑。弊端如果你只写一份大而全的回调逻辑代码就会充满大量的 if else 判断非常难维护。二、策略模式思想引入策略模式的核心思想是定义一系列算法或行为让它们可以相互替换且算法的变化不会影响使用算法的客户。“算法” ≈ “不同的消息回调处理逻辑”“客户” ≈ “RabbitTemplate 的 ConfirmCallback 回调”操作通过根据业务抽象接口 Map 注入在运行时动态选择。代码实现1、定义统一的回调处理接口public interface ConfirmCallbackService {/*** 投递失败后的回调处理* param message 投递的消息对象*/void confirmCallback(Message message);}例定义点赞案例的实现类可选public class LikeConfirmCallback implements ConfirmCallbackService{/*** 注入RedisTemplate*/private final RedisTemplate redisTemplate;/*** 执行失败后的反向操作* param message 投递的消息对象*/Overridepublic void confirmCallback(Message message) {byte[] bytes message.getBody();//反向序列化为LikeDTO对象try {LikeDTO dto new ObjectMapper().readValue(bytes, LikeDTO.class);if(dto.getLikeStatus()){redisTemplate.opsForSet().add(LikeEssayEnum.LIKE_ESSAY_PREFIX.getValue()dto.getEid(), dto.getUid());}else{redisTemplate.opsForSet().remove(LikeEssayEnum.LIKE_ESSAY_PREFIX.getValue()dto.getEid(),dto.getUid());}} catch (IOException e) {throw new RuntimeException(e);}}}小技巧可选不单独定义类而是让业务层本身实现ConfirmCallbackService接口,简化书写操作分离成策略类则更利于模块化、解耦和扩展。2、回调上下文: 策略分发器ComponentRequiredArgsConstructorSlf4jpublic class ConfirmCallbackContext {/*** 注入RabbitTemplate*/private final RabbitTemplate rabbitTemplate;/*** 注入所有ConfirmCallbackService的实现类* 在不同的业务场景调用不同的实现来处理投递失败的业务逻辑*/private final Map confirmCallbackServiceMap;/*** 统一调用回调处理* 在容器初始化就执行这个方法*/PostConstructpublic void confirmCallback(){rabbitTemplate.setConfirmCallback((cdata,ack,cause)-{ReturnedMessage returnedMessage cdata.getReturned();if(ack){log.info(The message was delivered to the{},returnedMessage);}else{//获取业务实现的bean的idString beanName returnedMessage.getReplyText();//根据bean的名称从map中获取相应的实现类ConfirmCallbackService callbackService confirmCallbackServiceMap.get(beanName);callbackService.confirmCallback(returnedMessage.getMessage());}});}}核心原理Spring Boot 会自动扫描所有实现 ConfirmCallbackService 的 BeanBean 名称作为 keyBean 实例作为 value 注入到 MapConfirmCallbackContext 根据 replyText 动态找到对应的策略实现类3.消息发送端封装ComponentRequiredArgsConstructorpublic class RabbitManager {private final RabbitTemplate rabbitTemplate;public void send(String exchange,String routingKey,String callbackBeanName,T data){try {//创建cdata对象并设置一个idCorrelationData correlationData new CorrelationData(UUID.randomUUID().toString());//将投递的数据转换为byte[]byte[] bytes new ObjectMapper().writeValueAsBytes(data);//将bytes封装为Message对象Message message new Message(bytes);//创建一个投递失败时返回的消息对象ReturnedMessage returnedMessage new ReturnedMessage(message, 0,callbackBeanName, exchange,routingKey);//将ReturnedMesssage保存到cdata中correlationData.setReturned(returnedMessage);//发送rabbitTemplate.convertAndSend(exchange,routingKey,data,correlationData);} catch (Exception e) {throw new RuntimeException(e);}}}** 关键点**callbackBeanName 会被放进 replyText 中作为“回调策略的指针”。4.点赞业务逻辑方法4.1简化写法Overridepublic LikeDTO likeEssay(Integer uid, Integer eid) {boolean likeStatus false;//如果缓存中存在用户id则取消点赞不存在则添加用户id记录点赞if(isLike(eid, uid)) {//将用户ID从set集合中移除redisTemplate.opsForSet().remove(LikeEssayEnum.LIKE_ESSAY_PREFIX.getValue() eid, uid);} else {likeStatus true;//将用户ID添加到set集合中redisTemplate.opsForSet().add(LikeEssayEnum.LIKE_ESSAY_PREFIX.getValue() eid, uid);}//获取当前帖子在redis中的点赞总数Long likeCount redisTemplate.opsForSet().size(LikeEssayEnum.LIKE_ESSAY_PREFIX.getValue() eid);//创建LikeDTO封装修改的数据并发布到消息队列LikeDTO likeDTO new LikeDTO(eid, uid, likeCount,likeStatus);//发送到mq异步更新到数据库rabbitManager.send(RabbitmqConfig.EXCHANGE_NAME, RabbitmqConfig.ROUTING_KEY,likeServiceImpl, likeDTO);return likeDTO;}/*** 消息投递失败后的处理* param message 失败后返回的消息*/Overridepublic void confirmCallback(Message message) {byte[] bytes message.getBody();try {//反序列化为LikeDTO对象LikeDTO dto new ObjectMapper().readValue(bytes, LikeDTO.class);//执行反向操作if(dto.getLikeStatus()) {redisTemplate.opsForSet().remove(LikeEssayEnum.LIKE_ESSAY_PREFIX.getValue() dto.getEid(), dto.getUid());} else {redisTemplate.opsForSet().add(LikeEssayEnum.LIKE_ESSAY_PREFIX.getValue() dto.getEid(), dto.getUid());}} catch (IOException e) {throw new RuntimeException(e);}}4.2 有业务实现类时public LikeDTO likeEssay(Integer uid, Integer eid) {boolean likeStatus false;//如果缓存中存在用户id则取消点赞不存在则添加用户id记录点赞if(isLike(uid,eid)){//取消点赞redisTemplate.opsForSet().remove(LikeEssayEnum.LIKE_ESSAY_PREFIX.getValue()eid,uid.toString());likeMapper.deleteLike(eid,uid);}else{likeStatus true;//将用户ID添加到set集合中redisTemplate.opsForSet().add(LikeEssayEnum.LIKE_ESSAY_PREFIX.getValue()eid,uid.toString());}//获取当前帖子在redis中的点赞总数Long likeCount redisTemplate.opsForSet().size(LikeEssayEnum.LIKE_ESSAY_PREFIX.getValue() eid);//创建LikeDTO封装修改的数据并发布到消息队列LikeDTO likeDTO new LikeDTO(eid, uid, likeCount,likeStatus);//发送到mq异步更新到数据库rabbitManager.send(RabbitmqConfig.EXCHANGE_NAME,RabbitmqConfig.ROUTING_KEY,likeConfirmCallbackService,likeDTO);return likeDTO;}

相关新闻

这份榜单够用!10个AI论文工具测评:本科生毕业论文写作必备指南

这份榜单够用!10个AI论文工具测评:本科生毕业论文写作必备指南

在当前学术写作日益依赖AI工具的背景下,本科生在毕业论文写作过程中常常面临选题困难、文献整理繁琐、格式规范不熟等挑战。为了帮助学生更高效地完成论文,我们基于2026年的实测数据与真实用户反馈,对市面上主流的10款AI论文工具进行了全面测…

2026/7/6 5:48:40 阅读更多 →
. LangChainj + 整合 Spring Boot

. LangChainj + 整合 Spring Boot

邑蚊劣僦在深度学习中,优化器(Optimizer)是连接模型与数据的桥梁,它负责根据损失函数的梯度来更新模型的参数,以期找到一组能最小化损失的“最优解”。优化器的选择和调优,直接关系到模型的训练速度、收敛性…

2026/5/17 8:16:00 阅读更多 →
强烈安利! AI论文软件 千笔写作工具 VS Checkjie,MBA专属写作神器!

强烈安利! AI论文软件 千笔写作工具 VS Checkjie,MBA专属写作神器!

随着人工智能技术的迅猛迭代与普及,AI辅助写作工具已逐步渗透到高校学术写作场景中,成为专科生、本科生、研究生完成毕业论文不可或缺的辅助手段。越来越多面临毕业论文压力的学生,开始依赖各类AI工具简化写作流程、提升创作效率。但与此同时…

2026/7/6 5:08:26 阅读更多 →

最新新闻

数据科学家的信号处理实战指南:时序特征工程与Python可落地方案

数据科学家的信号处理实战指南:时序特征工程与Python可落地方案

1. 这不是给电子工程师看的信号处理——而是一份数据科学家真正用得上的实操手册 “信号处理”四个字一出来,很多人脑子里立刻浮现出示波器、傅里叶变换公式、滤波器设计图,甚至还有人下意识翻出《奥本海姆信号与系统》——但我要先说清楚:这…

2026/7/6 11:01:07 阅读更多 →
LocalAI离线部署全攻略:内网环境下的私有AI服务搭建与优化

LocalAI离线部署全攻略:内网环境下的私有AI服务搭建与优化

1. 项目概述:为什么我们需要LocalAI的离线部署方案?最近在折腾本地大模型部署的朋友,估计没少听过LocalAI这个名字。简单来说,它就是一个让你能在自己的电脑或服务器上,搭建一个类似OpenAI API接口的开源项目。这意味着…

2026/7/6 10:59:04 阅读更多 →
Mob编程+本地大模型:重构人机协同开发新范式

Mob编程+本地大模型:重构人机协同开发新范式

1. 项目概述:这不是结对编程,是“ mob 编程”遇上 AI 的真实战场 “Mob Coding with AI: Lessons from a 9-Hour Sprint”——这个标题一出来,我就在团队 Slack 里被了三次。不是因为大家好奇什么叫 Mob Coding,而是所有人都在问&…

2026/7/6 10:59:04 阅读更多 →
C++笔记之std::list和std::vector的区别

C++笔记之std::list和std::vector的区别

C++笔记之std::list和std::vector的区别 code review! 文章目录 C++笔记之std::list和std::vector的区别 1. 核心区别对比 2. 怎么选?(使用场景) 这两种 C++ 标准库容器的核心区别可以概括为:** std::vector 是连续内存的“动态数组”,而 std::list 是分散内存的“双向…

2026/7/6 10:56:52 阅读更多 →
macOS Apple Silicon下Anaconda安装避坑指南:架构、校验与环境隔离

macOS Apple Silicon下Anaconda安装避坑指南:架构、校验与环境隔离

1. 为什么今天在 macOS 上装 Anaconda 不再是“点一下就完事”了? 你可能还记得五年前,双击那个 .pkg 文件,一路点“继续”,等进度条走完,打开终端敲 conda --version ,回车——绿色的版本号跳出来&…

2026/7/6 10:56:52 阅读更多 →
Excel ROUND函数底层原理与财务工程级避坑指南

Excel ROUND函数底层原理与财务工程级避坑指南

1. 项目概述:为什么一个“四舍五入”函数值得写上万字?Excel里敲下ROUND(A1,2),结果立刻出来——看起来简单得不能再简单。但如果你在财务报表里用它算过增值税、在工程预算中处理过材料损耗率、在科研数据里校验过有效数字,你大概…

2026/7/6 10:46:37 阅读更多 →

日新闻

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2与MySQL单元测试兼容性:5个关键SQL语句差异与规避方案1. 单元测试中的数据库兼容性挑战在Java开发领域,单元测试是保证代码质量的重要环节。当应用涉及数据库操作时,测试环境的搭建往往成为开发者的痛点。H2数据库因其轻量级、内存模式和快…

2026/7/6 0:01:17 阅读更多 →
Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘 【免费下载链接】rbtray A fork of RBTray from http://sourceforge.net/p/rbtray/code/. 项目地址: https://gitcode.com/gh_mirrors/rb/rbtray 你是否厌倦了Windows任务栏上密密麻麻的图标&…

2026/7/6 0:01:17 阅读更多 →
Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C 运行时库一键安装终极指南:告别DLL缺失烦恼 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过这样的情况:下载了…

2026/7/6 0:05:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/6 8:11:50 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/6 8:11:52 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/6 6:52:56 阅读更多 →

月新闻