使用Redis控制表单重复提交控制接口访问频率

场景一:控制表单重复提交

防重提交有很多方案,从前端的按钮置灰,到后端synchronize锁、Lock锁、借助Redis语法实现简单锁、Redis+Lua分布式锁、Redisson分布式锁,再到DB的悲观锁、乐观锁、借助表唯一索引等等都可以实现防重提交,以保证数据的安全性。
这篇文章我们介绍其中一种方案–借助Redis语法实现简单锁,最终实现防重提交。

背景:

我们项目中,为了控制表单重复提交问题,会在点击按钮(向后端发起业务请求)后就会置灰按钮,直到后端响应后解除按钮置灰。按钮置灰防止了页面重启提交问题。但Postman、Jmeter和其他服务调用呢?所以后端接口也要根据需要控制一下表单重复提交问题。

后端代码可以在2个位置做控制:
一是放在gateway网关做
好处是只在一个地方加上控制代码,就可以控制所有接口的重复提交问题。坏处是控制的范围太广(比如查询接口无需控制,控制了反而多余)、定义重复提交的时间段不能灵活调整。
二是放在AOP切面做
好处是只有需要的地方才会被控制(哪里需要引用一下自定义注解即可),另外也能灵活调整定义重复提交的时间段(自定义注解里定义时间字段开放给使用者填写)。坏处是每个需要控制的地方都要加注解,会有侵入性和一定的工作量。

实现代码

1、添加自定义注解

package com.xxx.annotations;import java.lang.annotation.*;/*** 自定义注解防止表单重复提交** @Author WANGLINGQIANG* @Date 2023/9/6 10:11*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RepeatSubmit {/*** 过期时间,单位毫秒*/long expireTime() default 500L;}

2、添加AOP切面

package com.xxx.aop;import com.crdigital.intelligent.user.common.core.annotations.RepeatSubmit;
import com.crdigital.intelligent.user.common.core.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;/*** 防止表单重复提交切面** @Author WANGLINGQIANG* @Date 2023/9/6 10:13*/
@Slf4j
@Aspect
@Component
public class RepeatSubmitAspect {private static final String KEY_PREFIX = "repeat_submit:";@Resourceprivate RedisTemplate redisTemplate;@Pointcut("@annotation(com.crdigital.intelligent.user.common.core.annotations.RepeatSubmit)")public void repeatSubmit() {}@Around("repeatSubmit()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = requestAttributes.getRequest();String uri = request.getRequestURI();String cacheKey = KEY_PREFIX.concat(uri);Boolean flag = null;try {flag = redisTemplate.opsForValue().setIfAbsent(cacheKey, "", annotation.expireTime(), TimeUnit.MILLISECONDS);} catch (Exception e) {log.error("", e);return joinPoint.proceed();}if (flag) {return joinPoint.proceed();} else {throw new ServiceException("系统繁忙,请稍后重试");}}
}

这里利用redisTemplate的setIfAbsent()实现的,如果存在就不能set成功,set的同时设置过期时间,可以是用使用默认,也可以自己根据业务调整。
另外,cacheKey的定义,也可以根据自己的需要去调整,比如根据当前登录用户的userId、当前登录的token等。

3、使用

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {@RepeatSubmit@PostMappingpublic AjaxResult add(@Validated @RequestBody SysUser user) {//....}

场景二:控制接口调用频率

背景:

明天补充哈, 今天有事中断一下


实现代码

明天补充哈, 今天有事中断一下

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

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

相关文章

Unity 之 Material (材质)渲染3D对象的重要组件

文章目录 介绍一些代码例子 介绍 在Unity中,Material(材质)是一种用于渲染3D对象的重要组件。Material定义了对象的外观,包括其颜色、纹理、光照属性和反射等。以下是关于Material的详细介绍: 创建Material&#xff1…

云计算时代的采集利器

大家好!在今天的知识分享中,我们将探讨一个在云计算环境中的爬虫应用利器——独享IP。如果你是一名爬虫程序员,或者对数据采集和网络爬虫有浓厚的兴趣,那么这篇文章将向你展示独享IP在云计算环境下的应用价值。 1. 什么是独享IP&…

资深测试面试-参考一下

资深测试面试 1、项目情况根据什么来跟进 2、团队的情况 3、发现问题怎么去处理 4、用例会去重点关注哪些 5、根据测试用例能发现什么问题吗 6、举例最近一个需求的核心要点,用例你是怎么做的 7、产品把需求给到你,你后续的工作有哪些,主要会…

冠达管理:元宇宙三年行动计划发布,高增长潜力股名单出炉

未来5年,国内元国际商场规划至少打破2000亿元大关。 金融监管总局9月10日发布《关于优化保险公司偿付能力监管规范的告诉》,优化保险公司偿付能力监管规范,自发布之日起施行。 金融监管总局释放重要利好,引导保险资金更大力度地…

ClickHouse 存算分离改造:小红书自研云原生数据仓库实践

ClickHouse 作为业界性能最强大的 OLAP 系统,在小红书内部被广泛应用于广告、社区、直播和电商等多个业务领域。然而,原生 ClickHouse 的 MPP 架构在运维成本、弹性扩展和故障恢复方面存在较大局限性。为应对挑战,小红书数据流团队基于开源 C…

四叶草clover配置工具:Clover Configurator for Mac

Clover Configurator是一款Mac上的工具,用于配置和优化Clover引导加载器。Clover引导加载器是一种用于启动macOS的开源引导加载器。它允许用户在启动时选择操作系统和配置启动选项。 Clover Configurator提供了一个可视化的界面,让用户可以轻松地编辑和…

thinkphp6(tp6)创建定时任务

使用 thinkphp6 框架中提供的命令行形式实现定时任务 一、创建一个自定义命令类文件 php think make:command Hello 会生成一个 app\command\Hello.php 命令行指令类&#xff0c;我们修改内容如下&#xff1a; <?php declare (strict_types1);namespace app\command;use …

PlantUML入门教程:画时序图

软件工程中会用到各种UML图&#xff0c;例如用例图、时序图等。那我们能不能像写代码一样去画图呢&#xff1f; 今天推荐一款软件工程师的作图利器--PlantUML&#xff0c;它能让你用写代码的方式快速画出UML图。 一、什么是PlantUML&#xff1f; PlantUML是一个允许你快速作出…

【Ubuntu搭建MQTT Broker及面板+发布消息、订阅主题】

Ubuntu搭建MQTT Broker及面板发布消息、订阅主题 配置curl数据源 curl -s https://assets.emqx.com/scripts/install-emqx-deb.sh | sudo bash开始安装 sudo apt-get install emqx启动 sudo emqx start使用面板 根据自己的服务器是否开始了防火墙放行端口&#xff08;1808…

2023工博会,正运动机器视觉运动控制一体机应用预览(二)

展会倒计时&#xff1a;7天 本次的中国国际工业博览会正运动技术将携高性能x86平台Windows实时视觉运动控制器VPLC711亮相。 •运动控制机器视觉一站式开发&#xff0c;缩短开发周期&#xff0c;降低硬件成本&#xff1b; •可替代传统的工控机运动控制卡/PLC视觉软件的自动化…

平衡二叉搜索树(AVL)——【C++实现插入、删除等操作】

本章完整代码gitee地址&#xff1a;平衡二叉搜索树 文章目录 &#x1f333;0. 前言&#x1f332;1. AVL树概念&#x1f334;2. 实现AVL树&#x1f33f;2.1 结构定义&#x1f33f;2.2 插入&#x1f490;左单旋&#x1f490;右单旋&#x1f490;左右双旋&#x1f490;右左双旋 &a…

TypeScript:赋予JavaScript数据类型新的力量,提升编程效率!

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! ​ &#x1f4da; 前言 TypeScript&#xff1a;扩展JavaScript数据类型&#xff0c;赋予编程更强大的表达能力&#xff01…

数据挖掘实验-主成分分析与类特征化

数据集&代码https://www.aliyundrive.com/s/ibeJivEcqhm 一.主成分分析 1.实验目的 了解主成分分析的目的&#xff0c;内容以及流程。 掌握主成分分析&#xff0c;能够进行编程实现。 2.实验原理 主成分分析的目的 主成分分析就是把原有的多个指标转化成少数几个代表…

web3j solidity 转java

需要使用的环境 web3j&#xff0c;nodejs 安装编译sol工具 1 $ npm install -g solc 保存为hello.sol文件到本地 1 2 3 4 5 6 7 8 pragma solidity 0.4.19; contract hello { function main(uint a) constant returns (uint b) { uint result a * 8; …

Kafka3.0.0版本——消费者(Sticky分区分配策略以及再平衡)

目录 一、Sticky分区分配策略原理二、Sticky分区分配策略 示例需求三、Sticky分区分配策略代码案例3.1、创建带有7个分区的sevenTopic主题3.2、创建三个消费者 组成 消费者组3.3、创建生产者3.4、测试3.5、Sticky分区分配策略代码案例说明 四、Sticky分区分配再平衡案例4.1、停…

Redis 删除策略

文章目录 Redis 删除策略一、过期数据二、数据删除策略1、定时删除2、惰性删除3、定期删除4、删除策略对比 三、逐出算法 Redis 删除策略 一、过期数据 Redis是一种内存级数据库&#xff0c;所有数据均存放在内存中&#xff0c;内存中的数据可以通过TTL指令获取其状态 XX &a…

【李自然说】在创业路演现场,3分钟打动投资人 (notebook)[Updating]

【李自然说】在创业路演现场&#xff0c;3分钟打动投资人_哔哩哔哩_bilibili 融资的核心问题&#xff08;三分钟内讲清楚&#xff09; - 竞争者做什么&#xff0c;我们做什么 &#xff08;是否有&#xff0c;没有那潜在competitor是谁&#xff0c;有没有可能变成合作伙伴&#…

构建高效实时数据流水线:Flink、Kafka 和 CnosDB 的完美组合

当今的数据技术生态系统中&#xff0c;实时数据处理已经成为许多企业不可或缺的一部分。为了满足这种需求&#xff0c;Apache Flink、Apache Kafka和CnosDB等开源工具的结合应运而生&#xff0c;使得实时数据流的收集、处理和存储变得更加高效和可靠。本篇文章将介绍如何使用 F…

java的动态代理如何实现

一. JdkProxy jdkproxy动态代理必须基于接口(interface)实现 接口UserInterface.java public interface UserService {String getUserName(String userCde); }原始实现类&#xff1a;UseServiceImpl.java public class UserServiceImpl implements UserSerice {Overridepub…

举例说明PyTorch函数torch.cat与torch.stack的区别

一、torch.cat与torch.stack的区别 torch.cat用于在给定的维度上连接多个张量&#xff0c;它将这些张量沿着指定维度堆叠在一起。 torch.stack用于在新的维度上堆叠多个张量&#xff0c;它会创建一个新的维度&#xff0c;并将这些张量沿着这个新维度堆叠在一起。 二、torch.…