关于springboot:SpringBoot实现表单重复提交检测

27次阅读

共计 1940 个字符,预计需要花费 5 分钟才能阅读完成。

前言

在理论开发过程中,web 利用常常会呈现网络提早,接口解决工夫略长,用户习惯等起因造成的客户间断屡次点击提交按钮调用接口,导致数据库会呈现反复数据或这接口业务逻辑 bug 等问题

计划

利用 redis 锁实同一个用户同一个申请 2 秒内反复提交返回谬误路由

SubmitLock

标记须要拦挡的办法

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface SubmitLock {int expire() default 2;
}

RedisLockUtil

redis 锁校验及写入

@Component
public class RedisLockUtil {
    @Autowired
    private RedisUtil redisUtil;

    private int lockDBIndex = 1;

    public boolean lock(String key,String clientID,int lockExpire){if(redisUtil.isValid(key,lockDBIndex)){return false;}else{redisUtil.redisTemplateSet(key,clientID,lockDBIndex);
           redisUtil.setExpire(key,lockExpire, TimeUnit.SECONDS,lockDBIndex);
           return true;
       }
    }
}

RepeatSubmitAspect

对立拦挡切面

@Aspect
@Component
@Order(value = 100)
public class RepeatSubmitAspect {private static Logger logger = LoggerFactory.getLogger(RepeatSubmitAspect.class);
    @Autowired
    private RedisLockUtil redisLockUtil;

    /**
     * 切面点 指定注解
     */
    @Pointcut("@annotation(com.haopan.frame.common.annotation.SubmitLock)" +
            "|| @within(com.haopan.frame.common.annotation.SubmitLock)")
    public void repeatSubmitAspect() {}

    /**
     * 拦挡办法指定为 repeatSubmitAspect
     */
    @Around("repeatSubmitAspect()")
    public Object around(ProceedingJoinPoint point) throws Throwable {MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        SubmitLock submitLock = method.getAnnotation(SubmitLock.class);
        if (submitLock != null) {ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = requestAttributes.getRequest();
            String token = request.getHeader("token");
            if (!StringUtil.isEmpty(token)) {String path = request.getServletPath();
                String key = "submitLock|" + token + "|" + path;
                String clientId = CommonUtil.getNewGuid();
                if (redisLockUtil.lock(key, clientId, submitLock.expire())) {
                    // 获取锁胜利
                    return point.proceed();} else {System.out.println("tryLock fail, key = ["+key+"]");
                    return Result.errorResult().setMsg("反复申请,请稍后再试").setCode(-980);
                }
            } else {return point.proceed();
            }
        } else {return point.proceed();
        }
    }
}

正文完
 0