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

相关推荐
闪电悠米9 小时前
黑马点评-Redis 消息队列-03_stream_consumer_group
开发语言·数据库·redis·分布式·缓存·junit·lua
Sam_Deep_Thinking11 小时前
Spring Boot 的启动原理是什么?
java·spring boot·后端
佛祖让我来巡山11 小时前
线上 Redis 突然“爆”了,怎么办?
redis·redis宕机·redis崩了·redis线上事故
屋外雨大,惊蛰出没12 小时前
深入浅出Spring Boot
java·spring boot·ioc·aop
三十..13 小时前
Redis 核心原理与高可用架构实践
运维·数据库·redis
协享科技13 小时前
Spring Boot 与 Go 双服务架构实践:从单体拆分到通信设计
java·人工智能·spring boot·后端·架构·golang·ai编程
小林敲代码778814 小时前
记录一下IDEA中很多变量变色的方案
java·开发语言·spring boot·idea
叶小鸡14 小时前
Java 篇-项目实战-AI 天机学堂(从 0 到 1)-day5
数据库·redis·缓存
IT策士14 小时前
Redis 从入门到精通:Python 操作 Redis
redis·python·bootstrap
Flittly14 小时前
【AgentScope Java新手村系列】(3)工具系统
java·spring boot·spring