你可以使用 @ModelAttribute 注解:
- 在
@RequestMapping
方法的 方法参数 上,从模型中创建或访问一个对象,并通过 WebDataBinder 将其绑定到请求上。 - 作为
@Controller
或@ControllerAdvice
类中的方法级注解,有助于在任何@RequestMapping
方法调用前初始化模型。 - 在一个
@RequestMapping
方法上,标记其返回值是一个模型属性。
本节讨论 @ModelAttribute 方法 - 前面列表中的第二项。一个控制器可以有任意数量的 @ModelAttribute 方法。所有这些方法都在同一个控制器的 @RequestMapping
方法之前被调用。一个 @ModelAttribute 方法也可以通过 @ControllerAdvice 在各个控制器之间共享。更多细节请看 控制器 advice 部分。
@ModelAttribute 方法有灵活的方法签名。它们支持许多与 @RequestMapping 方法相同的参数,除了 @ModelAttribute 本身或任何与请求体有关的东西。
下面的例子显示了一个 @ModelAttribute 方法:
@ModelAttribute
public void populateModel(@RequestParam String number, Model model) {
model.addAttribute(accountRepository.findAccount(number));
// add more ...
}
下面的例子只增加了一个属性:
@ModelAttribute
public Account addAccount(@RequestParam String number) {
return accountRepository.findAccount(number);
}
:::info 当没有明确指定名称时,会根据对象类型选择一个默认的名称,正如 Conventions 的 javadoc 中解释的那样。你总是可以通过使用重载的 addAttribute 方法或通过 @ModelAttribute 上的 name 属性(用于返回值)来指定一个明确的名字。 :::
你也可以使用 @ModelAttribute 作为 @RequestMapping 方法的方法级注解,在这种情况下,@RequestMapping 方法的返回值被解释为模型属性。这通常是不需要的,因为它是 HTML 控制器中的默认行为,除非返回值是一个 String,否则会被解释为视图名称。@ModelAttribute 也可以自定义模型属性名称,正如下面的例子所示:
@GetMapping("/accounts/{id}")
@ModelAttribute("myAccount")
public Account handle() {
// ...
return account;
}
一个例子
前面看了之后,没有明白是什么意思,下面看一个例子你就明白了
@ModelAttribute(name = "p2")
public Pet fun1(@RequestParam Integer id) {
final Pet pet = new Pet();
pet.setPetId(id);
return pet;
}
@GetMapping("/files")
@ResponseBody
public Pet fun2(@ModelAttribute(name = "p2") Pet pet) {
return pet;
}
访问 [http://localhost:8080/files?id=1&ownerId=567](http://localhost:8080/files?id=1&ownerId=567)
请求时,fun1 会先执行,参数 id 就是路径里面的值,然后才会执行 fun2,这个时候会将 fun1 里面的对象注入,由于 fun1 里面的 pet 没有设置 ownerId,这里会使用参数中的填充,下面是响应的信息(学到后面 Jackson JSON 下面的才能正常的响应 json 参数)
{
"ownerId": 567,
"petId": 1
}
:::tips
前面 说到这个 @ModelAttribute 的参数来自好几个地方。所以这样你就明白是啥意思了;
另外:
1. 对于 @ModelAttribute 注解的方法参数的对象,url 上的值会覆盖掉这个对象的值。
2. 同一个 controller 中如果有多个 @ModelAttribute 方法,每次请求这些都会执行,但是只会注入名称相同的 model 给你
3. 因为每个 @ModelAttribute 注解的方法都会执行,如果不满足方法里面的入参信息,就会报错
:::