美文网首页
简单分布式锁解决表单重复提交

简单分布式锁解决表单重复提交

作者: 川流不息attitude | 来源:发表于2022-07-06 21:27 被阅读0次

    前端按钮点击很快,有没有做置灰处理,反正后端不应该相信前端吧。

    比如一下 添加接口 ,快速点击 可能会出现 两条重复数据,没有做唯一索引的话。

    解决思路
    1. 定义一个小注解
    2. 定义一个切面
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface NotRepeatedSubmit {
        String msg() default "请勿重复提交";
    }
    
    @Aspect
    @Component
    public class NotRepeatedSubmitAspect {
    
        private static final String LOCK_REPEATED_SUBMIT = "lock_repeated_submit:";
        @Autowired
        private RedissonClient redissonClient;
    
        @Around("@annotation(notRepeatedSubmit)")
        public Object around(ProceedingJoinPoint pjp, NotRepeatedSubmit notRepeatedSubmit) throws Throwable {
            try {
                //获取当前执行类
                String className = pjp.getSignature().getDeclaringTypeName();
                //获取当前执行类中的执行方法
                String methodName = pjp.getSignature().getName();
                // 参数
                Map<String, Object> params = getRequestParams(pjp);
                String md5 = SecureUtil.md5(className + methodName + JSON.toJSONString(params));
                RLock lock = redissonClient.getLock(LOCK_REPEATED_SUBMIT+md5);
                boolean tryLock = lock.tryLock();
                if(tryLock){
                    try {
                        Object result = pjp.proceed();
                        return result;
                    } finally {
                        lock.unlock();
                    }
                }
                throw new BusinessException(notRepeatedSubmit.msg());
            } catch (Throwable e) {
                throw e;
            }
        }
    
    
        /**
         * 获取入参
         * @param proceedingJoinPoint
         *
         * @return
         * */
        private Map<String, Object> getRequestParams(ProceedingJoinPoint proceedingJoinPoint) {
            Map<String, Object> requestParams = new HashMap<>();
            //参数名
            String[] paramNames =
                    ((MethodSignature)proceedingJoinPoint.getSignature()).getParameterNames();
            //参数值
            Object[] paramValues = proceedingJoinPoint.getArgs();
    
            for (int i = 0; i < paramNames.length; i++) {
                Object value = paramValues[i];
                //如果是文件对象
                if (value instanceof MultipartFile) {
                    MultipartFile file = (MultipartFile) value;
                    //获取文件名
                    value = file.getOriginalFilename();
                }
    
                if(value instanceof HttpServletResponse){
                    continue;
                }
                if(value instanceof HttpServletRequest){
                    continue;
                }
                requestParams.put(paramNames[i], value);
            }
                 // 附加用户信息
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            String principal = "";
            if(null != authentication){
                principal = authentication.getName();
            }
            requestParams.put("username",principal);
            return requestParams;
        }
    }
    

    使用 就在方法上打个注解

    相关文章

      网友评论

          本文标题:简单分布式锁解决表单重复提交

          本文链接:https://www.haomeiwen.com/subject/jwaybrtx.html