Skip to content

模型方法 (@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 会智能地同步它们,非常适合多步骤表单的预加载逻辑。

Based on Spring Framework.