模型方法 (@ModelAttribute)
@ModelAttribute 注解除了用于方法参数外,还可以用于方法级别。本节讨论作为方法级注解的 @ModelAttribute。
基本用法
在一个控制器中,可以有任意数量的 @ModelAttribute 方法。这些方法会在该控制器的所有 @RequestMapping 方法执行之前被调用。
java
@ModelAttribute
public void populateModel(@RequestParam String number, Model model) {
model.addAttribute(accountRepository.findAccount(number));
// 还可以添加更多属性...
}
// 或者直接返回一个对象
@ModelAttribute
public Account addAccount(@RequestParam String number) {
return accountRepository.findAccount(number);
}kotlin
@ModelAttribute
fun populateModel(@RequestParam number: String, model: Model) {
model.addAttribute(accountRepository.findAccount(number))
}
@ModelAttribute
fun addAccount(@RequestParam number: String): Account {
return accountRepository.findAccount(number)
}核心特性
- 执行顺序:在任何
@RequestMapping方法之前运行。 - 默认命名:如果不通过
@ModelAttribute("name")显式指定名称,Spring 会根据返回对象的类型推断名称。 - 共享性:如果在
@ControllerAdvice类中声明,这些方法将在所有控制器中生效。 - 作为返回值处理:如果对
@RequestMapping方法应用@ModelAttribute,其返回值将被视为模型属性,而不是逻辑视图名。
补充教学
1. 为什么要使用方法级的 @ModelAttribute?
在传统的 HTML 页面(如 JSP, Thymeleaf)中,你经常需要一些通用的下拉列表数据(如国家列表、角色列表)。如果不使用这种方法,你得在每个 GetMapping 方法里手动写: model.addAttribute("roles", roleService.listAll())。 使用 @ModelAttribute 方法,你只需要写一次,该控制器下的所有页面就自动拥有了这些数据。
2. 注意性能陷阱
由于它在每一个请求方法之前都会运行,如果你的 @ModelAttribute 方法里包含耗时的数据库查询,会显著拖慢所有接口。 建议:仅用于确实需要全局初始化的轻量数据,或者配合缓存。
3. 它与 @SessionAttributes 的联动
如果一个属性名同时存在于 @ModelAttribute 方法的返回值和类级别的 @SessionAttributes 中,Spring 会智能地同步它们,非常适合多步骤表单的预加载逻辑。