You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot单个请求触发拦截器多次执行致限流失效问题咨询

问题原因

从日志可以看出两次拦截的请求路径不一致:第一次为/original-article/similar-articles,第二次为多了一层前缀的/original-article/original-article/similar-articles,说明test环境下携带originalUrl参数时触发了Spring MVC内部转发,而你的拦截器匹配/**规则,会同时拦截原始请求和内部转发请求,导致逻辑执行两次。

触发内部转发的根本原因是dev和test环境的Spring MVC配置差异:

  • 通常dev环境会开启spring.mvc.throw-exception-if-no-handler-found=true、关闭静态资源映射,路径匹配失败会直接抛异常
  • test环境默认关闭上述配置,当请求参数originalUrl携带的完整URL包含//等特殊字符时,Spring MVC的路径匹配器会尝试做路径补全/转发,触发二次请求

另外你当前用HashMap存储访问频率属于线程不安全实现,高并发下会有逻辑错误,属于隐藏问题。

解决方案

1. 拦截器直接过滤内部转发请求

在FrequencyInterceptor的preHandle方法最前面增加转发判断,仅处理原始用户请求:

import javax.servlet.RequestDispatcher;

// 放在方法最开头
if (request.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI) != null) {
    // 内部转发请求直接放行,不做频率校验
    return true;
}

2. 对齐dev/test环境的Spring MVC配置

修改test环境的application配置,避免Spring自动做路径补全:

spring:
  mvc:
    throw-exception-if-no-handler-found: true
    pathmatch:
      use-registered-suffix-pattern: true
      matching-strategy: ANT_PATH_MATCHER
  web:
    resources:
      add-mappings: false

3. 修复频率控制的线程安全问题

将存储访问时间的HashMap替换为ConcurrentHashMap,避免多线程并发修改导致的计数异常:

// 替换原有HashMap定义
private final Map<String, Long> frequency = new ConcurrentHashMap<>();

内容的提问来源于stack exchange,提问作者aszswaz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 20:54:01