zoukankan      html  css  js  c++  java
  • SpringBoot实现表单重复提交检测

    前言

    在实际开发过程中,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();
            }
        }
    }
    
  • 相关阅读:
    友盟上报 IOS
    UTF8编码
    Hill加密算法
    Base64编码
    Logistic Regression 算法向量化实现及心得
    152. Maximum Product Subarray(中等, 神奇的 swap)
    216. Combination Sum III(medium, backtrack, 本类问题做的最快的一次)
    77. Combinations(medium, backtrack, 重要, 弄了1小时)
    47. Permutations II(medium, backtrack, 重要, 条件较难思考)
    3.5 find() 判断是否存在某元素
  • 原文地址:https://www.cnblogs.com/yanpeng19940119/p/15202095.html
Copyright © 2011-2022 走看看