Spring Boot 升级后报 Name for argument 错误
控制器升级后无法发现形参名时,显式指定请求名称,或在实际编译模块启用 -parameters。区分请求值缺省、编译设置与最终部署产物。
控制器已经写了 @PathVariable,请求仍停在 Name for argument of type [long] not specified,后面还提示 parameter name information not available via reflection。如果刚升级到使用 Spring Framework 6.1 的版本,检查注解里是否省略了名称,以及实际部署的 class 文件是否保留了参数名。
Spring Framework 6.1 移除了从局部变量表读取参数名的旧实现。Java 源码里的 long id 仍然存在,并不代表运行时反射能够取得 id。这篇针对 Java 编写的 Spring MVC 控制器;例如 Spring Boot 3.2 默认使用 Framework 6.1。项目若覆盖了依赖版本,应以实际解析出的 Framework 版本为准。
一个接口报错,先把绑定名称写清楚
下面的控制器是参数绑定示例,不访问数据库:
package example.web;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LookupController {
@GetMapping("/items/{id}")
public String lookup(
@PathVariable(name = "id") long itemId,
@RequestParam(name = "q") String keyword) {
return itemId + ":" + keyword;
}
}
路径里的 {id} 对应 @PathVariable(name = "id"),查询字符串里的 q 对应 @RequestParam(name = "q")。Java 形参可以叫 itemId、keyword,不必与请求名称相同。@PathVariable("id") 是同样的写法;@RequestParam 的 name 与 value 也是别名。
请求路径示例是 /items/42?q=book。把 @PathVariable 补上却仍不写名称,Spring 仍需发现形参名;仅更换形参变量名也不能补回 class 中缺失的信息。
required = false 处理的是请求值可以缺省,不负责提供绑定名称。这里的 q 默认必填:名称发现问题修好后,缺少 q 导致的 400 应按参数要求处理;id 不能转成数字也是另一类绑定错误。
大量代码依赖形参名,修正编译任务
Java 项目可用 -parameters 保存反射所需的参数名。Maven 中,在已有的 maven-compiler-plugin 配置里合并下面这一项,保留原来的版本、Java release 和其他编译选项:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<parameters>true</parameters>
</configuration>
</plugin>
这个配置项要求支持它的插件版本,parameters 自 maven-compiler-plugin 3.6.2 提供。不要为了添加一项配置,在另一处再声明一份冲突的插件。
Gradle 的 Groovy DSL 可在拥有控制器源码的模块里配置 Java 编译任务:
tasks.withType(JavaCompile).configureEach {
options.compilerArgs.add("-parameters")
}
多模块项目要确认配置覆盖真正编译该控制器的任务;根模块的设置不一定已经应用到子模块。Java 编译选项也不会自动配置 Groovy 或 Kotlin 编译器。IDE 使用自己的编译器时,还需核对它是否沿用了构建工具设置,不能只看 pom.xml 或 build.gradle。
-g 一类调试信息不能代替 -parameters。添加 JVM 启动参数也来不及,它需要在编译 Java 源码时生效。若 Gradle 在构建阶段已报Unsupported class file major version 65,先解决 Gradle 与运行 JDK 的兼容问题,再核对控制器产物。
检查部署产物,别只看编辑器里的设置
修改后按项目原有构建方式清理旧输出并重新打包。先保存构建配置和当前可回退的部署包,避免把旧 class 混入新包;CI 与本地应采用一致的编译参数。
对前面的 Maven 示例,可在本机用 JDK 自带的 javap 查看重新生成的 class。下面的包路径要换成实际控制器路径:
javap -p -v target/classes/example/web/LookupController.class
使用省略注解名称的写法时,应在目标方法下看到 MethodParameters 以及真实形参名;只看到 LocalVariableTable 不够。还要确认这些 class 来自最终部署包,而不是另一个模块、旧构建目录或 IDE 缓存。若构建产物已有参数名、运行时却没有,再检查加载的是哪份 class,以及是否有字节码代理改写。
显式名称能解决当前 MVC 绑定,但依赖参数名的其他机制仍可能需要编译元数据。不要把所有报错都靠补一个控制器注解掩盖。改动后从原来的入口请求接口,确认路径变量和查询参数都进入对应形参;同时保留缺少必填参数、错误类型和原有权限检查的失败行为。


