防止请求重复提交:注解+拦截器的实现方案
文章目录
- 了解请求重复提交
- 解决思路
- 具体实现
了解请求重复提交
请求重复提交是指用户在一次请求还未处理完成时,重复提交了相同的请求。这种情况通常发生在网络延迟、用户误操作或系统性能不佳等情况下。
请求重复提交可能会导致以下问题和影响:
-
数据不一致:如果重复提交的请求包含了对数据的修改操作,那么可能会导致数据不一致的问题,例如重复购买商品、重复支付订单等。
-
系统资源浪费:重复提交的请求会占用系统资源,导致服务器负载过高、响应时间变慢等问题,影响系统性能和用户体验。
-
安全问题:某些敏感操作(如支付、修改密码等)如果被重复提交,可能会导致安全问题,例如重复支付导致资金损失、重复修改密码导致账号被盗等。
因此,防止请求重复提交是保证系统数据一致性、提高系统性能和保障系统安全的重要措施。
解决思路
在 Spring Boot 中有效地防止用户在短时间内重复提交表单或请求,我们可以结合 Redis 来实现这个功能,我们可以将用户的请求信息存储在缓存中,这样我们就可以实时跟踪用户请求的状态,同时也可以提高系统的性能。为了限制用户在短时间内重复提交相同的请求,我们可以设置一个时间间隔来限制重复提交。用户在指定时间间隔内提交相同的请求时,将返回一个错误信息,否则请求将被正常处理。因此,通过这个方法,我们可以有效地防止用户在短时间内提交重复的请求,避免系统资源的浪费。通常情况下,我们可以使用注解+拦截器的方式来实现这个功能。
注解是一种在代码中添加元数据的方式,它可以为方法、类、字段等添加额外的信息。在请求重复提交的场景中,我们可以通过在方法或接口上添加自定义注解,在运行时通过反射机制来获取并解析注解信息,从而执行相应的逻辑。
而拦截器则是一种在请求到达控制器之前对请求进行处理的组件。它可以拦截请求,并在请求到达目标处理程序之前或之后执行一些预处理或后处理操作。
具体工作流程图如下:
具体实现
-
首先我们需要创建一个自定义注解,用于标记需要进行重复请求拦截的方法。例如,我们在项目中创建一个名为
@RepeatSubmit
的注解:@Inherited @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RepeatSubmit {/*** 间隔时间(ms),小于此时间视为重复提交*/public int interval() default 60000;/*** 提示消息*/public String message() default "不允许重复提交,请稍候再试";}
-
创建一个拦截器类,用于拦截带有
@RepeatSubmit
注解的请求。在拦截器中,可以通过保存请求的唯一标识(如token)来判断请求是否已经被处理过。@Component public class RepeatSubmitInterceptor implements HandlerInterceptor {@Autowiredprivate RedisCache redisCache;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 判断处理器对象是否为HandlerMethod类型if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod = (HandlerMethod) handler;Method method = handlerMethod.getMethod();// 获取方法上的RepeatSubmit注解RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);if (annotation != null) {// 获取请求的IP地址、URI、请求方法、请求参数和请求体String ipAddr = IpUtils.getIpAddr(request);String requestURI = request.getRequestURI();String requestMethod = request.getMethod();Map<String, String> requestParams = ServletUtils.getRequestParams(request);Map<String, String> requestBody = ServletUtils.getRequestBody(request);// 创建缓存数据对象,并将请求信息存入其中Map<String,Object> cacheData = new HashMap<>();cacheData.put("ip",ipAddr);cacheData.put("uri",requestURI);cacheData.put("method",requestMethod);cacheData.put("params",requestParams);cacheData.put("body",requestBody);// 将缓存数据进行MD5加密String md5V = MD5Utils.encrypt(cacheData);// 在Redis缓存中设置缓存对象,如果已存在则返回falseBoolean b = redisCache.setCacheObjectIfAbsent("repeat_submit:"+ipAddr+":"+md5V, cacheData, annotation.interval(), TimeUnit.MILLISECONDS);if(b){// 如果缓存设置成功,则放行请求return true;}else {// 如果缓存已存在,则返回重复提交错误信息AjaxResult ajaxResult = AjaxResult.error(annotation.message());ServletUtils.renderString(response, JSON.toJSONString(ajaxResult));return false;}}// 如果方法没有RepeatSubmit注解,则放行请求return true;}else {// 如果处理器对象不是HandlerMethod类型,则放行请求return true;}}}
-
在Spring Boot的配置类中注册拦截器:
@Configuration public class WebMvcConfig implements WebMvcConfigurer {@Autowiredprivate RepeatSubmitInterceptor repeatSubmitInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");}}
-
在需要进行重复请求拦截的方法上添加
@DuplicateSubmitToken
注解:@Controller public class MyController {@RequestMapping("/submit")@RepeatSubmitpublic String submit() {// 处理请求逻辑return "success";} }
-
启动项目,使用 ApiFox 发起请求访问
/submit
接口,发送成功: -
请求发送成功后,查看Redis中的缓存数据,包含我们请求时接口数据:
-
再次发起同样的请求,直接返回提示信息“不允许重复提交,请稍候再试”:
相关文章:

防止请求重复提交:注解+拦截器的实现方案
文章目录 了解请求重复提交解决思路具体实现 了解请求重复提交 请求重复提交是指用户在一次请求还未处理完成时,重复提交了相同的请求。这种情况通常发生在网络延迟、用户误操作或系统性能不佳等情况下。 请求重复提交可能会导致以下问题和影响: 数据不…...

C#使用mysql-connector-net驱动连接mariadb报错
给树莓派用最新的官方OS重刷了一下,并且用apt install mariadb-server装上“mysql”作为我的测试服务器。然后神奇的事情发生了,之前用得好好的程序突然就报错了,经过排查,发现在连接数据库的Open阶段就报错了。写了个最单纯的Con…...

SpringBoot 定时任务:@EnableScheduling @Scheduled
Scheduled注解参数 cron参数 这个参数是最经常使用的参数,表示接收一个cron参数,cron它是一个表达式,最多接收7个参数,从左到右分别表示:秒 分 时 天 月 周 年;参数以空格隔开,其中年不是必须参…...

Jquery 如何获取子元素。如何找到所有 HTML select 标签的选中项。jQuery 里的 ID 选择器和 class 选择器有何不同
可以使用 jQuery 的子选择器(Child Selector)或 find() 方法来获取子元素。 子选择器(Child Selector): 使用父元素的选择器和 > 符号来选取该父元素的子元素。 例如:选取 id 为 parent 的元素内所有 cl…...

Python Selenium 之数据驱动测试的实现!
数据驱动模式的测试好处相比普通模式的测试就显而易见了吧!使用数据驱动的模式,可以根据业务分解测试数据,只需定义变量,使用外部或者自定义的数据使其参数化,从而避免了使用之前测试脚本中固定的数据。可以将测试脚本…...

【Proteus仿真】【STM32单片机】智能语音家居陪护机器人
文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真STM32单片机控制器,使用OLED显示模块、红外传感器、蜂鸣器、DS18B20温度传感器,风扇LED、语音识别模块等。 主要功能: 系统运行后,…...

C#上位机序列10: 批量读写+点对点更新+数据类型处理
一、源码结构 二、运行效果 三、源码解析 PLC批量读写点对点更新数据类型处理 优点:根据数据类型,判定监听的地址范围(40120_int 监听两个word:40120 40121;40130_long 监听四个word:40130 40131 40132 4…...

MySQL 概述 数据库表操作 数据增删改
目录 MySQL概述前言安装与配置MySQL登录与卸载 数据模型概述SQL简介SQL通用语法简介SQL分类 数据库设计(数据库操作)-DDL数据库操作查询数据库 show databases、select database()创建数据库 create database使用数据库 use删除数据库 drop database 图形化工具连接数据库操作数…...

存储器概述
一、存储系统基本概念...

Fabric.js 使用自定义字体
本文简介 点赞 关注 收藏 学会了 如果你使用 Fabric.js 做编辑类的产品,有可能需要给用户配置字体。 这次就讲讲在 Fabric.js 中创建文本时怎么使用自定义字体、在项目运行时怎么修改字体、以及推荐一个精简字体库的工具。 学习本文前,你必须有一点…...

【C++项目】高并发内存池第七讲性能分析
目录 1.测试代码2.代码介绍3.运行结结果 1.测试代码 #include"ConcurrentAlloc.h" #include"ObjectPool.h" #include"Common.h" void BenchmarkMalloc(size_t ntimes, size_t nworks, size_t rounds) {std::vector<std::thread> vthread(…...

【JavaScript】快速学习JS
JS区分大小写,后面的分号可有可无; 输出语句 window.alter() // 写入警告框;在浏览器中的警告弹窗输出 document.write() // 写入html输出;在html页面中输出 console.log() // 写入浏览器控制台;在控制台输出 变量…...

控制输入流,从控制台打印到文件中,更改输出的位置
public static void main(String[] args) throws IOException {PrintStream printStream System.out;//在默认情况下,PrintStream 输出数据的位置 标准输出,即显示器printStream.print("Tom,hello");/*public void print(String s) {if (s n…...

计算线阵相机 到 拍摄产品之间 摆放距离?(隐含条件:保证图像不变形)
一物体被放置在传送带上,转轴的直径为100mm。已知线阵相机4K7u(一行共4096个像素单元,像素单元大小7um),镜头35mm,编码器2000脉冲/圈。保证图像不变形的条件下,计算相机到产品之间 摆放距离&…...

【网络】详解http协议
目录 一、认识URLurlencode和urldecode 二、HTTP协议HTTP协议格式HTTP的方法HTTP的状态码HTTP常见Header 一、认识URL URL叫做统一资源定位符,也就是我们平时俗称的网址,是因特网的万维网服务程序上用于指定信息位置的表示方法。 urlencode和urldecode …...

1819_ChibiOS的互斥信号与条件变量
全部学习汇总: GreyZhang/g_ChibiOS: I found a new RTOS called ChibiOS and it seems interesting! (github.com) 1. 关于会吃信号与条件变量的全局配置提供了4个配置信息,分别是互斥信号的使能、互斥信号的递归支持、条件变量的使能、条件变量的超时使…...

CSDN学院 < 华为战略方法论进阶课 > 正式上线!
目录 你将收获 适用人群 课程内容 内容目录 CSDN学院 作者简介 你将收获 提升职场技能提升战略规划的能力实现多元化发展综合能力进阶 适用人群 主要适合公司中高层、创业者、产品经理、咨询顾问,以及致力于改变现状的学员。 课程内容 本期课程主要介绍华为…...

电商接口api数据比价接口推荐
当前,受诸多因素的影响,经济下行,在日趋激烈的市场竞争中,很多企业也都面临着越来越大的生存压力,企业的盈利空间也逐渐被压缩。因此,越来越多的企业在控制成本方面更下功夫,这也就对企业采购提…...

读取Excel的工具类——ExcelKit
文章目录 ExcelKit工具类1、准备工作1.1、SheetInfoVo1.2、BizException 2、读取xlsx3、读取xls4、完整的ExcelKit.java源码 ExcelKit工具类 1、准备工作 1.1、SheetInfoVo import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;import …...

vscode连接服务器一直retry
解决方法 打开vscode控制面板,输入命令remote-ssh: kill vs code server on host 选择一直连接不上的服务器端口 重新连接...

Spring Cloud Sentinel整合Nacos实现配置持久化
sentinel配置相关配置后无法持久化,服务重启之后就没了,所以整合nacos,在nacos服务持久化,sentinel实时与nacos通信获取相关配置。 使用上一章节Feign消费者服务实现整合。 版本信息: nacos:1.4.1 Sentinel 控制台 …...

STM32F4VGT6-DISCOVERY:uart1驱动
对于这款板子,官方并没有提供串口例程,只能自行添加。 一、PA9/PA10复用成串口1功能不可用 驱动测试代码如下: main.c: #include "main.h" #include <stdio.h>void usart1_init(void) {GPIO_InitTypeDef GPIO_InitStruct…...

C语言之 结构体,枚举,联合
目录 1.结构体 1.1结构的基础知识 1.2结构的声明 1.3 特殊的声明 1.4 结构的自引用 1.5 结构体变量的定义和初始化 1.6 结构体内存对齐 1.7 修改默认对齐数 1.8 结构体传参 2. 位段 2.1 什么是位段 2.2位段的内存分配 2.3 位段的跨平台问题 3. 枚举 3.1 枚举类型…...

红米电脑硬盘剪切
Redmi R14 2023版固态硬盘剪切 工具准备操作结尾语 首先要说明,本文所说的操作不一定适合你的电脑,因为电子产品更新换代过快,你的硬盘不一定能剪切,在操作前一定要仔细观察硬盘的型号,是否为同款,我上了图…...

微信小程序在线预览PDF文件
需求:微信小程序在线预览PDF合同文件,加载完成后强制阅读10秒才可点击同意按钮 H5代码: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" cont…...

Android 工厂模式增加Type-A功能测试
Android 工厂模式增加Type-A功能测试 收到客户需求想要增加Type-A测试项来验证Type-A功能,具体功能实现参照如下: /vendor/freeme/packages/apps/FreemeFactoryTest/src/com/freeme/factory/usb/TypeAUSB.java package com.freeme.factory.usb;i…...

Web攻防06_sqlmap的使用
文章目录 参考链接: SQLMAP简介支持五种不同的注入模式 数据猜解-库表列数据权限操作引出权限:引出文件:引出命令(执行命令): 提交方法-POST&HEAD&JSONPost注入cookie注入注入请求头中(…...

C++模拟实现-----日期计算器(超详细解析,小白一看就会!)
目录 一、前言 二、日期类计算器 三、日期计算器的实现 🍎日期计算器各个接口的实现 🍐日期计算器的需求 🍉打印当前日期(并检查日期是否合理) 💦检查日期是否合理 💦日期类构造函数&#x…...

Oracle实现把B表某一字段更新到A表
1.使用SQL命令UPDATE语句。 2.使用MERGE语句。 3.使用TRIGGER触发器。 4.使用游标CURSOR和循环 使用游标和循环来将B表中的数据更新到A表中,从而实现了两个表数据的同步。例如下面的代码实现:...

CUMCM历年赛题汇总
题目来源: 全国大学生数学建模竞赛官网 注:题目和数据均可在官网下载 2021–2023年 年份题号题目2023A定日镜场的优化设计2023B多波束测线问题2023C蔬菜类商品的自动定价与补货决策2023D圈养湖羊的空间利用率2023E黄河水沙监测数据分析2022A波浪能最大…...