方法参数 (Method Arguments)
下表描述了 Spring MVC 控制器方法支持的各种参数类型。
提示
对于具有 required 属性的注解(如 @RequestParam、@RequestHeader 等),支持使用 JDK 8 的 java.util.Optional 作为参数类型,这等同于设置 required=false。
| 参数类型 | 描述 |
|---|---|
WebRequest, NativeWebRequest | 允许访问请求参数、请求属性和会话属性,而无需直接使用 Servlet API。 |
ServletRequest, ServletResponse | 选择特定的请求或响应类型(如 HttpServletRequest 或 Spring 的 MultipartRequest)。 |
HttpSession | 强制会话存在(永远不会为 null)。注意:会话访问不是线程安全的。 |
Principal | 当前已认证的用户。 |
HttpMethod | 请求的 HTTP 方法。 |
java.util.Locale | 当前请求的区域设置(通过 LocaleResolver 确定)。 |
java.util.TimeZone + ZoneId | 与当前请求关联的时区。 |
InputStream, Reader | 访问 Servlet API 暴露的原始请求主体。 |
OutputStream, Writer | 访问 Servlet API 暴露的原始响应主体。 |
@PathVariable | 访问 URI 模板变量。 |
@MatrixVariable | 访问 URI 路径段中的键值对。 |
@RequestParam | 访问 Servlet 请求参数(包括文件上传)。简单类型可选。 |
@RequestHeader | 访问请求标头。 |
@CookieValue | 访问 Cookie。 |
@RequestBody | 访问 HTTP 请求主体。通过 HttpMessageConverter 转换。 |
HttpEntity<B> | 访问请求标头和主体。 |
@RequestPart | 访问 multipart/form-data 请求中的某个部分。 |
Model, ModelMap, Map | 访问 HTML 控制器使用的模型数据。 |
RedirectAttributes | 指定重定向时使用的属性或闪传属性(Flash Attributes)。 |
@ModelAttribute | 访问模型中的现有属性(若不存在则实例化),并应用数据绑定和校验。 |
Errors, BindingResult | 访问校验和数据绑定错误(必须紧跟在被验证的参数之后)。 |
SessionStatus | 用于标记表单处理完成,从而清理 @SessionAttributes 定义的会话属性。 |
UriComponentsBuilder | 用于准备相对于当前请求的主机、端口、方案等的 URL。 |
@SessionAttribute | 访问任何现有的会话属性。 |
@RequestAttribute | 访问请求范围的属性。 |
| 其他参数 | 如果不匹配上述任何项且是简单类型,解析为 @RequestParam;否则解析为 @ModelAttribute。 |
补充教学
1. 为什么推荐用 WebRequest 而不是 HttpServletRequest?
- 解耦:
WebRequest是 Spring 对原生 Servlet API 的抽象。 - 兼容性:如果你的代码未来可能迁移到非 Servlet 容器(虽然 MVC 绑定了 Servlet,但这种习惯有助于编写更通用的代码),
WebRequest更加中立。 - 工具支持:它提供了一些方便的方法来检查 ETag 或修改时间,逻辑更简洁。
2. @PathVariable 的隐式命名
如果你没有在注解里写名字,比如 handle(@PathVariable String id),Spring 依靠 -parameters 编译参数来获取变量名。 在现代 IDE(如 IntelliJ)和 Spring Boot 项目中,这通常是默认开启的。但如果你发现注入失败,请检查编译配置,或者老老实实写上 @PathVariable("id")。
3. “其他参数”的陷阱
这是一个非常有用的功能,但也容易引起混淆:
- 场景:你写了一个
public void save(User user)。 - 结果:Spring 发现
User不是简单类型,会自动把它当成@ModelAttribute处理。它会尝试从表单参数里获取数据并填入User对象。这通常被称为 “命令对象 (Command Object)”。 - 建议:为了代码可读性,建议显式加上
@ModelAttribute。