Spring Boot REST服务相同请求最多处理8次,改PathVariable名后恢复是什么原因
这个问题的核心是Java编译时参数名保留缺失 + Spring 参数名解析缓存限制共同导致的,具体逻辑如下:
- JDK 8及以上版本默认不会在编译后的字节码中保留方法参数名,只有开启
-parameters编译参数,或者编译时保留调试信息,Spring才能通过字节码解析拿到你定义的productId、customerId这类参数名。 - Spring 用于解析方法参数名的
CachingParameterNameDiscoverer默认使用容量为8的LRU缓存,前8次调用时,参数名可以通过解析局部变量表调试信息正常获取,缓存满了触发驱逐后,后续解析会 fallback 到默认的arg0、arg1这类索引式参数名。 - 当参数名变成
arg0、arg1后,两个逻辑会出问题:- 你没有给
@PathVariable指定显式的name属性,Spring MVC无法把路径中的productId、customerId变量和方法参数绑定,会出现参数赋值失败 @PreAuthorize注解中的SpEL表达式引用了#customerId,此时找不到对应名字的方法参数,表达式执行抛出异常,该异常被Spring Security的过滤器链拦截后没有正常返回响应,导致请求一直处于加载状态
- 你没有给
- 你修改后的代码给
@PathVariable指定了显式的prodId、custId作为匹配名,Spring不需要依赖方法参数名就可以完成路径变量绑定,同时SpEL表达式解析的时候也能正确匹配到你方法定义的参数名,所以不会再出现异常。
修复方案
- 最优方案:在编译插件中开启
-parameters参数,确保字节码中保留方法参数名,Maven项目的compiler插件配置示例如下:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <compilerArgs> <arg>-parameters</arg> </compilerArgs> </configuration> </plugin>
- 兜底方案:所有
@PathVariable、@RequestParam这类参数注解都显式指定name属性,不要依赖自动匹配参数名。
内容的提问来源于stack exchange,提问作者Yogesh Ukale
相关产品推荐
相关产品推荐

