对于最新的稳定版本,请使用 Spring Framework 6.2.0! |
@ModelAttribute
您可以使用@ModelAttribute
注解来访问来自
model 或实例化它(如果不存在)。model 属性还与
名称与字段名称匹配的查询参数和表单字段的值。这是
称为数据绑定,它使您不必处理解析和
转换单个查询参数和表单字段。以下示例将Pet
:
-
Java
-
Kotlin
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute Pet pet) { } (1)
1 | 绑定 的实例Pet . |
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
fun processSubmit(@ModelAttribute pet: Pet): String { } (1)
1 | 绑定 的实例Pet . |
这Pet
实例解析如下:
-
从模型(如果已添加)
Model
. -
从 HTTP 会话到
@SessionAttributes
. -
从默认构造函数的调用。
-
从具有与 query 匹配的参数的“主构造函数”的调用 参数或表单字段。参数名称是通过 JavaBeans 确定的
@ConstructorProperties
或通过字节码中运行时保留的参数名称。
获取 model 属性实例后,将应用数据绑定。这WebExchangeDataBinder
类将查询参数和表单字段的名称与字段匹配
目标上的名称Object
.在应用类型转换后填充匹配字段
必要时。有关数据绑定(和验证)的更多信息,请参阅验证。有关自定义数据绑定的更多信息,请参阅DataBinder
.
数据绑定可能会导致错误。默认情况下,WebExchangeBindException
被提升,但是,
要在控制器方法中检查此类错误,您可以添加BindingResult
论点
紧挨着@ModelAttribute
,如下例所示:
-
Java
-
Kotlin
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result) { (1)
if (result.hasErrors()) {
return "petForm";
}
// ...
}
1 | 添加BindingResult . |
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
fun processSubmit(@ModelAttribute("pet") pet: Pet, result: BindingResult): String { (1)
if (result.hasErrors()) {
return "petForm"
}
// ...
}
1 | 添加BindingResult . |
您可以通过在数据绑定后自动应用验证,方法是添加jakarta.validation.Valid
注解或 Spring 的@Validated
注解(另请参见 Bean 验证和 Spring 验证)。以下示例使用@Valid
注解:
-
Java
-
Kotlin
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@Valid @ModelAttribute("pet") Pet pet, BindingResult result) { (1)
if (result.hasErrors()) {
return "petForm";
}
// ...
}
1 | 用@Valid 在 model 属性参数上。 |
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
fun processSubmit(@Valid @ModelAttribute("pet") pet: Pet, result: BindingResult): String { (1)
if (result.hasErrors()) {
return "petForm"
}
// ...
}
1 | 用@Valid 在 model 属性参数上。 |
与 Spring MVC 不同,Spring WebFlux 在模型中支持响应式类型——例如,Mono<Account>
或io.reactivex.Single<Account>
.您可以声明@ModelAttribute
论点
有或没有响应式类型包装器,并且它将被相应地解析,
如有必要,请更改为实际值。但是,请注意,要使用BindingResult
参数,则必须声明@ModelAttribute
参数,而没有响应式
type 包装器,如前所述。或者,您可以通过
reactive 类型,如下例所示:
-
Java
-
Kotlin
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public Mono<String> processSubmit(@Valid @ModelAttribute("pet") Mono<Pet> petMono) {
return petMono
.flatMap(pet -> {
// ...
})
.onErrorResume(ex -> {
// ...
});
}
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
fun processSubmit(@Valid @ModelAttribute("pet") petMono: Mono<Pet>): Mono<String> {
return petMono
.flatMap { pet ->
// ...
}
.onErrorResume{ ex ->
// ...
}
}
请注意,使用@ModelAttribute
是可选的 — 例如,设置其属性。
默认情况下,任何不是简单值类型的参数(由 BeanUtils#isSimpleProperty 确定)
并且未由任何其他参数解析 resolver 被视为已批注
跟@ModelAttribute
.
使用 GraalVM 编译为原生镜像时,隐式的@ModelAttribute 上述支持不允许对相关数据进行适当的提前推理
绑定反射提示。因此,建议显式注释
method 参数替换为@ModelAttribute 用于 GraalVM 原生映像。 |