一、前言

在某些情况下,由于网速慢,用户操作有误(连续点击两下提交按钮),页面卡顿等原因,可能会出现表单数据重复提交造成数据库保存多条重复数据。

存在如上问题可以交给前端解决,判断多长时间内不能再次点击保存按钮,当然,如果存在聪明的用户能够绕过前端验证,后端更应该去进行拦截处理,下面小编将基于 SpringBoot 2.1.8.RELEASE 环境通过 AOP切面 + 自定义校验注解 + Redis缓存 来解决这一问题。

二、Spring Boot 校验表单重复提交操作

1、pom.xml 中引入所需依赖

<!-- ==================  校验表单重复提交所需依赖 ===================== --> <!-- AOP依赖 --> <dependency>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-aop</artifactId> </dependency> <!-- Redis --> <dependency>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>

2、application.yml 中引入Redis配置

spring:   redis:     # Redis数据库索引(默认为0)     database: 0     # Redis服务器地址     host: 127.0.0.1     # Redis服务器连接端口     port: 6379     timeout: 6000     # Redis服务器连接密码(默认为空)     #      password:     jedis:       pool:         max-active: 1000  # 连接池最大连接数(使用负值表示没有限制)         max-wait: -1      # 连接池最大阻塞等待时间(使用负值表示没有限制)         max-idle: 10      # 连接池中的最大空闲连接         min-idle: 5       # 连接池中的最小空闲连接

3、自定义注解 @NoRepeatSubmit

// 作用到方法上 @Target(ElementType.METHOD) // 运行时有效 @Retention(RetentionPolicy.RUNTIME) public @interface NoRepeatSubmit {     /**      * 默认时间3秒      */     int time() default 3 * 1000; }

4、AOP 拦截处理

注:这里redis存储的key值可由个人具体业务灵活发挥,这里只是示例
ex:单用户登录情况下可以组合 token + url请求路径 , 多个用户可以同时登录的话,可以再加上 ip地址

@Slf4j @Aspect @Component public class NoRepeatSubmitAop {      @Autowired     RedisUtil redisUtil;      /**      * <p> 【环绕通知】 用于拦截指定方法,判断用户表单保存操作是否属于重复提交 <p>      *      *      定义切入点表达式: execution(public * (…))      *      表达式解释: execution:主体    public:可省略   *:标识方法的任意返回值  任意包+类+方法(…) 任意参数      *      *      com.zhengqing.demo.modules.*.api : 标识AOP所切服务的包名,即需要进行横切的业务类      *      .*Controller : 标识类名,*即所有类      *      .*(..) : 标识任何方法名,括号表示参数,两个点表示任何参数类型      *      * @param pjp:切入点对象      * @param noRepeatSubmit:自定义的注解对象      * @return: java.lang.Object      */     @Around("execution(* com.zhengqing.demo.modules.*.api.*Controller.*(..)) && @annotation(noRepeatSubmit)")