From c65acd6a28e15d95459e1f835856b384eabde2a8 Mon Sep 17 00:00:00 2001
From: 疯狂的狮子li <15040126243@163.com>
Date: 星期五, 30 七月 2021 19:10:54 +0800
Subject: [PATCH] update 重写 防重提交拦截器 支持全局与注解自定义 拦截时间配置配置 优化逻辑

---
 ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java     |   66 ++++++-------
 ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java |  162 ++++++++++++++------------------
 ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java                       |   52 +++++----
 ruoyi-admin/src/main/resources/application.yml                                                 |    5 +
 4 files changed, 136 insertions(+), 149 deletions(-)

diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index 4a52958..95ccf20 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -107,6 +107,11 @@
   # 浠ょ墝鏈夋晥鏈燂紙榛樿30鍒嗛挓锛�
   expireTime: 30
 
+# 閲嶅鎻愪氦
+repeat-submit:
+  # 鍏ㄥ眬闂撮殧鏃堕棿(姣)
+  intervalTime: 1000
+
 # MyBatisPlus閰嶇疆
 # https://baomidou.com/config/
 mybatis-plus:
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java
index 628eef1..c2bbee4 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java
@@ -1,23 +1,29 @@
-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;
-
-/**
- * 鑷畾涔夋敞瑙i槻姝㈣〃鍗曢噸澶嶆彁浜�
- * 
- * @author ruoyi
- *
- */
-@Inherited
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-public @interface RepeatSubmit
-{
-
-}
+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;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 鑷畾涔夋敞瑙i槻姝㈣〃鍗曢噸澶嶆彁浜�
+ *
+ * @author Lion Li
+ */
+@Inherited
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface RepeatSubmit {
+
+	/**
+	 * 榛樿浣跨敤鍏ㄥ眬閰嶇疆
+	 */
+	int intervalTime() default 0;
+
+	TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
+
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java
index bd0e99e..9af0a83 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java
@@ -6,7 +6,7 @@
 import com.ruoyi.common.utils.ServletUtils;
 import org.springframework.stereotype.Component;
 import org.springframework.web.method.HandlerMethod;
-import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+import org.springframework.web.servlet.HandlerInterceptor;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -15,42 +15,36 @@
 /**
  * 闃叉閲嶅鎻愪氦鎷︽埅鍣�
  *
- * @author ruoyi
+ * 绉婚櫎缁ф壙 HandlerInterceptorAdapter 杩囨湡绫�
+ * 鏀逛负瀹炵幇 HandlerInterceptor 鎺ュ彛(瀹樻柟鎺ㄨ崘鍐欐硶)
+ *
+ * @author Lion Li
  */
 @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, JsonUtils.toJsonString(ajaxResult));
-                    return false;
-                }
-            }
-            return true;
-        }
-        else
-        {
-            return super.preHandle(request, response, handler);
-        }
-    }
+public abstract class RepeatSubmitInterceptor implements HandlerInterceptor {
 
-    /**
-     * 楠岃瘉鏄惁閲嶅鎻愪氦鐢卞瓙绫诲疄鐜板叿浣撶殑闃查噸澶嶆彁浜ょ殑瑙勫垯
-     *
-     * @param request
-     * @return
-     * @throws Exception
-     */
-    public abstract boolean isRepeatSubmit(HttpServletRequest request);
+	@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(annotation, request)) {
+					AjaxResult ajaxResult = AjaxResult.error("涓嶅厑璁搁噸澶嶆彁浜わ紝璇风◢鍚庡啀璇�");
+					ServletUtils.renderString(response, JsonUtils.toJsonString(ajaxResult));
+					return false;
+				}
+			}
+			return true;
+		} else {
+			return HandlerInterceptor.super.preHandle(request, response, handler);
+		}
+	}
+
+	/**
+	 * 楠岃瘉鏄惁閲嶅鎻愪氦鐢卞瓙绫诲疄鐜板叿浣撶殑闃查噸澶嶆彁浜ょ殑瑙勫垯
+	 */
+	public abstract boolean isRepeatSubmit(RepeatSubmit annotation, HttpServletRequest request);
 }
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java
index bc09231..8fc4e79 100644
--- a/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java
@@ -1,15 +1,19 @@
 package com.ruoyi.framework.interceptor.impl;
 
+import cn.hutool.core.convert.Convert;
 import cn.hutool.core.io.IoUtil;
 import cn.hutool.core.lang.Validator;
+import com.ruoyi.common.annotation.RepeatSubmit;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.common.filter.RepeatedlyRequestWrapper;
 import com.ruoyi.common.utils.JsonUtils;
+import com.ruoyi.framework.config.properties.RepeatSubmitProperties;
+import com.ruoyi.framework.config.properties.TokenProperties;
 import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 
 import javax.servlet.http.HttpServletRequest;
@@ -20,45 +24,34 @@
 
 /**
  * 鍒ゆ柇璇锋眰url鍜屾暟鎹槸鍚﹀拰涓婁竴娆$浉鍚岋紝
- * 濡傛灉鍜屼笂娆$浉鍚岋紝鍒欐槸閲嶅鎻愪氦琛ㄥ崟銆� 鏈夋晥鏃堕棿涓�10绉掑唴銆�
+ * 濡傛灉鍜屼笂娆$浉鍚岋紝鍒欐槸閲嶅鎻愪氦琛ㄥ崟銆�
  *
- * @author ruoyi
+ * @author Lion Li
  */
 @Slf4j
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
 @Component
-public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
-{
-    public final String REPEAT_PARAMS = "repeatParams";
+public class SameUrlDataInterceptor extends RepeatSubmitInterceptor {
+	public final String REPEAT_PARAMS = "repeatParams";
 
-    public final String REPEAT_TIME = "repeatTime";
+	public final String REPEAT_TIME = "repeatTime";
 
-    // 浠ょ墝鑷畾涔夋爣璇�
-    @Value("${token.header}")
-    private String header;
+	private final TokenProperties tokenProperties;
+	private final RepeatSubmitProperties repeatSubmitProperties;
+	private final RedisCache redisCache;
 
-    @Autowired
-    private RedisCache redisCache;
 
-    /**
-     * 闂撮殧鏃堕棿锛屽崟浣�:绉� 榛樿10绉�
-     *
-     * 涓ゆ鐩稿悓鍙傛暟鐨勮姹傦紝濡傛灉闂撮殧鏃堕棿澶т簬璇ュ弬鏁帮紝绯荤粺涓嶄細璁ゅ畾涓洪噸澶嶆彁浜ょ殑鏁版嵁
-     */
-    private int intervalTime = 10;
-
-    public void setIntervalTime(int intervalTime)
-    {
-        this.intervalTime = intervalTime;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public boolean isRepeatSubmit(HttpServletRequest request)
-    {
-        String nowParams = "";
-        if (request instanceof RepeatedlyRequestWrapper)
-        {
-            RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
+	@SuppressWarnings("unchecked")
+	@Override
+	public boolean isRepeatSubmit(RepeatSubmit repeatSubmit, HttpServletRequest request) {
+		// 濡傛灉娉ㄨВ涓嶄负0 鍒欎娇鐢ㄦ敞瑙f暟鍊�
+		long intervalTime = repeatSubmitProperties.getIntervalTime();
+		if (repeatSubmit.intervalTime() > 0) {
+			intervalTime = repeatSubmit.timeUnit().toMillis(repeatSubmit.intervalTime());
+		}
+		String nowParams = "";
+		if (request instanceof RepeatedlyRequestWrapper) {
+			RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
 			try {
 				nowParams = IoUtil.readUtf8(repeatedlyRequest.getInputStream());
 			} catch (IOException e) {
@@ -66,68 +59,57 @@
 			}
 		}
 
-        // body鍙傛暟涓虹┖锛岃幏鍙朠arameter鐨勬暟鎹�
-        if (Validator.isEmpty(nowParams))
-        {
-            nowParams = JsonUtils.toJsonString(request.getParameterMap());
-        }
-        Map<String, Object> nowDataMap = new HashMap<String, Object>();
-        nowDataMap.put(REPEAT_PARAMS, nowParams);
-        nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
+		// body鍙傛暟涓虹┖锛岃幏鍙朠arameter鐨勬暟鎹�
+		if (Validator.isEmpty(nowParams)) {
+			nowParams = JsonUtils.toJsonString(request.getParameterMap());
+		}
+		Map<String, Object> nowDataMap = new HashMap<String, Object>();
+		nowDataMap.put(REPEAT_PARAMS, nowParams);
+		nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
 
-        // 璇锋眰鍦板潃锛堜綔涓哄瓨鏀綾ache鐨刱ey鍊硷級
-        String url = request.getRequestURI();
+		// 璇锋眰鍦板潃锛堜綔涓哄瓨鏀綾ache鐨刱ey鍊硷級
+		String url = request.getRequestURI();
 
-        // 鍞竴鍊硷紙娌℃湁娑堟伅澶村垯浣跨敤璇锋眰鍦板潃锛�
-        String submitKey = request.getHeader(header);
-        if (Validator.isEmpty(submitKey))
-        {
-            submitKey = url;
-        }
+		// 鍞竴鍊硷紙娌℃湁娑堟伅澶村垯浣跨敤璇锋眰鍦板潃锛�
+		String submitKey = request.getHeader(tokenProperties.getHeader());
+		if (Validator.isEmpty(submitKey)) {
+			submitKey = url;
+		}
 
-        // 鍞竴鏍囪瘑锛堟寚瀹歬ey + 娑堟伅澶达級
-        String cacheRepeatKey = Constants.REPEAT_SUBMIT_KEY + submitKey;
+		// 鍞竴鏍囪瘑锛堟寚瀹歬ey + 娑堟伅澶达級
+		String cacheRepeatKey = Constants.REPEAT_SUBMIT_KEY + submitKey;
 
-        Object sessionObj = redisCache.getCacheObject(cacheRepeatKey);
-        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> cacheMap = new HashMap<String, Object>();
-        cacheMap.put(url, nowDataMap);
-        redisCache.setCacheObject(cacheRepeatKey, cacheMap, intervalTime, TimeUnit.SECONDS);
-        return false;
-    }
+		Object sessionObj = redisCache.getCacheObject(cacheRepeatKey);
+		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, intervalTime)) {
+					return true;
+				}
+			}
+		}
+		Map<String, Object> cacheMap = new HashMap<String, Object>();
+		cacheMap.put(url, nowDataMap);
+		redisCache.setCacheObject(cacheRepeatKey, cacheMap, Convert.toInt(intervalTime), TimeUnit.MILLISECONDS);
+		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 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;
-    }
+	/**
+	 * 鍒ゆ柇涓ゆ闂撮殧鏃堕棿
+	 */
+	private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap, long intervalTime) {
+		long time1 = (Long) nowMap.get(REPEAT_TIME);
+		long time2 = (Long) preMap.get(REPEAT_TIME);
+		return (time1 - time2) < intervalTime;
+	}
 }

--
Gitblit v1.9.3