当前位置: 首页 > news >正文

SpringBoot表单防止重复提交

哪些因素会引起重复提交?
开发的项目中可能会出现下面这些情况:

前端下单按钮重复点击导致订单创建多次
网速等原因造成页面卡顿,用户重复刷新提交请求
黑客或恶意用户使用postman等http工具重复恶意提交表单

重复提交会带来哪些问题?

重复提交带来的问题

会导致表单重复提交,造成数据重复或者错乱
核心接口的请求增加,消耗服务器负载,严重甚至会造成服务器宕机

订单的防重复提交你能想到几种方案?
核心接口需要做防重提交,你应该可以想到以下几种方案:

方式一:前端JS控制点击次数,屏蔽点击按钮无法点击 前端可以被绕过,前端有限制,后端也需要有限制

方式二:数据库或者其他存储增加唯一索引约束 需要想出满足业务需求的唯一索引约束,比如注册的手机号唯一。但是有些业务是没有唯一性限制的,且重复提交也会导致数据错乱,比如你在电商平台可以买一部手机,也可以买两部手机

方式三:服务端token令牌方式 下单前先获取令牌-存储redis,下单时一并把token提交并检验和删除-lua脚本

分布式情况下,采用Lua脚本进行操作(保障原子性)

其中方式三 是大家采用的最多的,那有没更加优雅的方式呢?

假如系统中不止一个地方,需要用到这种防重复提交,每一次都要写这种lua脚本,代码耦合性太强,这种又不属于业务逻辑,所以不推荐耦合进service中,可读性较低。

本文采用自定义注解+AOP的方式,优雅的实现防止重复提交功能。

1、注解
/*** 表单防止重复提交自定义注解*/
@Documented
@Target(ElementType.METHOD) //可以用在方法上
@Retention(RetentionPolicy.RUNTIME) //保留到虚拟机上,可通过反射获取
public @interface RepeatSubmit {/*** 加锁过期时间,默认是5秒* @return*/int lockTime() default 5;}
注解解析:
@Documented 将此注解包含在 javadoc 中

@Inherited 是否允许子类继承父类中的注解
@interface 用来声明一个注解,可以通过default来声明参数的默认值
自定义注解时,自动继承了java.lang.annotation.Annotation接口,可以通过反射可以获取自定义注解

@Retention 表示在什么级别保存该注解信息
  • RetentionPolicy.SOURCE 保留到源码上
  • RetentionPolicy.CLASS 保留到字节码上
  • RetentionPolicy.RUNTIME 保留到虚拟机运行时(最多,可通过反射获取)
@Target 表示该注解用于什么地方

ElementType.CONSTRUCTOR 用在构造器
ElementType.FIELD 用于描述域-属性上
ElementType.METHOD 用在方法上
ElementType.TYPE 用在类或接口上
ElementType.PACKAGE 用于描述包

2、aop
/*** 表单防止重复提交切面*/
@Aspect
@Component
@Slf4j
public class RepeatSubmitAspect {private Lock lock = new ReentrantLock();@Resourceprivate RedisCache redisCache;/*** 定义 @Pointcut注解表达式, 通过特定的规则来筛选连接点, 就是Pointcut,选中那几个你想要的方法* 在程序中主要体现为书写切入点表达式(通过通配、正则表达式)过滤出特定的一组 JointPoint连接点* 方式一:@annotation:当执行的方法上拥有指定的注解时生效*/@Pointcut("@annotation(repeatSubmit)")public void pointCutNoRepeatSubmit(RepeatSubmit repeatSubmit) {}/*** 环绕通知, 围绕着方法执行* @param joinPoint* @param repeatSubmit* @Around 可以用来在调用一个具体方法前和调用后来完成一些具体的任务。* 用@Pointcut和@Around联合注解也可以*/@Around("pointCutNoRepeatSubmit(repeatSubmit)")public Object around(ProceedingJoinPoint joinPoint, RepeatSubmit repeatSubmit) throws Throwable {// 获取用户的token验证,这里项目用的是 header 里的  Authorization 参数HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();String requestToken = request.getHeader("Authorization");log.info("请求的token->{}", requestToken);boolean res = true;//从redis中获取tokenObject token = redisCache.getCacheObject("submit:token"+requestToken);if(token == null){//设置token并且设置有效期redisCache.setCacheObject("submit:token"+requestToken,requestToken,repeatSubmit.lockTime(), TimeUnit.SECONDS);res = false;}//用于记录成功或者失败log.info("环绕通知中");log.info("默认加锁时间->{}秒", repeatSubmit.lockTime());Object obj  = "";try {if (lock.tryLock(repeatSubmit.lockTime(), TimeUnit.SECONDS)) { //设置尝试获取锁得时间//防重提交if (res) {log.error("请求重复提交");log.info("环绕通知中");throw new ServiceException("请勿重复提交");}log.info("环绕通知执行前");obj = joinPoint.proceed();log.info("环绕通知执行后");}} catch (InterruptedException e) {throw new RuntimeException(e);} finally {lock.unlock(); //释放锁}return obj;}
}
3、使用
    /*** 同步菜谱* @param data* @return*/@RepeatSubmit@PostMapping("/addRecipe")public AjaxResult addRecipe(@RequestBody String data){recipeService.addRecipe(data);return AjaxResult.success();}

相关文章:

SpringBoot表单防止重复提交

哪些因素会引起重复提交? 开发的项目中可能会出现下面这些情况: 前端下单按钮重复点击导致订单创建多次 网速等原因造成页面卡顿,用户重复刷新提交请求 黑客或恶意用户使用postman等http工具重复恶意提交表单 重复提交会带来哪些问题&…...

java面向对象.day17(什么是面向对象)

先认识:面向过程思想,面向对象思想 面向过程思想(具体) 步骤清晰简单,第一步做什么,第二步做什么.... 面对过程适合处理一些较为简单的问题 面向对象思想(抽象) 物以类聚&#x…...

mysql处理并发简单示例

处理并发的基本思路是使用锁来控制对共享资源的访问。在MySQL中,可以使用事务和行级锁来处理并发。 具体处理方式如下: 创建一个用于存储并发任务的MySQL表,该表包含一个自增的ID字段和任务名称字段。设置一个最大并发数量,用来…...

顺序表——功能实现

✨✨欢迎👍👍点赞☕️☕️收藏✍✍评论 个人主页:秋邱博客 所属栏目:C语言 (感谢您的光临,您的光临蓬荜生辉) 目录 1.0 前言 2.0 线性表 2.1 顺序表 2.2 顺序表的分类 2.3 顺序表功能的实现…...

达梦导出工具dexp

基础环境 操作系统:Red Hat Enterprise Linux Server release 7.9 (Maipo) 数据库版本:DM Database Server 64 V8 架构:单实例dexp 逻辑导出 dexp 工具可以对本地或者远程数据库进行数据库级、用户级、模式级和表级的逻辑备份。备份的内容非…...

Ubuntu 22.04安装新硬盘并启动时自动挂载

方法一 要在Ubuntu 22.04系统中安装一个新硬盘、对其进行格式化并实现启动时自动挂载,需要按以下步骤操作: 1. 安装硬盘 - 确保你的硬盘正确连接到计算机上(涉及硬件安装)。 2. 发现新硬盘 - 在系统启动后,打开终端…...

Mybatis中sqlSession.getMapper背后的原理

在通过MyBatis操作数据库之前我们一定先通过Session对象获取指定Mappper接口的代理对象。如下代码所示&#xff1a; public class UserMapper{Select(value"SELECT * FROM user")public List<User> findAll(); }public static void main(String [] args){Conf…...

[环境配置]conda 64位安装32位python

进入32模式 set CONDA_FORCE_32BIT1创建环境 conda create --name yourEnv python3.8退出32模式 set CONDA_FORCE_32BIT0ok...

某虚假交友APP(信息窃取)逆向分析

应用初探 在群里水群的时候 群u发了一个交友APP 于是拿来分析一下 可以看到应用打开后又一个登录的界面 需要用户输入手机号与验证码进行登录 #在线云沙箱分析 将APK放入某安信云沙箱中分析 提示应用请求了过多的敏感权限 逆向分析 直接拖入Jadx分析 好在程序没有加固 也没…...

基于FPGA的按键消抖

按键工作原理 当KEY1按下时&#xff0c;整条电路就会导通&#xff0c;这个时候KEY1就是低电平&#xff1b; 当KEY1松开时&#xff0c;整条电路就会断开&#xff0c;这个时候KEY1就是高定平&#xff1b; 我们可以通过判断KEY1的高低电平来判断按键是否被按下。 为什么按键消…...

1.网络编程-网络协议

目录 网络编程是什么 网络编程三要素 OSI七层网络模型 TCP/IP五层模型 SSL/TLS 是哪层协议 网络编程是什么 网络编程是计算机科学中的一个重要领域&#xff0c;它涉及到编写能够在网络环境中进行通信的程序。网络编程的核心目标是使不同的设备能够通过网络交换信息&#…...

代码+视频,手动绘制logistic回归预测模型校准曲线(Calibration curve)(2)

校准曲线图表示的是预测值和实际值的差距&#xff0c;作为预测模型的重要部分&#xff0c;目前很多函数能绘制校准曲线。 一般分为两种&#xff0c;一种是通过Hosmer-Lemeshow检验&#xff0c;把P值分为10等分&#xff0c;求出每等分的预测值和实际值的差距 另外一种是calibrat…...

金融数据_Scikit-Learn决策树(DecisionTreeClassifier)实例

金融数据_Scikit-Learn决策树(DecisionTreeClassifier)实例 逻辑回归: 逻辑回归常被用于二分类问题, 比如涨跌预测。你可以将涨跌标记为类别, 然后使用逻辑回归进行训练。 决策树和随机森林: 决策树和随机森林是用于分类问题的强大模型。它们能够处理非线性关系, 并且对于特征…...

bash的login shell与non-login shell,以及各自的初始化过程

识别login shell与non-login shell login shell 可能是以-开头的 [almalinuxVM-AlmaLinux8-tmpl-wanlinwang ~]$ echo $0 -bash # "-" is the first character. Therefore, this is a login shell.或者以--login启动的bash [almalinuxVM-AlmaLinux8-tmpl-wanlinw…...

为什么苹果 Mac 电脑需要使用清理软件?

尽管 Apple Mac 电脑因其卓越的性能、简洁高效的 macOS 操作系统及独特的美学设计备受全球用户青睐&#xff0c;但任何电子设备在长期使用后都难以避免面临系统资源日渐累积的问题。其中一个重要维护需求在于&#xff0c;随着使用时间的增长&#xff0c;Mac电脑可能会由于系统垃…...

33. UE5 RPG使用增强输入激活GameplayAbility(三)

在前面的文章&#xff0c;我们实现了使用GameplayTag和InputAction的对应绑定的数据&#xff0c;并且添加到了增强输入映射的上下文中&#xff0c;实现了通过按键打印对应的GameplayTag&#xff0c;这只是我们基础需要制作的。目的主要是为了实现在GameplayAblity上面设置对应的…...

speech to text 库FastASR交叉编译arm target的配置

FastASR是一个比较方便的SPEECH TO TEXT的AI库。开源。下面介绍下其在交叉编译到ARM target时候的交叉编译的cmake配置&#xff1a; cmake_minimum_required(VERSION 3.10)project(FastASR)SET(CMAKE_C_COMPILER "/home/xxx/buildroot/output/platform_name/host/bin/aar…...

WPS快速将插入Excle数据插入Word

前置条件&#xff1a; 一张有标题、数据的excle表格word中的表格与excle表格标题对应或包含电脑已经安装WPS软件 第一步、根据word模板设计excle模板&#xff0c;标头对应 第二步、word上面选【引用】--【邮件】&#xff0c;选打开数据源&#xff0c;找到excle文件&#xff0c;…...

Springboot 集成Rabbitmq之延时队列

1.首先确保已经引入了Spring AMQP和RabbitMQ的相关依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId> </dependency> 2. 创建一个普通队列并设置TTL&#x…...

【云开发笔记NO.22】运用云原生产品打造技术中台

一、云原生产品与技术中台的结合点 云原生产品以其容器化、微服务化、自动化等特性&#xff0c;为技术中台的建设提供了强大的技术支持。容器化技术使得应用可以更容易地进行部署和管理&#xff0c;提高了应用的可移植性和弹性。微服务架构则让应用更加模块化&#xff0c;便于…...

C++进阶(五) 哈希

1. unordered系列关联式容器 1.1 unordered_map 1.2 unordered_map的接口说明 2. 底层结构 2.1 哈希概念 2.2 哈希冲突 2.3 哈希函数 2.4 哈希冲突解决 2.4.1 闭散列 2.4.2 开散列 3. 模拟实现 3.1 unordered_set 3.2 unordered_map 4.哈希的应用 4.1 位图 4.1.…...

【算法基础】基于异或的排序、基于异或的经典面试题

文章目录 1. 传统交换2. 异或与异或的规律3. 基于异或的排序4. 需要注意的地方5. 经典面试题15.1 题目5.2 思路5.3 实现 6. 经典面试题26.1 题目6.2 思路6.3 实现 1. 传统交换 传统交换方法如下&#xff1a; def swap(i, j):tmp ii jj tmp通过开辟一个额外的变量空间&…...

HTML2:列表和表格

列表 有序列表 ordered list ol 无序列表 unordered list ul 定义列表 definition list dl 1,有序列表 每条列表前自带一个序号 2,无序列表 每条列表前自带一个小圆点 3,定义列表 注意:dl中放的不是li列表而是dt列表和dd表项 dt代表术语标题 dd代表术语内容 一个…...

用于无人机小型化设计的高精度温补晶振

用于无人机小型化设计的高精度温补晶振:TG2016SMN和TG2520SMN。无人机的发展可以说是非常的迅速&#xff0c;在安防&#xff0c;农业&#xff0c;交通&#xff0c;电力&#xff0c;直播等领域经常能看到无人机大显身手。无人机的应用场最是非常的广泛&#xff0c;功能更强&…...

轨迹规划 | 图解最优控制LQR算法(附ROS C++/Python/Matlab仿真)

目录 0 专栏介绍1 最优控制理论2 线性二次型问题3 LQR的价值迭代推导4 基于差速模型的LQR控制5 仿真实现5.1 ROS C实现5.2 Python实现5.3 Matlab实现 0 专栏介绍 &#x1f525;附C/Python/Matlab全套代码&#x1f525;课程设计、毕业设计、创新竞赛必备&#xff01;详细介绍全…...

工业视觉检测

目录 我对工业视觉检测的了解 一、关键组成部分 二、应用场景 三、技术挑战 我对工业视觉检测的了解 工业视觉检测是利用机器视觉技术对产品质量进行自动化检查的过程&#xff0c;它在制造业中扮演着至关重要的角色&#xff0c;用于确保产品质量、提高生产效率、减少人工成…...

wheeltec轮趣ROS教育机器人的网络连接

一、术语解析 宿主机&#xff1a;宿主机是指物理主机&#xff0c;比如用于开发测试的笔记本电脑和台式机电脑。 虚拟机&#xff1a;虚拟机是指安装在宿主机的VMware&#xff0c;推荐在宿主机上安装虚拟机&#xff0c;官方提供虚拟机的镜像以及配套的开发环境。 ROS主机&…...

【Linux ARM 裸机】开发环境搭建

1、Ubuntu 和 Windows 文件互传 使用过程中&#xff0c;要频繁进行 Ubuntu 和 Windows 的文件互传&#xff0c;需要使用 FTP 服务&#xff1b; 1.1、开启 Ubuntu 下的 FTP 服务 //安装 FTP 服务 sudo apt-get install vsftpd //修改配置文件 sudo vi /etc/vsftpd.conf//重启…...

怎么保证缓存与数据库的最终一致性?

目录 零.读数据的标准操作 一.Cache aside Patten--旁路模式 二.Read/Write Through Pattern--读写穿透 三.Write Back Pattern--写回 四.运用canal监听mysql的binlog实现缓存同步 零.读数据的标准操作 这里想说的是不管哪种模式读操作都是一样的&#xff0c;这是一种统一…...

免费SSL通配符证书/SSL泛域名证书获取教程

我们先基本了解什么是SSL证书以及其作用。SSL证书是一种数字证书&#xff0c;它通过为网站提供身份验证和数据加密服务&#xff0c;从而保护网站的用户信息安全。当我们在浏览器的地址栏看到“https”和绿色锁标志时&#xff0c;就表示该网站使用了SSL证书。 那么什么又是通配…...

深圳政府网官网首页/seo标题优化步骤

电脑使用的时间越久&#xff0c;系统运行就会变得越来越卡&#xff0c;这是Windows和Mac系统都会出现的现象。为了提高系统运行速度&#xff0c;我们有必要清理一下电脑缓存。那么苹果电脑怎么清理垃圾和缓存文件&#xff1f;本指南将详细讲解清理Mac缓存的技巧&#xff0c;还补…...

网站建设 天秀网络/seo技术交流

最近要做后台主动推送&#xff1a;&#xff08;iris框架&#xff0c;封装的有wesocket&#xff0c;刚开始以为直接拿过来用&#xff0c;结果不是现在贴一下代码&#xff0c;写一下遇到的坑&#xff09; func main() { app : iris.New() app.Adapt(iris.DevLogger()) a…...

工程公司账务处理分录/在线排名优化

require() 和 include() 几乎完全一样&#xff0c;除了处理失败的方式不同之外。include() 产生一个Warning而 require() 则导致一个 Fatal Error。换句话说&#xff0c;如果想在丢失文件时停止处理页面&#xff0c;那就别犹豫了&#xff0c;用 require() 吧。include() 就不是…...

张雪峰对市场营销专业的建议/seo上海网站推广

Rust 集合与字符串 集合&#xff08;Collection&#xff09;是数据结构中最普遍的数据存放形式&#xff0c;Rust 标准库中提供了丰富的集合类型帮助开发者处理数据结构的操作。 向量 向量&#xff08;Vector&#xff09;是一个存放多值的单数据结构&#xff0c;该结构将相同…...

隐藏wordpress目录/5188关键词挖掘工具

学习 Bootstrap 5 之 表格表格 (Tables)1. 创建表格(1). 使用原生的表格标签(2). 使用Bootstrap 5 的提供的表格标签类(3). 原生与Bootstrap创建出来的表格的对比2. 表格颜色样式(1). 表格颜色样式的效果(2). 表格颜色样式的使用1). 用于 <table> 标签2). 用于 <thead…...

个人做网站能备案吗/网站推广系统方案

好的热部署让开发调试事半功倍&#xff0c;这样的“神技能”怎么能错过呢&#xff0c; 使用过IDEA的童鞋赶紧进来撸一把吧。学习目标快速学会在项目中使用热部署插件运行项目&#xff0c;提高开发效率。具体步骤一、开启IDEA的自动编译&#xff08;静态&#xff09;具体步骤&am…...