Spring Boot开发——结合Redis实现接口防止重复提交

devtools/2025/1/11 10:16:29/

文章目录

  • 一、准备工作
    • 1、引入依赖
    • 2、配置Redis
  • 二、实现代码
    • 1、创建Redis服务类
    • 2、创建AOP切面类
    • 3、自定义注解
    • 4、处理异常
    • 5、使用注解
  • 三、测试验证
    • 1、启动Redis服务
    • 2、启动Spring Boot应用
    • 3、模拟重复提交

在Web开发中,防止用户重复提交表单是一个常见的需求。例如,在用户点击提交按钮后,由于网络延迟或其他原因,用户可能会多次点击,导致数据被重复提交。这不仅会造成数据冗余,还可能引发业务逻辑错误。本文将介绍如何使用Spring Boot结合Redis来实现一个高效的接口防重提交机制。

一、准备工作

1、引入依赖

在Spring Boot项目的pom.xml文件中添加Redis和Spring Data Redis的依赖。

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

2、配置Redis

在application.properties或application.yml文件中配置Redis的连接信息。

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

二、实现代码

1、创建Redis服务类

编写一个Redis服务类,用于操作Redis。这里我们使用Spring Data Redis提供的StringRedisTemplate。

@Service
public class RedisService {@Autowiredprivate StringRedisTemplate redisTemplate;private static final String REPEAT_SUBMIT_KEY_PREFIX = "repeat_submit:";/*** 设置防重提交标识* @param userId 用户ID* @param requestId 请求ID* @param expireTime 过期时间(秒)*/public void setRepeatSubmitKey(String userId, String requestId, long expireTime) {String key = REPEAT_SUBMIT_KEY_PREFIX + userId + ":" + requestId;redisTemplate.opsForValue().set(key, "1", expireTime, TimeUnit.SECONDS);}/*** 检查是否存在防重提交标识* @param userId 用户ID* @param requestId 请求ID* @return 存在返回true,不存在返回false*/public boolean hasRepeatSubmitKey(String userId, String requestId) {String key = REPEAT_SUBMIT_KEY_PREFIX + userId + ":" + requestId;return redisTemplate.hasKey(key);}
}

2、创建AOP切面类

编写一个AOP切面类,用于拦截需要防重提交的接口,并在执行前检查Redis中是否存在防重提交标识。

@Aspect
@Component
public class RepeatSubmitAspect {@Autowiredprivate RedisService redisService;@Before("@annotation(RepeatSubmit)")public void beforeMethod(JoinPoint joinPoint, RepeatSubmit repeatSubmit) throws Throwable {// 获取当前用户ID和请求ID(这里假设通过ThreadLocal获取,实际项目中可能通过Session、JWT等方式获取)String userId = "当前用户ID"; // 替换为实际获取用户ID的代码String requestId = UUID.randomUUID().toString(); // 使用UUID作为请求ID// 检查Redis中是否存在防重提交标识if (redisService.hasRepeatSubmitKey(userId, requestId)) {throw new RepeatSubmitException("请勿重复提交");}// 设置防重提交标识(设置过期时间,如60秒)redisService.setRepeatSubmitKey(userId, requestId, repeatSubmit.expireTime());}
}

3、自定义注解

创建一个自定义注解@RepeatSubmit,用于标记需要防重提交的接口。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RepeatSubmit {long expireTime() default 60; // 默认过期时间60秒
}

4、处理异常

创建一个自定义异常RepeatSubmitException,用于在检测到重复提交时抛出。

public class RepeatSubmitException extends RuntimeException {public RepeatSubmitException(String message) {super(message);}
}

5、使用注解

在需要防重提交的接口上使用@RepeatSubmit注解。

@RestController
@RequestMapping("/api")
public class DemoController {@PostMapping("/submit")@RepeatSubmit(expireTime = 60)public ResponseEntity<String> submit(@RequestBody DemoRequest request) {// 业务逻辑处理return ResponseEntity.ok("提交成功");}
}

三、测试验证

1、启动Redis服务

确保Redis服务已启动并运行。

2、启动Spring Boot应用

运行Spring Boot应用,访问需要防重提交的接口。

3、模拟重复提交

使用postman等测试工具在接口响应前多次点击提交按钮,观察是否抛出RepeatSubmitException异常。


http://www.ppmy.cn/devtools/149580.html

相关文章

openGauss系列 --启动和停止服务器

https://docs.opengauss.org/zh/docs/6.0.0/docs/DatabaseOMGuide/%E5%90%AF%E5%81%9CopenGauss.html 启动服务器 以操作系统用户omm登录数据库主节点。 使用以下命令启动openGauss。 gs_om -t start [ommlab6 ~]$ gs_om -t start Starting cluster. [SUCCESS] lab6 2024-12-…

数据结构(Java版)第七期:LinkedList与链表(二)

专栏&#xff1a;数据结构(Java版) 个人主页&#xff1a;手握风云 一、链表的实现&#xff08;补&#xff09; 接上一期&#xff0c;下面我们要实现删除所有值为key的元素&#xff0c;这时候有的老铁就会想用我们上一期中讲到的remove方法&#xff0c;循环使用remove方法&#…

【计算机网络】什么是网关(Gateway)?

网上冲浪多了&#xff0c;你可以听到过网关&#xff08;Gateway&#xff09;这个词&#xff0c;但是却不太清楚网关&#xff08;Gateway&#xff09;到底是干什么的、负责网络当中的什么任务&#xff0c;本篇文字将会为你介绍网关&#xff08;Gateway&#xff09;的作用&#x…

如何评价deepseek-V3 VS OpenAI o1 自然语言处理成Sql的能力

DeepSeek-V3 介绍 在目前大模型主流榜单中&#xff0c;DeepSeek-V3 在开源模型中位列榜首&#xff0c;与世界上最先进的闭源模型不分伯仲。 准备工作&#xff1a; 笔者只演示实例o1 VS DeepSeek-V3两个模型&#xff0c;大家可以自行验证结果或者实验更多场景&#xff0c;同时…

HTML 迷宫游戏

HTML 迷宫游戏 相关资源文件已经打包成压缩文件&#xff0c;可双击index.html直接运行程序&#xff0c;且文章末尾已附上相关源码&#xff0c;以供大家学习交流&#xff0c;博主主页还有更多Python相关程序案例&#xff0c;秉着开源精神的想法&#xff0c;望大家喜欢&#xff0…

鸿蒙开发(29)弹性布局 (Flex)

概述 弹性布局&#xff08;Flex&#xff09;提供更加有效的方式对容器中的子元素进行排列、对齐和分配剩余空间。常用于页面头部导航栏的均匀分布、页面框架的搭建、多行数据的排列等。 容器默认存在主轴与交叉轴&#xff0c;子元素默认沿主轴排列&#xff0c;子元素在主轴方…

碰一碰发视频的剪辑功能开发的细节源码搭建,支持OEM

在短视频盛行的今天&#xff0c;为碰一碰发视频增添剪辑功能&#xff0c;能极大提升用户创作的灵活性与趣味性。下面将详细阐述这一功能从技术选型到源码搭建的全过程。 一、技术选型 前端 框架&#xff1a;选择 React 作为前端框架&#xff0c;其基于组件化的开发模式&#x…

基于SpringBoot的洗浴管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…