文章目录
- 一、准备工作
- 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异常。