@ModelAttribute 是 Spring MVC 中的一个核心注解,主要用于在控制器(@Controller 或 @RestController)中处理 HTTP 请求参数绑定到 Java 对象 ,以及 向视图(如 JSP、Thymeleaf)或响应体中添加模型数据。它有两种主要用法:
1. 方法级 @ModelAttribute(绑定请求参数到对象)
作用
- 在
@Controller或@RequestMapping方法执行前 自动调用,用于将请求参数(query params、form data、JSON等)绑定到一个 Java 对象(通常是 POJO)。 - 绑定后的对象会被自动添加到
Model中,供视图(如 JSP、Thymeleaf)或后续方法使用。
示例
场景 1:表单提交(application/x-www-form-urlencoded)
java
`@Controller
public class UserController {
// 方法级 @ModelAttribute:在 @PostMapping 方法执行前自动调用
@ModelAttribute("user") // 可选:指定 Model 中的 key(默认是类名首字母小写,如 "user")
public User prepareUser() {
return new User(); // 返回一个空对象,Spring 会自动填充请求参数
}
@PostMapping("/register")
public String register(@ModelAttribute("user") User user, BindingResult result) {
if (result.hasErrors()) {
return "error"; // 返回错误页面
}
return "success"; // 返回成功页面
}
}`
-
请求示例 (表单提交):
html`<form action="/register" method="post"> <input type="text" name="username" placeholder="用户名"> <input type="password" name="password" placeholder="密码"> <button type="submit">注册</button> </form>` -
Spring 会自动 :
- 调用
prepareUser()创建User对象。 - 将表单中的
username和password绑定到User对象的对应字段。 - 将
User对象存入Model(key 默认为"user")。 - 在
register()方法中可以直接使用绑定后的User对象。
- 调用
场景 2:REST API(application/json)
如果请求是 JSON 格式(@RestController 或 @RequestBody 不适用时),可以手动绑定:
java
`@PostMapping("/api/user")
public ResponseEntity<User> createUser(@ModelAttribute User user) {
return ResponseEntity.ok(user); // 返回绑定后的 User 对象
}`
-
请求示例 (
POST /api/user,Content-Type: application/x-www-form-urlencoded):`username=John&password=123456` -
或 (
POST /api/user,Content-Type: application/json,需额外配置):json`{ "username": "John", "password": "123456" }`注意 :
@ModelAttribute默认不支持JSON,通常用@RequestBody处理JSON请求。
2. 参数级 @ModelAttribute(直接绑定请求参数到方法参数)
作用
- 直接在方法参数上使用
@ModelAttribute,Spring 会自动从请求中绑定数据到该对象。 - 适用于 简化代码 ,避免显式调用
@ModelAttribute方法。
示例
java
`@PostMapping("/register")
public String register(@ModelAttribute User user, BindingResult result) {
if (result.hasErrors()) {
return "error";
}
return "success";
}`
- 效果 :
- Spring 会自动创建一个
User对象,并绑定请求参数(如username、password)。 - 相当于隐式调用了
@ModelAttribute方法。
- Spring 会自动创建一个
3. @ModelAttribute 的其他用途
(1) 向 Model 中添加数据(不绑定请求参数)
java
`@ModelAttribute("message")
public String addMessage() {
return "Hello, Spring MVC!";
}`
- 作用 :
- 将
"Hello, Spring MVC!"添加到Model中,key 为"message"。 - 可以在视图(如 JSP、Thymeleaf)中直接使用
${message}。
- 将
(2) 与 @SessionAttributes 结合使用
java
`@Controller
@SessionAttributes("user") // 将 Model 中的 "user" 存入 Session
public class UserController {
@ModelAttribute("user")
public User prepareUser() {
return new User();
}
@PostMapping("/login")
public String login(@ModelAttribute("user") User user) {
// 登录逻辑...
return "redirect:/dashboard"; // 跳转后,user 仍存在于 Session
}
}`
- 作用 :
- 将
Model中的user对象存入HttpSession,后续请求可以继续使用。
- 将
@ModelAttribute vs @RequestBody
| 特性 | @ModelAttribute |
@RequestBody |
|---|---|---|
| 数据来源 | 表单数据(application/x-www-form-urlencoded) |
JSON/XML(application/json) |
| 绑定方式 | 自动绑定请求参数到 Java 对象字段 | 通过 HttpMessageConverter 反序列化 |
| 适用场景 | 传统表单提交、REST API(非 JSON) | REST API(JSON/XML) |
| 校验支持 | 支持 @Valid |
支持 @Valid |
示例对比
@ModelAttribute(表单提交)
java
`@PostMapping("/user")
public String createUser(@ModelAttribute User user) {
return "user: " + user.getUsername();
}`
-
请求 :
`POST /user Content-Type: application/x-www-form-urlencoded username=John&password=123`
@RequestBody(JSON 请求)
java
`@PostMapping("/api/user")
public ResponseEntity<User> createUser(@RequestBody User user) {
return ResponseEntity.ok(user);
}`
-
请求 :
`POST /api/user Content-Type: application/json { "username": "John", "password": "123" }`
总结
| 用法 | 说明 |
|---|---|
方法级 @ModelAttribute |
在 @RequestMapping 方法前执行,绑定请求参数到对象并存入 Model |
参数级 @ModelAttribute |
直接绑定请求参数到方法参数对象 |
向 Model 添加数据 |
@ModelAttribute("key") String value() |
与 @SessionAttributes 结合 |
将 Model 数据存入 Session |
| 适用场景 | 表单提交、非 JSON REST API |
最佳实践
- 表单提交 → 用
@ModelAttribute。 - JSON/XML REST API → 用
@RequestBody。 - 校验 → 结合
@Valid或@Validated使用。
希望这个解释能帮到你! 😊