Model

你可以使用 @ModelAttribute 注解:

  • @RequestMapping方法的 方法参数 上,从模型中创建或访问一个对象,并通过 WebDataBinder 将其绑定到请求上。
  • 作为 @Controller@ControllerAdvice类中的方法级注解,有助于在任何 @RequestMapping方法调用前初始化模型。
  • 在一个 @RequestMapping方法上,标记其返回值是一个模型属性。

本节讨论 @ModelAttribute 方法 - 前面列表中的第二项。一个控制器可以有任意数量的 @ModelAttribute 方法。所有这些方法都在同一个控制器的 @RequestMapping方法之前被调用。一个 @ModelAttribute 方法也可以通过 @ControllerAdvice 在各个控制器之间共享。更多细节请看 控制器 advice 部分

@ModelAttribute 方法有灵活的方法签名。它们支持许多与 @RequestMapping 方法相同的参数,除了 @ModelAttribute 本身或任何与请求体有关的东西。

下面的例子显示了一个 @ModelAttribute 方法:

  1. @ModelAttribute
  2. public void populateModel(@RequestParam String number, Model model) {
  3. model.addAttribute(accountRepository.findAccount(number));
  4. // add more ...
  5. }

下面的例子只增加了一个属性:

  1. @ModelAttribute
  2. public Account addAccount(@RequestParam String number) {
  3. return accountRepository.findAccount(number);
  4. }

:::info 当没有明确指定名称时,会根据对象类型选择一个默认的名称,正如 Conventions 的 javadoc 中解释的那样。你总是可以通过使用重载的 addAttribute 方法或通过 @ModelAttribute 上的 name 属性(用于返回值)来指定一个明确的名字。 :::

你也可以使用 @ModelAttribute 作为 @RequestMapping 方法的方法级注解,在这种情况下,@RequestMapping 方法的返回值被解释为模型属性。这通常是不需要的,因为它是 HTML 控制器中的默认行为,除非返回值是一个 String,否则会被解释为视图名称。@ModelAttribute 也可以自定义模型属性名称,正如下面的例子所示:

  1. @GetMapping("/accounts/{id}")
  2. @ModelAttribute("myAccount")
  3. public Account handle() {
  4. // ...
  5. return account;
  6. }

一个例子

前面看了之后,没有明白是什么意思,下面看一个例子你就明白了

  1. @ModelAttribute(name = "p2")
  2. public Pet fun1(@RequestParam Integer id) {
  3. final Pet pet = new Pet();
  4. pet.setPetId(id);
  5. return pet;
  6. }
  7. @GetMapping("/files")
  8. @ResponseBody
  9. public Pet fun2(@ModelAttribute(name = "p2") Pet pet) {
  10. return pet;
  11. }

访问 [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 参数)

  1. {
  2. "ownerId": 567,
  3. "petId": 1
  4. }

:::tips 前面 说到这个 @ModelAttribute 的参数来自好几个地方。所以这样你就明白是啥意思了;
另外:
1. 对于 @ModelAttribute 注解的方法参数的对象,url 上的值会覆盖掉这个对象的值。
2. 同一个 controller 中如果有多个 @ModelAttribute 方法,每次请求这些都会执行,但是只会注入名称相同的 model 给你
3. 因为每个 @ModelAttribute 注解的方法都会执行,如果不满足方法里面的入参信息,就会报错 :::