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异常。

相关推荐
Mr_sst7 小时前
文件上传并发控制:为什么选Redisson可过期信号量?(避坑指南)
网络·数据库·redis·分布式·安全架构
倚楼盼风雨7 小时前
Redis 为什么快
数据库·redis·缓存
xiaoliuliu123457 小时前
redis-windows-7.2.3安装步骤详解(附Redis配置与Windows服务注册)
数据库·windows·redis
一个心烑7 小时前
Layui结合springboot读取返回值,前端展示简单示例
前端·spring boot·layui
郝开7 小时前
Spring Cloud Gateway 3.5.14 使用手册
java·数据库·spring boot·gateway
y = xⁿ7 小时前
Redis八股学习日记:数据结构;跳表的底层;Reids的事务机制
数据结构·redis·学习
yuzhiboyouye7 小时前
java redis(缓存)
java·redis·缓存
Rust研习社8 小时前
Rust 操作 Redis 从入门到生产级应用
开发语言·redis·后端·rust
Wmenghu8 小时前
Ubuntu 安装 MySQL 8.0 + Redis 并开启远程访问
redis·mysql·ubuntu
Thanks_ks10 小时前
分布式系统中的并发控制与分布式锁机制深度剖析
redis·zookeeper·高并发·分布式锁·架构设计·并发控制·分布式系统