SpringBoot实现表单重复提交检测

前言 在实际开发过程中,web应用经常会出现网络延迟,接口处理时间略长,用户习惯等原因造成的客户连续多次点击提交按钮调用接口,导致数据库会出现重复数据或这接口业务逻辑bug等问题
方案 【SpringBoot实现表单重复提交检测】利用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 = https://www.it610.com/article/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(); } } }

    推荐阅读