From e6cd9c430f229edb5284cf274f46ed13ecfb579b Mon Sep 17 00:00:00 2001
From: RuoYi <yzz_ivy@163.com>
Date: 星期三, 13 十一月 2019 15:20:05 +0800
Subject: [PATCH] 新增@RepeatSubmit注解,防止重复提交

---
 ruoyi/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java                  |   15 +++
 ruoyi/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java     |   55 +++++++++++++
 ruoyi/src/main/java/com/ruoyi/framework/interceptor/annotation/RepeatSubmit.java     |   23 +++++
 ruoyi/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java |   94 +++++++++++++++++++++++
 4 files changed, 187 insertions(+), 0 deletions(-)

diff --git a/ruoyi/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java b/ruoyi/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
index b836c21..8c19564 100644
--- a/ruoyi/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
+++ b/ruoyi/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
@@ -1,9 +1,12 @@
 package com.ruoyi.framework.config;
 
+import org.springframework.beans.factory.annotation.Autowired;
 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.WebMvcConfigurer;
 import com.ruoyi.common.constant.Constants;
+import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
 
 /**
  * 閫氱敤閰嶇疆
@@ -13,6 +16,9 @@
 @Configuration
 public class ResourcesConfig implements WebMvcConfigurer
 {
+    @Autowired
+    private RepeatSubmitInterceptor repeatSubmitInterceptor;
+
     @Override
     public void addResourceHandlers(ResourceHandlerRegistry registry)
     {
@@ -23,4 +29,13 @@
         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("/**");
+    }
 }
\ No newline at end of file
diff --git a/ruoyi/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java b/ruoyi/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java
new file mode 100644
index 0000000..088798d
--- /dev/null
+++ b/ruoyi/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java
@@ -0,0 +1,55 @@
+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.alibaba.fastjson.JSONObject;
+import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.framework.interceptor.annotation.RepeatSubmit;
+import com.ruoyi.framework.web.domain.AjaxResult;
+
+/**
+ * 闃叉閲嶅鎻愪氦鎷︽埅鍣�
+ * 
+ * @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, JSONObject.toJSONString(ajaxResult));
+                    return false;
+                }
+            }
+            return true;
+        }
+        else
+        {
+            return super.preHandle(request, response, handler);
+        }
+    }
+
+    /**
+     * 楠岃瘉鏄惁閲嶅鎻愪氦鐢卞瓙绫诲疄鐜板叿浣撶殑闃查噸澶嶆彁浜ょ殑瑙勫垯
+     * 
+     * @param httpServletRequest
+     * @return
+     * @throws Exception
+     */
+    public abstract boolean isRepeatSubmit(HttpServletRequest request);
+}
diff --git a/ruoyi/src/main/java/com/ruoyi/framework/interceptor/annotation/RepeatSubmit.java b/ruoyi/src/main/java/com/ruoyi/framework/interceptor/annotation/RepeatSubmit.java
new file mode 100644
index 0000000..0fbd73b
--- /dev/null
+++ b/ruoyi/src/main/java/com/ruoyi/framework/interceptor/annotation/RepeatSubmit.java
@@ -0,0 +1,23 @@
+package com.ruoyi.framework.interceptor.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;
+
+/**
+ * 鑷畾涔夋敞瑙i槻姝㈣〃鍗曢噸澶嶆彁浜�
+ * 
+ * @author ruoyi
+ *
+ */
+@Inherited
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface RepeatSubmit
+{
+
+}
\ No newline at end of file
diff --git a/ruoyi/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java b/ruoyi/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java
new file mode 100644
index 0000000..9d915c6
--- /dev/null
+++ b/ruoyi/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java
@@ -0,0 +1,94 @@
+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.alibaba.fastjson.JSONObject;
+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)
+    {
+        // 鏈鍙傛暟鍙婄郴缁熸椂闂�
+        String nowParams = JSONObject.toJSONString(request.getParameterMap());
+        Map<String, Object> nowDataMap = new HashMap<String, Object>();
+        nowDataMap.put(REPEAT_PARAMS, nowParams);
+        nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
+
+        // 璇锋眰鍦板潃锛堜綔涓哄瓨鏀緎ession鐨刱ey鍊硷級
+        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;
+    }
+}

--
Gitblit v1.9.3