• SpringBoot防止重复请求,重复表单提交超级简单的注解实现


    1.注解接口
    
    /**
     * @description 防止表单重复提交注解
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    @Documented
    public @interface DuplicateSubmitToken {
    
        //保存重复提交标记 默认为需要保存
        boolean save() default true;
    }
    2.定义异常类
    
    
    /**
     * 重复提交异常
     */
    public class DuplicateSubmitException extends RuntimeException {
        public DuplicateSubmitException(String msg) {
            super(msg);
        }
    
        public DuplicateSubmitException(String msg, Throwable cause) {
            super(msg, cause);
        }
    }
    
    
    3.拦截器
    
    /**
     * @description 防止表单重复提交拦截器
     */
    @Aspect
    @Component
    @Slf4j
    public class DuplicateSubmitAspect {
        public static final String DUPLICATE_TOKEN_KEY = "duplicate_token_key";
    
        @Pointcut("execution(public * cn.test.core.controller..*(..))")
    
        public void webLog() {
        }
    
        @Before("webLog() && @annotation(token)")
        public void before(final JoinPoint joinPoint, DuplicateSubmitToken token) {
            if (token != null) {
                Object[] args = joinPoint.getArgs();
                HttpServletRequest request = null;
                HttpServletResponse response = null;
                for (int i = 0; i < args.length; i++) {
                    if (args[i] instanceof HttpServletRequest) {
                        request = (HttpServletRequest) args[i];
                    }
                    if (args[i] instanceof HttpServletResponse) {
                        response = (HttpServletResponse) args[i];
                    }
                }
    
                boolean isSaveSession = token.save();
                if (isSaveSession) {
                    String key = getDuplicateTokenKey(joinPoint);
                    Object t = request.getSession().getAttribute(key);
                    if (null == t) {
                        String uuid = UUID.randomUUID().toString();
                        request.getSession().setAttribute(key.toString(), uuid);
                        log.info("token-key=" + key);
                        log.info("token-value=" + uuid.toString());
                    } else {
                        throw new DuplicateSubmitException(TextConstants.REQUEST_REPEAT);
                    }
                }
    
            }
        }
    
        /**
         * 获取重复提交key-->duplicate_token_key+','+请求方法名
         *
         * @param joinPoint
         * @return
         */
        public String getDuplicateTokenKey(JoinPoint joinPoint) {
            String methodName = joinPoint.getSignature().getName();
            StringBuilder key = new StringBuilder(DUPLICATE_TOKEN_KEY);
            key.append(",").append(methodName);
            return key.toString();
        }
    
        @AfterReturning("webLog() && @annotation(token)")
        public void doAfterReturning(JoinPoint joinPoint, DuplicateSubmitToken token) {
            // 处理完请求,返回内容
            log.info("出来方法:");
            if (token != null) {
                Object[] args = joinPoint.getArgs();
                HttpServletRequest request = null;
                for (int i = 0; i < args.length; i++) {
                    if (args[i] instanceof HttpServletRequest) {
                        request = (HttpServletRequest) args[i];
                    }
                }
                boolean isSaveSession = token.save();
                if (isSaveSession) {
                    String key = getDuplicateTokenKey(joinPoint);
                    Object t = request.getSession().getAttribute(key);
                    if (null != t) {
                        //方法执行完毕移除请求重复标记
                        request.getSession(false).removeAttribute(key);
                        log.info("方法执行完毕移除请求重复标记!");
                    }
                }
            }
        }
    
        /**
         * 异常
         *
         * @param joinPoint
         * @param e
         */
        @AfterThrowing(pointcut = "webLog()&& @annotation(token)", throwing = "e")
        public void doAfterThrowing(JoinPoint joinPoint, Throwable e, DuplicateSubmitToken token) {
            if (null != token
                    && e instanceof DuplicateSubmitException == false) {
                //处理处理重复提交本身之外的异常
                Object[] args = joinPoint.getArgs();
                HttpServletRequest request = null;
                for (int i = 0; i < args.length; i++) {
                    if (args[i] instanceof HttpServletRequest) {
                        request = (HttpServletRequest) args[i];
                    }
                }
                boolean isSaveSession = token.save();
                //获得方法名称
                if (isSaveSession) {
                    String key = getDuplicateTokenKey(joinPoint);
                    Object t = request.getSession().getAttribute(key);
                    if (null != t) {
                        //方法执行完毕移除请求重复标记
                        request.getSession(false).removeAttribute(key);
                        log.info("异常情况--移除请求重复标记!");
                    }
                }
            }
        }
    }
    4.控制器 使用方法:在你想要避免重复提交的控制器方法添加注解
    
    @DuplicateSubmitToken即可
    /**
     * @description
     */
    @RestController
    public class TestController {
        @RequestMapping(value = "/test", method = RequestMethod.GET)
        public Map<String, Object> firstResp(HttpServletRequest request) {
            Map<String, Object> map = new HashMap<>();
            request.getSession().setAttribute("request Url", request.getRequestURL());
            map.put("request Url", request.getRequestURL());
            return map;
        }
    
        @DuplicateSubmitToken
        @RequestMapping(value = "/test/d", method = RequestMethod.GET)
        public Map<String, Object> test(HttpServletRequest request) {
    
            Random r = new Random();
            int i = r.nextInt(3);
            if (i == 2) {
                throw new CustomException("有异常");
            }
    
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            Map<String, Object> map = new HashMap<>();
            request.getSession().setAttribute("request Url", request.getRequestURL());
            map.put("request Url", request.getRequestURL());
            return map;
        }
    }
    5.测试略过。。。
  • 相关阅读:
    vhdl 语法总结 4
    模拟地数字地连接以及0欧电阻作用
    vhdl 语法总结5
    电容参数X5R,X7R,Y5V等代表什么意思呢?(转)
    传智播客视频资料
    out.println 和<%=%>两种不同输出的形式
    易忘记的java名词
    JavaScript和JSP运用上的区别
    多线程 Time和TimeTask组合
    马路上的井盖为什么是圆的?(微软面试题)
  • 原文地址:https://www.cnblogs.com/bevis-byf/p/11491547.html
Copyright © 2020-2023  润新知