• RepeatSubmitInterceptor extends HandlerInterceptorAdapter


    package com.ruoyi.framework.interceptor;
    
    import java.lang.reflect.Method;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.springframework.stereotype.Component;
    import org.springframework.web.method.HandlerMethod;
    import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
    import com.ruoyi.common.annotation.RepeatSubmit;
    import com.ruoyi.common.core.domain.AjaxResult;
    import com.ruoyi.common.json.JSON;
    import com.ruoyi.common.utils.ServletUtils;
    
    /**
     * 防止重复提交拦截器
     * 
     * @author ruoyi
     */
    @Component
    public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter
    {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
        {
            if (handler instanceof HandlerMethod)
            {
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                Method method = handlerMethod.getMethod();
                RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
                if (annotation != null)
                {
                    if (this.isRepeatSubmit(request))
                    {
                        AjaxResult ajaxResult = AjaxResult.error("不允许重复提交,请稍后再试");
                        ServletUtils.renderString(response, JSON.marshal(ajaxResult));
                        return false;
                    }
                }
                return true;
            }
            else
            {
                return super.preHandle(request, response, handler);
            }
        }
    
        /**
         * 验证是否重复提交由子类实现具体的防重复提交的规则
         * 
         * @param httpServletRequest
         * @return
         * @throws Exception
         */
        public abstract boolean isRepeatSubmit(HttpServletRequest request) throws Exception;
    }
    package com.ruoyi.framework.interceptor.impl;
    
    import java.util.HashMap;
    import java.util.Map;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    import org.springframework.stereotype.Component;
    import com.ruoyi.common.json.JSON;
    import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
    
    /**
     * 判断请求url和数据是否和上一次相同, 
     * 如果和上次相同,则是重复提交表单。 有效时间为10秒内。
     * 
     * @author ruoyi
     */
    @Component
    public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
    {
        public final String REPEAT_PARAMS = "repeatParams";
    
        public final String REPEAT_TIME = "repeatTime";
    
        public final String SESSION_REPEAT_KEY = "repeatData";
    
        /**
         * 间隔时间,单位:秒 默认10秒
         * 
         * 两次相同参数的请求,如果间隔时间大于该参数,系统不会认定为重复提交的数据
         */
        private int intervalTime = 10;
    
        public void setIntervalTime(int intervalTime)
        {
            this.intervalTime = intervalTime;
        }
    
        @SuppressWarnings("unchecked")
        @Override
        public boolean isRepeatSubmit(HttpServletRequest request) throws Exception
        {
            // 本次参数及系统时间
            String nowParams = JSON.marshal(request.getParameterMap());
            Map<String, Object> nowDataMap = new HashMap<String, Object>();
            nowDataMap.put(REPEAT_PARAMS, nowParams);
            nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
    
            // 请求地址(作为存放session的key值)
            String url = request.getRequestURI();
    
            HttpSession session = request.getSession();
            Object sessionObj = session.getAttribute(SESSION_REPEAT_KEY);
            if (sessionObj != null)
            {
                Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
                if (sessionMap.containsKey(url))
                {
                    Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url);
                    if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap))
                    {
                        return true;
                    }
                }
            }
            Map<String, Object> sessionMap = new HashMap<String, Object>();
            sessionMap.put(url, nowDataMap);
            session.setAttribute(SESSION_REPEAT_KEY, sessionMap);
            return false;
        }
    
        /**
         * 判断参数是否相同
         */
        private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap)
        {
            String nowParams = (String) nowMap.get(REPEAT_PARAMS);
            String preParams = (String) preMap.get(REPEAT_PARAMS);
            return nowParams.equals(preParams);
        }
    
        /**
         * 判断两次间隔时间
         */
        private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap)
        {
            long time1 = (Long) nowMap.get(REPEAT_TIME);
            long time2 = (Long) preMap.get(REPEAT_TIME);
            if ((time1 - time2) < (this.intervalTime * 1000))
            {
                return true;
            }
            return false;
        }
    }
    package com.ruoyi.common.annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * 自定义注解防止表单重复提交
     * 
     * @author ruoyi
     *
     */
    @Inherited
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface RepeatSubmit
    {
    
    }
    package com.ruoyi.common.core.domain;
    
    import java.util.HashMap;
    import com.ruoyi.common.utils.StringUtils;
    
    /**
     * 操作消息提醒
     * 
     * @author ruoyi
     */
    public class AjaxResult extends HashMap<String, Object>
    {
        private static final long serialVersionUID = 1L;
    
        /** 状态码 */
        public static final String CODE_TAG = "code";
    
        /** 返回内容 */
        public static final String MSG_TAG = "msg";
    
        /** 数据对象 */
        public static final String DATA_TAG = "data";
    
        /**
         * 状态类型
         */
        public enum Type
        {
            /** 成功 */
            SUCCESS(0),
            /** 警告 */
            WARN(301),
            /** 错误 */
            ERROR(500);
            private final int value;
    
            Type(int value)
            {
                this.value = value;
            }
    
            public int value()
            {
                return this.value;
            }
        }
    
        /**
         * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
         */
        public AjaxResult()
        {
        }
    
        /**
         * 初始化一个新创建的 AjaxResult 对象
         * 
         * @param type 状态类型
         * @param msg 返回内容
         */
        public AjaxResult(Type type, String msg)
        {
            super.put(CODE_TAG, type.value);
            super.put(MSG_TAG, msg);
        }
    
        /**
         * 初始化一个新创建的 AjaxResult 对象
         * 
         * @param type 状态类型
         * @param msg 返回内容
         * @param data 数据对象
         */
        public AjaxResult(Type type, String msg, Object data)
        {
            super.put(CODE_TAG, type.value);
            super.put(MSG_TAG, msg);
            if (StringUtils.isNotNull(data))
            {
                super.put(DATA_TAG, data);
            }
        }
    
        /**
         * 返回成功消息
         * 
         * @return 成功消息
         */
        public static AjaxResult success()
        {
            return AjaxResult.success("操作成功");
        }
    
        /**
         * 返回成功数据
         * 
         * @return 成功消息
         */
        public static AjaxResult success(Object data)
        {
            return AjaxResult.success("操作成功", data);
        }
    
        /**
         * 返回成功消息
         * 
         * @param msg 返回内容
         * @return 成功消息
         */
        public static AjaxResult success(String msg)
        {
            return AjaxResult.success(msg, null);
        }
    
        /**
         * 返回成功消息
         * 
         * @param msg 返回内容
         * @param data 数据对象
         * @return 成功消息
         */
        public static AjaxResult success(String msg, Object data)
        {
            return new AjaxResult(Type.SUCCESS, msg, data);
        }
    
        /**
         * 返回警告消息
         * 
         * @param msg 返回内容
         * @return 警告消息
         */
        public static AjaxResult warn(String msg)
        {
            return AjaxResult.warn(msg, null);
        }
    
        /**
         * 返回警告消息
         * 
         * @param msg 返回内容
         * @param data 数据对象
         * @return 警告消息
         */
        public static AjaxResult warn(String msg, Object data)
        {
            return new AjaxResult(Type.WARN, msg, data);
        }
    
        /**
         * 返回错误消息
         * 
         * @return
         */
        public static AjaxResult error()
        {
            return AjaxResult.error("操作失败");
        }
    
        /**
         * 返回错误消息
         * 
         * @param msg 返回内容
         * @return 警告消息
         */
        public static AjaxResult error(String msg)
        {
            return AjaxResult.error(msg, null);
        }
    
        /**
         * 返回错误消息
         * 
         * @param msg 返回内容
         * @param data 数据对象
         * @return 警告消息
         */
        public static AjaxResult error(String msg, Object data)
        {
            return new AjaxResult(Type.ERROR, msg, data);
        }
    }
    package com.ruoyi.framework.config;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    import com.ruoyi.common.config.Global;
    import com.ruoyi.common.constant.Constants;
    import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
    
    /**
     * 通用配置
     * 
     * @author ruoyi
     */
    @Configuration
    public class ResourcesConfig implements WebMvcConfigurer
    {
        /**
         * 首页地址
         */
        @Value("${shiro.user.indexUrl}")
        private String indexUrl;
    
        @Autowired
        private RepeatSubmitInterceptor repeatSubmitInterceptor;
    
        /**
         * 默认首页的设置,当输入域名是可以自动跳转到默认指定的网页
         */
        @Override
        public void addViewControllers(ViewControllerRegistry registry)
        {
            registry.addViewController("/").setViewName("forward:" + indexUrl);
        }
    
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry)
        {
            /** 本地文件上传路径 */
            registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**").addResourceLocations("file:" + Global.getProfile() + "/");
    
            /** swagger配置 */
            registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
            registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
        }
    
        /**
         * 自定义拦截规则
         */
        @Override
        public void addInterceptors(InterceptorRegistry registry)
        {
            registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
        }
    }
  • 相关阅读:
    JS运行机制之 Event Loop 的思考
    模块机制 之commonJs、node模块 、AMD、CMD
    git报错:'fatal:remote origin already exists'怎么处理?附上git常用操作以及说明。
    Uncaught RangeError: Maximum call stack size exceeded-栈溢出
    对循环内部反复声明变量的写法的一点想法?
    JS的forEach和map方法的区别
    函数的属性和方法之call、apply 及bind
    利用Apach ab对nodejs进行并发负载的压力测试
    怎么判断一个对象是不是数组类型?
    Python模块学习之fabric
  • 原文地址:https://www.cnblogs.com/tonggc1668/p/11876557.html
Copyright © 2020-2023  润新知