文章目录
- 1. 环境准备
- 2. 引入依赖
- 3. 配置Redis
- 4. 创建防重复提交注解
- 5. 实现AOP切面
- 6. 创建示例Controller
- 7. 测试
- 8. 进一步优化
- 8.1 自定义异常处理
- 8.2 提升Redis的健壮性
- 9. 总结
🎉欢迎来到Java学习路线专栏~探索Java中的静态变量与实例变量
- ☆* o(≧▽≦)o *☆嗨~我是IT·陈寒🍹
- ✨博客主页:IT·陈寒的博客
- 🎈该系列文章专栏:Java学习路线
- 📜其他专栏:Java学习路线 Java面试技巧 Java实战项目 AIGC人工智能 数据结构学习
- 🍹文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏
- 📜 欢迎大家关注! ❤️
在现代Web应用中,防止重复提交是一个常见的需求。重复提交可能会导致数据一致性问题,例如重复的订单生成、数据多次插入等。本文将介绍如何使用Spring Boot、AOP、注解和Redis来实现防重复提交(防抖)功能。
1. 环境准备
在开始之前,我们需要准备以下开发环境:
- JDK 1.8+
- Maven
- Spring Boot
- Redis
首先,创建一个新的Spring Boot项目,可以使用Spring Initializr(https://start.spring.io/)快速生成项目结构。选择依赖项包括:Spring Web、Spring Data Redis、Lombok等。
2. 引入依赖
在pom.xml
中添加必要的依赖:
<dependencies>
<!-- Spring Boot Starter Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Starter Data Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- AOP -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
3. 配置Redis
在application.properties
文件中配置Redis连接信息:
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=yourpassword
4. 创建防重复提交注解
首先,创建一个自定义注解@NoRepeatSubmit
,用于标识需要防重复提交的方法:
package com.example.demo.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NoRepeatSubmit {
long expire() default 5; // 防重复提交时间间隔(秒)
}
5. 实现AOP切面
接下来,创建一个AOP切面类,用于拦截标注了@NoRepeatSubmit
注解的方法,并检查是否重复提交:
package com.example.demo.aspect;
import com.example.demo.annotation.NoRepeatSubmit;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;
@Aspect
@Component
@Slf4j
public class NoRepeatSubmitAspect {
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private HttpServletRequest request;
@Around("@annotation(noRepeatSubmit)")
public Object around(ProceedingJoinPoint pjp, NoRepeatSubmit noRepeatSubmit) throws Throwable {
String key = getKey();
long expireTime = noRepeatSubmit.expire();
Boolean hasKey = redisTemplate.hasKey(key);
if (Boolean.TRUE.equals(hasKey)) {
log.warn("重复提交请求, key: {}", key);
throw new RuntimeException("请勿重复提交");
}
redisTemplate.opsForValue().set(key, "1", expireTime, TimeUnit.SECONDS);
try {
return pjp.proceed();
} finally {
redisTemplate.delete(key);
}
}
private String getKey() {
String sessionId = request.getSession().getId();
String uri = request.getRequestURI();
return "noRepeatSubmit:" + sessionId + ":" + uri;
}
}
在这个切面类中,我们通过@Around
注解拦截所有标注了@NoRepeatSubmit
注解的方法。通过Redis,我们为每个请求生成一个唯一的key,并设置一个过期时间。如果在过期时间内再次提交相同的请求,就会被拦截。
6. 创建示例Controller
创建一个简单的Controller,用于测试防重复提交功能:
package com.example.demo.controller;
import com.example.demo.annotation.NoRepeatSubmit;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/test")
public class TestController {
@PostMapping("/submit")
@NoRepeatSubmit(expire = 10) // 设置防重复提交时间为10秒
public String submit() {
return "提交成功";
}
}
7. 测试
启动Spring Boot应用,使用Postman或其他工具向/test/submit
端点发送POST请求。第一次请求会成功,但在10秒内重复发送相同请求将会被拦截,并返回错误信息。
8. 进一步优化
8.1 自定义异常处理
为防重复提交功能添加自定义异常处理,使其返回更加友好的错误信息:
package com.example.demo.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
@ControllerAdvice
@RestController
public class GlobalExceptionHandler {
@ExceptionHandler(RuntimeException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public String handleRuntimeException(RuntimeException ex) {
return ex.getMessage();
}
}
8.2 提升Redis的健壮性
可以进一步优化Redis的配置,如添加连接池、超时设置等,以提升系统的健壮性和性能。
spring.redis.jedis.pool.max-active=20
spring.redis.jedis.pool.max-idle=10
spring.redis.jedis.pool.min-idle=5
spring.redis.timeout=2000
9. 总结
本文详细介绍了如何使用Spring Boot、AOP、注解和Redis实现防重复提交(防抖)功能。通过自定义注解和AOP切面,我们能够方便地为指定的接口添加防重复提交功能,避免数据重复插入等问题。
这种方法不仅实现简单,而且通过Redis的高性能存储和快速读取特性,能够有效地提升系统的性能和用户体验。在实际开发中,可以根据具体需求进行进一步的优化和扩展。希望本文能对你有所帮助!
🧸结尾 ❤️ 感谢您的支持和鼓励! 😊🙏
📜您可能感兴趣的内容:
- 【Java面试技巧】Java面试八股文 - 掌握面试必备知识(目录篇)
- 【Java学习路线】2023年完整版Java学习路线图
- 【AIGC人工智能】Chat GPT是什么,初学者怎么使用Chat GPT,需要注意些什么
- 【Java实战项目】SpringBoot+SSM实战:打造高效便捷的企业级Java外卖订购系统
- 【数据结构学习】从零起步:学习数据结构的完整路径