自定义防抖注解
问题场景
在开发中由于可能存在的网络波动问题导致用户重复提交,所以自定义一个防抖注解。设计思路:自定义注解加在接口的方法上,注解中设置了SPEL表达式,可以通过SPEL表达式从接口参数中提取Redis的Key,以这个Key作为判断是否重复提交的依据。如果没有设置SPEL表达式的话就以当前登录用户的ID作为Key。同时在将数据设置到缓存的时候使用Lua脚本执行保证Redis命令的原子性。
代码实现
自定义注解
package com.creatar.common.annotation;import java.lang.annotation.*;/*** 防抖注解** @author: 张定辉* @date: 2024/6/13 上午9:43* @description: 防抖注解*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RepeatLock {/*** SPEL表达式,根据该表达式解析出的值作为key** @return SPEL表达式解析得到的值*/String value();/*** redis前缀*/String prefix() default "repeat_lock::";/*** 错误提示信息*/String message() default "请勿重复提交!";/*** 设置单位时间内禁止重复提交,以秒为单位*/int unitTime() default 3;
}
AOP注解处理器
package com.creatar.common.annotation.handler;import com.creatar.common.annotation.RepeatLock;
import com.creatar.exception.CustomException;
import com.creatar.util.SecurityUtil;
import com.creatar.util.SpelUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.expression.EvaluationContext;
import org.springframework.stereotype.Component;import java.util.Collections;
import java.util.Objects;/*** 防抖注解处理器** @author: 张定辉* @date: 2024/6/13 上午9:49* @description: 防抖注解处理器*/
@Aspect
@RequiredArgsConstructor
@Slf4j
@Component
public class RepeatLockAspect {private final RedisTemplate<String, String> redisTemplate;@Before("@annotation(repeatLock)")public void before(JoinPoint joinPoint, RepeatLock repeatLock) {String redisPrefix = repeatLock.prefix();String errorMessage = repeatLock.message();String value = repeatLock.value();int unitTime = repeatLock.unitTime();MethodSignature signature = (MethodSignature) joinPoint.getSignature();EvaluationContext context = SpelUtil.getContext(joinPoint.getArgs(), signature.getMethod());String key = SecurityUtil.getCurrentUserId();try {key = key + SpelUtil.getValue(context, value, String.class);} catch (Exception e) {log.error("防抖注解获取SPEL表达式失败,类名称:{},方法名称{}\n", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(), e);}String redisKey = redisPrefix + key;//如果是重复提交则抛出异常if (isRepeat(redisKey,unitTime)) {throw new CustomException(errorMessage);}}/*** 使用Lua脚本执行原子性的Redis操作,避免由于并发过大从而导致的key永久有效* 如果key不存在则设置value为1并且设置过期时间,** @return 如果没有key则false,如果有key则返回true表示重复提交*/private boolean isRepeat(String key,int unitTime) {String scriptStr = """if redis.call('exists', KEYS[1]) == 0 thenredis.call('set', KEYS[1], 1, 'ex',%s)return falseelsereturn trueend""".formatted(unitTime);RedisScript<Boolean> script = new DefaultRedisScript<>(scriptStr, Boolean.class);Boolean result = redisTemplate.execute(script, Collections.singletonList(key));if (Objects.isNull(result)) {return true;}return result;}
}
应用
package com.creatar.controller;import com.creatar.common.Res;
import com.creatar.common.annotation.RepeatLock;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.security.PermitAll;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;/*** 测试接口** @author: 张定辉* @date: 2024/6/15 下午4:36* @description: 测试接口*/
@RestController
@RequestMapping("/test")
@Tag(name = "测试接口",description = "测试接口")
@PermitAll
public class TestController {@GetMapping("/testLimit")@RepeatLock(value = "#param",unitTime = 5)public Res<String> testLimit(@RequestParam(value = "param")String param) {return Res.success(param);}
}
相关文章:
自定义防抖注解
问题场景 在开发中由于可能存在的网络波动问题导致用户重复提交,所以自定义一个防抖注解。设计思路:自定义注解加在接口的方法上,注解中设置了SPEL表达式,可以通过SPEL表达式从接口参数中提取Redis的Key,以这个Key作为…...
【尚庭公寓SpringBoot + Vue 项目实战】登录管理(十八)
【尚庭公寓SpringBoot Vue 项目实战】登录管理(十八) 文章目录 【尚庭公寓SpringBoot Vue 项目实战】登录管理(十八)1、登录业务介绍2、接口开发2.1、获取图形验证码2.2、登录接口2.3、获取登录用户个人信息 1、登录业务介绍 登…...
【html】用html+css做地表最强王者荣耀辅助工具
源码: <!DOCTYPE html> <html><head><meta charset"utf-8" /><title></title><style>* {margin: 0;padding: 0;}body{background-color: blue;}.con {width: 300px;height: 500px;background-color: rgba(230,…...
TF-IDF、BM25传统算法总结
1. TF-IDF算法 F-IDF(词频-逆文档频率)是一种用于衡量文本中词语重要性的方法,特别适用于信息检索和文本挖掘任务。下面会拆分为两部分深入讲解TF-IDF的计算过程,以便更好地理解。 TF-IDF的计算过程可以分为两个主要部分…...
项目五 OpenStack镜像管理与制作
任务一 理解OpenStack镜像服务 1.1 •什么是镜像 • 镜像通常 是指一系列文件或一个磁盘驱动器的精确副本 。 • 虚拟机 所使用的虚拟磁盘, 实际上是 一种特殊格式的镜像文件 。 • 云 环境下尤其需要 镜像。 • 镜像 就是一个模板,类似于 VMware 的虚拟…...
LabVIEW回热系统热经济性分析及故障诊断
开发了一种利用LabVIEW软件的电厂回热系统热经济性分析和故障诊断系统。该系统针对火电厂回热加热器进行优化,通过实时数据监控与分析,有效提高机组的经济性和安全性,同时降低能耗和维护成本。系统的实施大幅提升了火电厂运行的效率和可靠性&…...
设计模式-迭代器模式
目录 一:基本介绍 二:原理说明 三:案例说明 四:优点 五:缺点 一:基本介绍 1)属于行为模式 2)如果我们的集合元素是用不同的方式实现的,有数组,还有java的集合类,或者还有其他方式,当客户 端要遍历这些集合元素的时候就要使用多种遍历方式,而且还会暴露元素的内部结构,可以…...
UV胶带和UV胶水的应用场景有哪些不同吗?
UV胶带和UV胶水的应用场景有哪些不同吗? UV胶带和UV胶水的应用场景确实存在不同之处,以下是详细的比较和归纳: 一:按使用场景来看: UV胶带的应用场景: 包装行业:UV胶带在包装行业中常用于食品包装、药…...
监控员工上网软件有哪些|4款好用的员工上网行为管理软件推荐
在当今数字化办公环境中,确保网络安全、提升工作效率、以及规范员工上网行为成为企业管理的重要组成部分。 为此,一套高效的员工上网行为管理软件显得尤为关键。 本文将为您推荐五款市场上广受好评的员工上网行为管理软件,帮助您有效监控与管…...
【IPython的使用技巧】
🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出…...
最新AI智能聊天对话问答系统源码(详细图文搭建部署教程)+AI绘画系统(Midjourney),DALL-E3文生图,TTS语音识别输入,文档分析
一、文章前言 随着人工智能技术的持续进步,AI绘画已经发展成为一个日益成熟的领域。越来越多的人开始尝试使用AI绘画软件来创作艺术作品。尽管这些AI绘画软件对绘画领域产生了显著影响,但它们并不会完全取代画师。与传统手绘不同,AI绘画可以…...
项目四 OpenStack身份管理
任务一 理解身份服务 1.1 •Keystone的基本概念 • 认证 ( Authentication ) —— 确认 用户身份的过程,又称身份验证 。 • 凭证 ( Credentials ) —— 又 称凭据,是用于确认用户身份的数据 。 • 令牌 …...
【后端】websocket学习笔记
文章目录 1. 消息推送常见方式1.1 轮询 VS 长轮询1.2 SSE(server-sent event)服务器发送事件 2. websocket介绍2.1 介绍2.2 原理2.3 websoket API2.3.1 客户端【浏览器】API2.3.2 服务端API 3. 代码实现3.1 流程分析3.2 pom依赖3.3 配置类3.4 消息格式3.5 消息类 4.…...
DataWhale - 吃瓜教程学习笔记(一)
学习视频:第1章-绪论_哔哩哔哩_bilibili 西瓜书对应章节: 第一章 & 第二章 文章目录 机器学习三观What:什么是机器学习?Why: 为什么要学机器学习?1. 机器学习理论研究2. 机器学习系统开发3. 机器学习算法迁移 &…...
Attention Is All You Need论文地址
论文地址 点击即可...
如何优雅的一键下载OpenHarmony活跃分支代码?请关注【itopen: ohos_download】
itopen组织:1、提供OpenHarmony优雅实用的小工具2、手把手适配riscv qemu linux的三方库移植3、未来计划riscv qemu ohos的三方库移植 小程序开发4、一切拥抱开源,拥抱国产化 一、概述 为方便大家每次下载OpenHarmony不同分支/tag代码,…...
torch.topk用法
torch.topk用法 介绍使用示例 介绍 官网介绍:https://pytorch.org/docs/stable/generated/torch.topk.html 在指定维度选取k个最大(最小)的值。 使用示例 values torch.tensor([[2, 1, 3], [1, 2, 3]]) # values # tensor([[2, 1, 3], #…...
终极版本的Typora上传到博客园和csdn
激活插件 下载网址是这个: https://codeload.github.com/obgnail/typora_plugin/zip/refs/tags/1.9.4 解压之后这样的: 解压之后将plugin,复制到自己的安装目录下的resources 点击安装即可: 更改配置文件 "dependencies&q…...
洛谷:P5707【深基2.例12】上学迟到
1. 题目链接 https://www.luogu.com.cn/problem/P5707 【深基2.例12】上学迟到 2. 题目描述 学校和y的家距离s米,s以v的速度去学校,8点之前到,y出门前要打扫10分钟卫生,求s最晚的出门时间 输入:两个正整数路程s&…...
数据治理:数据提取过程中的合规性与安全性
数据治理:数据提取过程中的合规性与安全性 随着数字化时代的到来,数据已经成为企业运营和决策的核心驱动力。然而,在数据提取的过程中,确保数据的合规性和安全性成为了企业面临的重要挑战。数据治理作为一种系统的方法࿰…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
