【CouponHub项目开发】使用RocketMQ5.x实现延时修改优惠券状态,并通过使用模板方法模式重构消息队列发送功能

在上个章节中我实现了创建优惠券模板的功能,但是,优惠券总会有过期时间,我们怎么去解决到期自动修改优惠券状态这样一个功能呢?我们可以使用RocketMQ5.x新出的任意定时发送消息功能来解决。

初始方案:
在这里插入图片描述

  • 首先在创建优惠券模板下面继续添加代码。首先先创建topic
    在这里插入图片描述
  • 接着去定义消息体
// 执行 RocketMQ5.x 消息队列发送&异常处理逻辑SendResult sendResult;try {sendResult = rocketMQTemplate.syncSendDeliverTimeMills(couponTemplateDelayCloseTopic, message, deliverTimeStamp);log.info("[生产者] 优惠券模板延时关闭 - 发送结果:{},消息ID:{},消息Keys:{}", sendResult.getSendStatus(), sendResult.getMsgId(), messageKeys);} catch (Exception ex) {log.error("[生产者] 优惠券模板延时关闭 - 消息发送失败,消息体:{}", couponTemplateDO.getId(), ex);}
  • 接着去调用相关方法去发送消息

这样一个延时发送的消息生产者就定义好了,接着我们去定义消费者。

在这里插入图片描述

  • 我们可以创建一个消费者类让他去实现RocketMQListener然后添加 @RocketMQMessageListener 注解,其中加上 Topic 和消费者组定义
  • 接着我们可以在onMessage方法内去定义我们接收到消息以后需要去做什么
  • 这里我们需要去修改数据库当中的优惠券的状态

这样就已经解决了定时修改优惠券模板状态这样的功能,但是这样直接写在代码当中不是太优雅,而且耦合度太高。我们可以通过去定义一个生产者的抽象类(模板),然后去通过定义具体的类来继承这些抽象类。然后在创建优惠券模板的方法中我们只需要去定义一个事件,然后调用该类的方法去发送消息即可。

@RequiredArgsConstructor
@Slf4j(topic = "CommonSendProduceTemplate")
public abstract class AbstractCommonSendProduceTemplate<T> {private final RocketMQTemplate rocketMQTemplate;/*** 构建消息发送事件基础扩充属性实体** @param messageSendEvent 消息发送事件* @return 扩充属性实体*/protected abstract BaseSendExtendDTO buildBaseSendExtendParam(T messageSendEvent);/*** 构建消息基本参数,请求头、Keys...** @param messageSendEvent 消息发送事件* @param requestParam     扩充属性实体* @return 消息基本参数*/protected abstract Message<?> buildMessage(T messageSendEvent, BaseSendExtendDTO requestParam);/*** 消息事件通用发送** @param messageSendEvent 消息发送事件* @return 消息发送返回结果*/public SendResult sendMessage(T messageSendEvent) {BaseSendExtendDTO baseSendExtendDTO = buildBaseSendExtendParam(messageSendEvent);SendResult sendResult;try {// 构建 Topic 目标落点 formats: `topicName:tags`StringBuilder destinationBuilder = StrUtil.builder().append(baseSendExtendDTO.getTopic());if (StrUtil.isNotBlank(baseSendExtendDTO.getTag())) {destinationBuilder.append(":").append(baseSendExtendDTO.getTag());}// 延迟时间不为空,发送任意延迟消息,否则发送普通消息if (baseSendExtendDTO.getDelayTime() != null) {sendResult = rocketMQTemplate.syncSendDeliverTimeMills(destinationBuilder.toString(),buildMessage(messageSendEvent, baseSendExtendDTO),baseSendExtendDTO.getDelayTime());} else {sendResult = rocketMQTemplate.syncSend(destinationBuilder.toString(),buildMessage(messageSendEvent, baseSendExtendDTO),baseSendExtendDTO.getSentTimeout());}log.info("[生产者] {} - 发送结果:{},消息ID:{},消息Keys:{}", baseSendExtendDTO.getEventName(), sendResult.getSendStatus(), sendResult.getMsgId(), baseSendExtendDTO.getKeys());} catch (Throwable ex) {log.error("[生产者] {} - 消息发送失败,消息体:{}", baseSendExtendDTO.getEventName(), JSON.toJSONString(messageSendEvent), ex);throw ex;}return sendResult;}
}

在该抽象类中定义了两个抽象方法,

  • protected abstract BaseSendExtendDTO buildBaseSendExtendParam(T messageSendEvent);该方法用来补充事件的相关属性

  • protected abstract Message<?> buildMessage(T messageSendEvent, BaseSendExtendDTO requestParam);该方法是用来补充消息的属性

  • sendMessage方法中首先会通过buildBaseSendExtendParam方法把事件的属性进行补充,比如延时时间等。

  • 然后会获取这个时间是否存在延时时间这个属性,如果有则发送延时消息,如果没有,就发送普通消息。

在这里插入图片描述
这就是延时发送消息的生产者的一个实现类

在这里插入图片描述
这是消费者没有太大变化。

我们现在梳理一下它的执行流程

  • 创建完优惠券模板之后,我们根据优惠券的相关信息构建出一个发送事件templateDelayEvent
  • 然后通过自动注入的couponTemplateDelayExecuteStatusProducer延时发送消息的生产者,调用它的发送消息方法进行延时发送消息。
  • 这个生产者是去实现了生产者的一个抽象类,并实现了补充事件属性,以及构建消息体的抽象方法。
  • 然后消费者通过监听该消息来完成消费。

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

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

相关文章

Claude Code SDK 配置Gitlab MCP服务

一、MCP配置前期准备 &#xff08;一&#xff09;创建个人令牌/群组令牌 我这里是创建个人令牌&#xff0c;去到首页左上角&#xff0c;点击头像——>偏好设置——>访问令牌——>添加新令牌 &#xff08;二&#xff09;配置mcp信息 去到魔塔社区&#xff0c;点击mc…

Eclipse 常用搜索功能汇总

Eclipse 常用搜索功能汇总 Eclipse 提供了多种搜索功能&#xff0c;帮助开发者快速定位代码、文件、类、方法、API 等资源。以下是详细的使用方法和技巧。 一、常用搜索快捷键快捷键功能描述Ctrl H打开全局搜索对话框&#xff0c;支持文件、Java 代码、任务等多种搜索。Ctrl …

关于Spring的一些理解

Spring整体结构&#xff1a;Spring实际运行场景&#xff1a;基础 Spring启动过程 传统Spring&#xff1a; &#xff08;1&#xff09;初始化准备阶段 &#xff08;2&#xff09;容器创建与注入 &#xff08;3&#xff09;Bean工厂后置处理 &#xff08;4&#xff09;Bean工厂后…

Windows右下角系统托盘图标快速显示或隐藏

系统托盘指的是Windows电脑桌面右下角的区域&#xff0c;包括时间、wifi&#xff08;网络&#xff09;、音量、电源、输入法、一些程序/应用等。启动了应用后&#xff0c;Windows会把部分应用的图标显示或隐藏在系统托盘区。我们可以根据需要快速显示或隐藏相关应用&#xff0c…

Kotlin编程学习记录2

Kotlin编程学习记录2——条件与循环 条件语句&#xff1a;if 与 when ​ Kotlin 的控制流把“表达式优先”作为设计原则——if、when 不只是控制语句&#xff0c;都可以作为表达式使用并返回值&#xff0c;这影响了日常代码风格&#xff08;更函数式、可组合&#xff09;。笔…

印度物联网崛起:政策红利下的千亿蓝海与本土化博弈

印度物联网市场正处于快速发展阶段,2025年市场规模预计达到200亿美元,主要得益于政府"数字印度"计划和智能城市项目的推动。蜂窝物联网连接数在2024年同比增长34%,2025年Q1增速进一步提升至32%,其中智能电表部署和资产追踪应用成为核心驱动力。然而,市场也面临着…

html学习:

ok,今天准备学一下html&#xff0c;花费点时间整理一下&#xff1a; HTML标签的语法格式 HTML 中的标签就像关键字一样&#xff0c;每个标签都有自己的语义&#xff08;含义&#xff09;。 HTML 标签的语法格式 属性↓ <div class"begin">cyx</div>↑…

CRYPT32!PkiAsn1Decode函数分析的一个例子

第一部分&#xff1a; 0: kd> g Breakpoint 35 hit CRYPT32!PkiAsn1Decode: 001b:75c9af0c 55 push ebp 1: kd> kc# 00 CRYPT32!PkiAsn1Decode 01 CRYPT32!PkiAsn1DecodeAndAllocInfo 02 CRYPT32!PkiAsn1DecodeAndAllocInfoEx 03 CRYPT32!Asn1InfoDecode…

大模型蒸馏、大模型微调、RAG

前言&#xff1a; 有很多同学想学习大模型开发&#xff0c;又无从下手&#xff0c;网上一搜&#xff0c;铺天盖地的付费课程。又不想当韭菜&#xff0c;打破认知障碍&#xff0c;通过自学&#xff0c;改变自己&#xff0c;改变世界&#xff01; 一、大模型蒸馏、微调、RAG的适…

25高教社杯数模国赛【E题保姆级思路+问题分析】

注&#xff1a;本内容由”数模加油站“ 原创出品&#xff0c;虽无偿分享&#xff0c;但创作不易。 欢迎参考teach&#xff0c;但请勿抄袭、盗卖或商用。 E 题 AI辅助智能体测 《国家学生体质健康标准》的颁布&#xff0c;有效地促进了大中小学生关注自身体质健康的发展&#xf…

基于单片机车内换气温度检测空气质量检测系统Proteus仿真(含全部资料)

全套资料包含&#xff1a;Proteus仿真源文件keil C语言源程序AD原理图流程图元器件清单说明书等 资料下载&#xff1a; 通过网盘分享的文件&#xff1a;资料分享 链接: 百度网盘 请输入提取码 提取码: tgnu 目录 资料下载&#xff1a; Proteus仿真功能 项目文件资料&#…

MySQL子查询的分类讲解与实战

精选专栏链接 &#x1f517; MySQL技术笔记专栏Redis技术笔记专栏大模型搭建专栏Python学习笔记专栏深度学习算法专栏 欢迎订阅&#xff0c;点赞&#xff0b;关注&#xff0c;每日精进1%&#xff0c;与百万开发者共攀技术珠峰 更多内容持续更新中&#xff01;希望能给大家带来…

Leetcode 206. 反转链表 迭代/递归

原题链接&#xff1a;Leetcode 206. 反转链表 解法一&#xff1a;迭代 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* …

C++11新特性 | 欢迎来到现代C++的世界!

左值与右值 左值与右值的概念 可以被取地址的值为左值&#xff08;left value&#xff0c;简称lvalue&#xff09;&#xff0c;否则为右值&#xff08;right value&#xff0c;简称rvalue&#xff09;。 常见的左值、右值例子&#xff1a; // >>>>>>> 左值…

因为对象装箱拆箱导致的空指针异常

今天业务突然提了个事件单&#xff0c;客户添加承租人一直报错&#xff0c;但是很奇怪&#xff0c;报错信息是空的二话不说&#xff0c;先跟API组要了接口和参数&#xff0c;然后看日志然鹅&#xff0c;这个接口并没有打印日志&#xff0c;只有一个e.printStackTrace()然后静下…

Rust 在 Windows 环境下交叉编译其他操作系统可执行文件的详细指南

前言&#xff1a;为什么需要交叉编译&#xff1f; 想象一下这样的场景&#xff1a;你在 Windows 电脑上开发了一个 Rust 程序&#xff0c;希望它能在 Linux 服务器上运行&#xff0c;或者在朋友的 macOS 电脑上测试 —— 总不能为了编译不同系统的版本&#xff0c;专门买一台 …

Ubuntu系统配置镜像源

要修改的文件 /etc/apt/sources.list操作步骤 1. 备份原文件 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak2. 编辑文件 sudo nano /etc/apt/sources.list3. 清空文件内容&#xff0c;填入以下内容 先获取Ubuntu版本代号&#xff1a; lsb_release -cs然后根据版本填…

【Spring Cloud Alibaba】Sentinel(一)

【Spring Cloud Alibaba】Sentinel&#xff08;一&#xff09;1. 简介2. 服务雪崩1. 简介 Sentinel 是阿里巴巴开源的分布式系统的流量防护组件&#xff0c;主要用来做流量控制、熔断降级、系统保护。它的定位类似于 Hystrix&#xff0c;但更侧重在 流量治理 上。目前在微服务…

Delphi 5 操作Word表格选区问题解析

在 Delphi 5 中操作 Word 时&#xff0c;您遇到的 Selection.MoveDown 方法选中整行而不是仅移动一行的原因与 Word 的选择机制和单元格内部结构有关。以下是详细解释和解决方案&#xff1a;问题分析单元格的选区范围&#xff1a;当使用 .Cell(r, c).Select 选中单元格时&#…