springboot防止表单重复提交

第一种方法:单个防止

在Spring Boot应用中使用Redis来防止表单的重复提交,可以通过以下几个步骤来实现:

步骤 1: 添加依赖

确保你的项目中添加了Spring Boot Starter Data Redis和Spring Boot Starter Web依赖。在pom.xml文件中添加以下依赖:

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
</dependencies>

步骤 2: 配置Redis

application.propertiesapplication.yml中配置Redis服务器的信息:

spring.redis.host=localhost
spring.redis.port=6379

步骤 3: 创建一个工具类处理Redis操作

创建一个工具类来封装Redis的一些常用操作,比如设置键值对、获取键值对等。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;@Component
public class RedisUtil {@Autowiredprivate StringRedisTemplate stringRedisTemplate;public void set(String key, String value) {stringRedisTemplate.opsForValue().set(key, value);}public String get(String key) {return stringRedisTemplate.opsForValue().get(key);}public void delete(String key) {stringRedisTemplate.delete(key);}
}

步骤 4: 实现防重逻辑

在Controller中使用上面的工具类来实现防重逻辑。通常的做法是在请求开始时检查Redis中是否存在该请求的唯一标识(如用户ID + 时间戳),如果不存在则允许请求继续,并将此标识存入Redis;如果存在,则直接返回错误信息。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class MyController {@Autowiredprivate RedisUtil redisUtil;@PostMapping("/submit")public String submit(@RequestParam("userId") String userId) {// 使用用户ID和时间戳作为key,防止并发下的重复提交String key = "form_submit_" + userId + "_" + System.currentTimeMillis();if (redisUtil.get(key) != null) {return "请求重复,请勿重复提交!";} else {// 执行业务逻辑// ...// 将key存入Redis并设置过期时间redisUtil.set(key, "1", 5, TimeUnit.MINUTES);return "提交成功!";}}
}

请注意,在实际应用中,你可能需要根据具体需求调整上述代码,比如更改存储在Redis中的键的生成方式、设置更合理的过期时间等。此外,为了提高性能和避免并发问题,可以考虑使用Redis的原子操作,例如SETNX命令。

第二种方法:aop全局方法

使用AOP(面向切面编程)来统一处理防重复提交是一种很好的实践,它能减少重复代码并保持业务逻辑的清晰性。下面是如何使用Spring AOP来实现这一功能的示例。

首先,你需要在项目中添加Spring AOP的支持,通常情况下Spring Boot项目已经默认包含AOP支持。

步骤 1: 创建切面类

创建一个切面类,用于定义防重提交的逻辑。

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;import java.util.concurrent.TimeUnit;@Aspect
@Component
public class AntiDuplicateSubmissionAspect {private static final String KEY_PREFIX = "anti_duplicate_";@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Around("@annotation(antiDuplicateSubmission)")public Object antiDuplicateSubmit(ProceedingJoinPoint joinPoint, AntiDuplicateSubmission antiDuplicateSubmission) throws Throwable {// 从注解中获取参数名String paramName = antiDuplicateSubmission.value();// 获取方法参数Object[] args = joinPoint.getArgs();// 假设参数位置已知,或者通过参数名获取参数值String userId = (String) args[0];// 生成唯一标识符String key = KEY_PREFIX + userId + "_" + System.currentTimeMillis();// 检查是否已经存在if (stringRedisTemplate.hasKey(key)) {throw new RuntimeException("请求重复,请勿重复提交!");}// 设置过期时间,例如5分钟stringRedisTemplate.opsForValue().set(key, "1", 5, TimeUnit.MINUTES);try {return joinPoint.proceed();} finally {// 清理key,这一步在大多数情况下可选,因为设置了过期时间stringRedisTemplate.delete(key);}}
}

步骤 2: 创建自定义注解

创建一个自定义注解,用于标记需要防重提交的控制器方法。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AntiDuplicateSubmission {String value();
}

步骤 3: 应用注解

在需要防重提交的Controller方法上应用这个注解。

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class MyController {@PostMapping("/submit")@AntiDuplicateSubmission(value = "userId")public String submit(@RequestParam("userId") String userId) {// 执行业务逻辑// ...return "提交成功!";}
}

这样,每次有请求到达带有@AntiDuplicateSubmission注解的方法时,AOP切面会先执行防重检查,如果发现重复提交,则阻止业务逻辑执行并抛出异常。

注意,这里的AntiDuplicateSubmission注解的value属性应该与请求参数名匹配,以便正确地获取到用户ID或其他用于生成唯一标识符的参数。同时,使用System.currentTimeMillis()生成的时间戳作为一部分唯一标识符可能在高并发场景下存在并发问题,你可能需要一个更安全的唯一生成策略,例如UUID或者结合用户ID、请求时间以及随机数等生成一个更复杂的唯一标识符。

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

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

相关文章

探索风电机组:关键软件工具全解析

探索风电机组&#xff1a;关键软件工具全解析 随着可再生能源市场的迅猛发展&#xff0c;风电作为一种重要的可再生能源&#xff0c;其相关技术和工具也越来越受到重视。风电机组的设计、仿真、优化及运维等方面&#xff0c;都需要依靠一系列专业软件工具来实现。这些软件涵盖…

Netty中的ByteBuf使用介绍

ByteBuf有三类&#xff1a; 堆缓存区&#xff1a;JVM堆内存分配直接缓冲区&#xff1a;有计算机内存分配&#xff0c;JVM只是保留分配内存的地址信息&#xff0c;相对于堆内存方式较为昂贵&#xff1b;复合缓冲区&#xff1a;复合缓冲区CompositeByteBuf&#xff0c;它为多个B…

VS2019创建c++动态链接库dll与调用方法

VS2019创建c动态链接库dll与调用方法 1.点击文件-》新建-》项目&#xff0c;输入dll,选择具有导出项的(DLL)动态链接库 2.输入一个文件名&#xff1a;dll2 头文件.h 3.添加加减法函数&#xff1a; // 下列 ifdef 块是创建使从 DLL 导出更简单的 // 宏的标准方法。此 DLL 中的…

题解web

1.[LitCTF 2023]Follow me and hack me 1&#xff09;进入题目环境&#xff0c;提示get传参&#xff0c;post传参 2&#xff09;看看源码&#xff0c;也没啥 3&#xff09;直接用hackbar&#xff0c;传入对应参数即可得到FLAG 3&#xff09;但是扫描出来它后端还有东西&#x…

linux-磁盘空间显示指令

在Linux中&#xff0c;要查看磁盘空间并输出详细报告&#xff0c;你可以使用df&#xff08;disk filesystem&#xff09;命令。通过添加不同的选项&#xff0c;你可以定制df命令的输出&#xff0c;以获取更详细的信息。 以下是一些常用的df命令选项&#xff0c;以及它们如何帮…

Vue 学习笔记 总结

Vue.js 教程 | 菜鸟教程 (runoob.com) 放一下课上的内容 Vue练习 1、练习要求和实验2的用户注册一样&#xff0c;当用户输入后&#xff0c;能在下方显示用户输入的各项内容&#xff08;不需要实现【重置】按钮&#xff09; 2、实验报告中的实验小结部分来谈谈用JS、jQuery和…

大模型怎么评价未来

以下内容都是腾讯元宝大模型回答的结果&#xff0c;不代表个人的意见。 目录 腾讯元宝APP自我介绍主要功能用户体验技术特点用户评价腾讯元宝APP自我评价技术细节功能特点与其他大模型比较怎么选择人工智能模型选择人工智能模型的步骤考虑因素评估和优化模型未来大模型的发展…

618数码产品有什么推荐?四大2024“宝藏”数码产品推荐!

随着618购物节的热情逐渐升温&#xff0c;你是否在繁多且诱人的商品海洋中迷失方向&#xff0c;难以找到那最心仪的宝贝&#xff1f;团团在此特别为你精心挑选了一系列经过亲身体验的优质好物。这些推荐不仅时尚前沿&#xff0c;更贴合你的日常生活需求&#xff0c;确保实用与品…

霸气的短视频:成都科成博通文化传媒公司

霸气的短视频&#xff1a;瞬间的力量与魅力 在数字化浪潮中&#xff0c;短视频以其独特的魅力迅速崛起&#xff0c;成为社交媒体的新宠。而在众多短视频中&#xff0c;那些充满霸气、让人热血沸腾的作品&#xff0c;总能引起广泛的关注和讨论。成都科成博通文化传媒公司将从内…

CSS基础知识汇总

目录 CSS 基础知识1. CSS 的基本结构2. 选择器3. 常用 CSS 属性4. CSS 单位5. CSS 盒模型 总结 学习 CSS&#xff08;Cascading Style Sheets&#xff09;是前端开发的重要部分&#xff0c;它用于控制网页的样式和布局。以下是学习 CSS 过程中需要掌握的基本概念、符号和对应的…

Excel中的SUMPRODUCT函数:使用方法与案例分析

在Excel中&#xff0c;SUMPRODUCT函数是一个强大的工具&#xff0c;它允许你将数组间对应的元素相乘&#xff0c;并返回乘积之和。这个函数在处理复杂数据和分析时非常有用&#xff0c;特别是在需要多条件求和或计数的情况下。以下是对SUMPRODUCT函数使用方法的详细介绍和案例分…

LeetCode 1174, 274, 240

目录 1174. 即时食物配送 II题目链接表要求知识点思路代码 274. H 指数题目链接标签思路代码优化 240. 搜索二维矩阵 II题目链接标签特性线性查找 二分查找思路代码 官方题解的Z字形查找思路代码 1174. 即时食物配送 II 题目链接 1174. 即时食物配送 II 表 表Delivery的字…

Vue08-数据代理

一、Object.defineProperty() Object.defineProperty() 是 JavaScript 中的一个方法&#xff0c;用于直接在一个对象上定义一个新属性&#xff0c;或者修改一个对象的现有属性&#xff0c;并返回这个对象。 这个方法允许你精确地控制一个对象的属性&#xff0c;包括它的值、是…

1. 在Java中,为何枚举类型的比较推荐==而不是equals

开源项目SDK&#xff1a;https://github.com/mingyang66/spring-parent 个人文档&#xff1a;https://mingyang66.github.io/raccoon-docs/#/ 比较运算符和equals的区别 比较运算符是比较两个对象在内存中的引用&#xff0c;equals方法是比较两个对象的值是否相等。 枚举类型…

数据库存储过程和锁机制

存储过程 存储过程是事先经过编译并存储在数据库中的一段SQL语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的&#xff0c;存储过程思想上很简单,就是数据库SQL语言层面的代码封装与有重用 …

找工作,你知道找你的是外包吗?这篇文章讲透各种外包、内包公司!

文章目录 一、传统外包公司二、软件厂商。三、内包如何选择?参考链接互联网上存在大量键盘侠,但多数缺乏对行业的深入了解,凭个人热情和经历妄下定论。为避免误导,现详细探讨市场上涉及“外包”的不同公司类型,希望能为大家提供帮助。 一、传统外包公司 首先是传统的外包…

Flutter开发效率提升1000%,Flutter Quick教程之对Widget进行删除,剪切,粘贴

一&#xff0c;删除操作 1&#xff0c;首先我们选中要删除的Widget。 2&#xff0c;在左边的侧边栏&#xff0c;点击删除按钮&#xff0c;即可完成对组件的删除操作。 二&#xff0c;剪切。剪切是相同的道理&#xff0c;都是先选中&#xff0c;再点击对应的按钮。 1&#xff…

C#朗读语音

最近有个需求&#xff0c;需要在C#程序发生异常时候&#xff0c;朗读文字&#xff0c;C#提供了.net framework可以提供简单的语音朗读功能。 引入依赖 using System.Media; using System.Speech.Synthesis; using System.Runtime.InteropServices; //报警音量 SystemSounds.…

【程序语言定义】

文章目录 一、程序语言的定义与分类1.程序语言的定义2.程序语言的分类低级语言高级语言 二、程序语言的组成1.语法&#xff08;Syntax&#xff09;2.语义&#xff08;Semantics&#xff09;3.实现&#xff08;Implementation&#xff09; 三、程序语言的发展历程早期的机器语言…

javaWeb4 Maven

Maven-管理和构建java项目的工具 基于POM的概念 1.依赖管理&#xff1a;管理项目依赖的jar包 &#xff0c;避免版本冲突 2.统一项目结构&#xff1a;比如统一eclipse IDEA等开发工具 3.项目构建&#xff1a;标准跨平台的自动化项目构建方式。有标准构建流程&#xff0c;能快速…