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 316a370c13701d3a0050766b980b364e7181467a..c05e2c909edc7fbb78c881645d3da3d8925eb451 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 @@ -65,23 +65,37 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor // 唯一标识(指定key + url + 消息头) String cacheRepeatKey = CacheConstants.REPEAT_SUBMIT_KEY + url + submitKey; - Object sessionObj = redisCache.getCacheObject(cacheRepeatKey); - if (sessionObj != null) - { - Map sessionMap = (Map) sessionObj; - if (sessionMap.containsKey(url)) - { - Map preDataMap = (Map) sessionMap.get(url); - if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, annotation.interval())) - { - return true; + // 使用原子操作检查并设置,避免竞态条件 + String lockKey = cacheRepeatKey + "_lock"; + + // 先尝试获取分布式锁,防止并发问题 + Boolean lockResult = redisCache.redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 1, TimeUnit.SECONDS); + if (lockResult == null || !lockResult) { + // 获取锁失败,说明有并发请求,直接返回重复提交 + return true; + } + + try { + Object sessionObj = redisCache.getCacheObject(cacheRepeatKey); + + if (sessionObj != null) { + Map sessionMap = (Map) sessionObj; + if (sessionMap.containsKey(url)) { + Map preDataMap = (Map) sessionMap.get(url); + if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, annotation.interval())) { + return true; + } } } + + Map cacheMap = new HashMap(); + cacheMap.put(url, nowDataMap); + redisCache.setCacheObject(cacheRepeatKey, cacheMap, annotation.interval(), TimeUnit.MILLISECONDS); + return false; + } finally { + // 释放锁 + redisCache.deleteObject(lockKey); } - Map cacheMap = new HashMap(); - cacheMap.put(url, nowDataMap); - redisCache.setCacheObject(cacheRepeatKey, cacheMap, annotation.interval(), TimeUnit.MILLISECONDS); - return false; } /**