跳到主要内容
版本:7.0.3

@ModelAttribute

Hunyuan 7b 中英对照 @ModelAttribute @ModelAttribute

@ModelAttribute方法参数注解可以将表单数据、查询参数、URI路径变量和请求头绑定到模型对象上。例如:

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute Pet pet) { } 1
  • Pet 实例绑定。

表单数据和查询参数的优先级高于 URI 变量及头部信息;只有当这些头部信息不会覆盖同名请求参数时,才会被包含进来。头部信息的名称中的短横线(-)会被删除。

Pet实例可以是:

  • 从模型中访问,该模型可能通过Model进行添加。
  • 如果模型属性在类级别的@SessionAttributes中列出,则从HTTP会话中访问。
  • 通过默认构造函数实例化。
  • 通过“主构造函数”实例化,其参数与Servlet请求参数匹配。参数名称是根据字节码中在运行时保留的参数名称来确定的。

默认情况下,构造函数和属性数据绑定都会被应用。然而,模型对象的设计需要仔细考虑,出于安全原因,建议使用专为Web绑定定制的对象,或者仅应用构造函数绑定。如果仍然必须使用属性绑定,则应设置allowedFields模式来限制可以设置的属性。有关此内容的更多详细信息和示例配置,请参见模型设计

在使用构造函数绑定时,你可以通过@BindParam注解来自定义请求参数的名称。例如:

class Account {

private final String firstName;

public Account(@BindParam("first-name") String firstName) {
this.firstName = firstName;
}
}
备注

@BindParam也可以用于对应于构造函数参数的字段上。虽然@BindParam是默认支持的,但你也可以通过在DataBinder上设置DataBinder.NameResolver来使用不同的注解。

构造函数绑定支持ListMap和数组参数,这些参数可以是从单个字符串转换而来的(例如,逗号分隔的列表),也可以是基于索引键的,如accounts[2].nameaccount[KEY].name

与Spring MVC不同,WebFlux在模型中支持响应式类型(例如Mono<Account>)。你可以声明一个带有或不带有响应式类型包装器的@ModelAttribute参数,它将根据实际值进行相应的解析。

如果数据绑定导致错误,默认会抛出WebExchangeBindException,但你也可以在@ModelAttribute旁边直接添加一个BindingResult参数,以便在控制器方法中处理此类错误。例如:

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result) { 1
if (result.hasErrors()) {
return "petForm";
}
// ...
}
  • 添加了 BindingResult

要使用BindingResult参数,你必须先声明没有反应型类型包装的@ModelAttribute参数。如果你想使用反应型类型,就可以通过它直接处理错误。例如:

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public Mono<String> processSubmit(@Valid @ModelAttribute("pet") Mono<Pet> petMono) {
return petMono
.flatMap(pet -> {
// ...
})
.onErrorResume(ex -> {
// ...
});
}

你可以在数据绑定后自动应用验证,只需添加 jakarta.validation VALID 注解或 Spring 的 @Validated 注解(请参阅 Bean ValidationSpring 验证)。例如:

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@Valid @ModelAttribute("pet") Pet pet, BindingResult result) { 1
if (result.hasErrors()) {
return "petForm";
}
// ...
}
  • 在模型属性参数上使用 @Valid

如果由于其他参数具有@Constraint注解而需要应用方法验证,那么将会抛出HandlerMethodValidationException异常。请参阅关于控制器方法验证的相关部分。

提示

使用@ModelAttribute是可选的。默认情况下,任何不是由BeanUtils#isSimpleProperty判断为简单值类型的参数,并且没有通过其他参数解析器进行解析的,都会被视为隐式的@ModelAttribute

注意

在使用GraalVM编译为原生镜像时,上述隐式的@ModelAttribute支持不允许对相关的数据绑定反射提示进行适当的提前推断。因此,建议在方法参数上明确标注@ModelAttribute,以便在GraalVM原生镜像中使用。