From 3ff79b2c4075d9273a587226f247d952bc01beeb Mon Sep 17 00:00:00 2001 From: xuyuxiang Date: Tue, 25 Apr 2023 15:21:43 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E4=BF=AE=E5=A4=8D=E3=80=91=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=20#I6YA2U=20=E8=8A=82=E6=B5=81=E9=98=B2=E6=8A=96?= =?UTF-8?q?=E6=B3=A8=E8=A7=A3=E5=A4=B1=E6=95=88=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xiaonuo/core/config/GlobalConfigure.java | 46 +++++++++++++------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/snowy-web-app/src/main/java/vip/xiaonuo/core/config/GlobalConfigure.java b/snowy-web-app/src/main/java/vip/xiaonuo/core/config/GlobalConfigure.java index bc32e983..3d35bd7b 100644 --- a/snowy-web-app/src/main/java/vip/xiaonuo/core/config/GlobalConfigure.java +++ b/snowy-web-app/src/main/java/vip/xiaonuo/core/config/GlobalConfigure.java @@ -58,19 +58,20 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import vip.xiaonuo.auth.core.util.StpClientUtil; import vip.xiaonuo.common.annotation.CommonNoRepeat; import vip.xiaonuo.common.annotation.CommonWrapper; +import vip.xiaonuo.common.cache.CommonCacheOperator; import vip.xiaonuo.common.enums.CommonDeleteFlagEnum; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.common.listener.CommonDataChangeEventCenter; import vip.xiaonuo.common.listener.CommonDataChangeListener; import vip.xiaonuo.common.pojo.CommonResult; import vip.xiaonuo.common.pojo.CommonWrapperInterface; +import vip.xiaonuo.common.util.CommonTimeFormatUtil; import vip.xiaonuo.core.handler.GlobalExceptionUtil; import vip.xiaonuo.sys.core.enums.SysBuildInEnum; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; import javax.sql.DataSource; import java.lang.reflect.Array; import java.lang.reflect.Method; @@ -87,6 +88,11 @@ import java.util.*; @MapperScan(basePackages = {"vip.xiaonuo.**.mapper"}) public class GlobalConfigure implements WebMvcConfigurer { + private static final String COMMON_REPEAT_SUBMIT_CACHE_KEY = "common-repeatSubmit:"; + + @Resource + private CommonCacheOperator commonCacheOperator; + /** * 无需登录的接口地址集合 */ @@ -312,10 +318,11 @@ public class GlobalConfigure implements WebMvcConfigurer { Method method = handlerMethod.getMethod(); CommonNoRepeat annotation = method.getAnnotation(CommonNoRepeat.class); if (ObjectUtil.isNotEmpty(annotation)) { - if (this.isRepeatSubmit(request, annotation)) { + JSONObject repeatSubmitJsonObject = this.isRepeatSubmit(request, annotation); + if (repeatSubmitJsonObject.getBool("repeat")) { response.setCharacterEncoding(CharsetUtil.UTF_8); response.setContentType(ContentType.JSON.toString()); - response.getWriter().write(JSONUtil.toJsonStr(CommonResult.error("请求过于频繁,请稍后再试"))); + response.getWriter().write(JSONUtil.toJsonStr(CommonResult.error("请求过于频繁,请" + repeatSubmitJsonObject.getStr("time") + "后再试"))); return false; } } @@ -323,25 +330,34 @@ public class GlobalConfigure implements WebMvcConfigurer { return true; } - public boolean isRepeatSubmit(HttpServletRequest request, CommonNoRepeat annotation) { + public JSONObject isRepeatSubmit(HttpServletRequest request, CommonNoRepeat annotation) { JSONObject jsonObject = JSONUtil.createObj(); jsonObject.set("repeatParam", JSONUtil.toJsonStr(request.getParameterMap())); jsonObject.set("repeatTime", DateUtil.current()); String url = request.getRequestURI(); - HttpSession session = request.getSession(); - Object sessionObj = session.getAttribute("repeatData"); - if (ObjectUtil.isNotEmpty(sessionObj)) { - JSONObject sessionJsonObject = JSONUtil.parseObj(sessionObj); - if(sessionJsonObject.containsKey(url)) { - JSONObject existRepeatJsonObject = sessionJsonObject.getJSONObject(url); - if (jsonObject.getStr("repeatParam").equals(existRepeatJsonObject.getStr("repeatParam")) && - jsonObject.getLong("repeatTime") - existRepeatJsonObject.getLong("repeatTime") < annotation.interval()) { - return true; + // 获取该接口缓存的限流数据 + Object cacheObj = commonCacheOperator.get(COMMON_REPEAT_SUBMIT_CACHE_KEY + url); + if (ObjectUtil.isNotEmpty(cacheObj)) { + JSONObject cacheJsonObject = JSONUtil.parseObj(cacheObj); + if(cacheJsonObject.containsKey(url)) { + JSONObject existRepeatJsonObject = cacheJsonObject.getJSONObject(url); + // 如果与上次参数一致,且时间间隔小于要求的限流时长,则判定为重复提交 + if (jsonObject.getStr("repeatParam").equals(existRepeatJsonObject.getStr("repeatParam"))) { + long interval = jsonObject.getLong("repeatTime") - existRepeatJsonObject.getLong("repeatTime"); + if(interval < annotation.interval()) { + long secondsParam = (annotation.interval() - interval) / 1000; + if(secondsParam == 0) { + return JSONUtil.createObj().set("repeat", false); + } else { + return JSONUtil.createObj().set("repeat", true).set("time", CommonTimeFormatUtil.formatSeconds(secondsParam)); + } + } } } } - session.setAttribute("repeatData", JSONUtil.createObj().set(url, jsonObject)); - return false; + // 缓存最新的该接口的限流数据,为防止缓存的数据过多,缓存时效为1小时 + commonCacheOperator.put(COMMON_REPEAT_SUBMIT_CACHE_KEY + url, JSONUtil.createObj().set(url, jsonObject), 60 * 60); + return JSONUtil.createObj().set("repeat", false); } }).addPathPatterns("/**"); }