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;
+
+/**
+ * 自定义注解防止表单重复提交
+ *
+ * @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());
+
+ // 请求地址(作为存放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;
+ }
+}
--
Gitblit v1.9.2