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

文章目录

  • 一、准备工作
    • 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的依赖。

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2、配置Redis

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

java 复制代码
spring.redis.host=localhost
spring.redis.port=6379

二、实现代码

1、创建Redis服务类

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

java 复制代码
@Service
public class RedisService {

    @Autowired
    private 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中是否存在防重提交标识。

java 复制代码
@Aspect
@Component
public class RepeatSubmitAspect {

    @Autowired
    private 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,用于标记需要防重提交的接口。

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

4、处理异常

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

java 复制代码
public class RepeatSubmitException extends RuntimeException {
    public RepeatSubmitException(String message) {
        super(message);
    }
}

5、使用注解

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

java 复制代码
@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异常。

相关推荐
猴哥源码1 小时前
基于Java+SpringBoot的健身房管理系统
java·spring boot
猴哥源码1 小时前
基于Java+SpringBoot的三国之家网站
java·spring boot
Spirit_NKlaus1 小时前
解决HttpServletRequest无法获取@RequestBody修饰的参数
java·spring boot·spring
不死的精灵2 小时前
【Java21】在spring boot中使用ScopedValue
java·spring boot·后端
都叫我大帅哥3 小时前
🌊 Redis Stream深度探险:从秒杀系统到面试通关
java·redis
都叫我大帅哥3 小时前
Redis持久化全解析:从健忘症患者到记忆大师的逆袭
java·redis
仰望星空@脚踏实地4 小时前
Spring Boot Web 服务单元测试设计指南
spring boot·后端·单元测试
野蛮人6号4 小时前
黑马点评系列问题之基础篇p7 06初识redis无法在虚拟机查到图形化界面存进去的键
redis·黑马点评
一勺菠萝丶6 小时前
Spring Boot + MyBatis/MyBatis Plus:XML中循环处理List参数的终极指南
xml·spring boot·mybatis
大春儿的试验田7 小时前
高并发收藏功能设计:Redis异步同步与定时补偿机制详解
java·数据库·redis·学习·缓存