对于最新的稳定版本,请使用 Spring Framework 6.2.0spring-doc.cadn.net.cn

@ModelAttribute

您可以使用@ModelAttribute注解来访问来自 model 或实例化它(如果不存在)。model 属性还与 名称与字段名称匹配的查询参数和表单字段的值。这是 称为数据绑定,它使您不必处理解析和 转换单个查询参数和表单字段。以下示例将Pet:spring-doc.cadn.net.cn

@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实例解析如下:spring-doc.cadn.net.cn

获取 model 属性实例后,将应用数据绑定。这WebExchangeDataBinder类将查询参数和表单字段的名称与字段匹配 目标上的名称Object.在应用类型转换后填充匹配字段 必要时。有关数据绑定(和验证)的更多信息,请参阅验证。有关自定义数据绑定的更多信息,请参阅DataBinder.spring-doc.cadn.net.cn

数据绑定可能会导致错误。默认情况下,WebExchangeBindException被提升,但是, 要在控制器方法中检查此类错误,您可以添加BindingResult论点 紧挨着@ModelAttribute,如下例所示:spring-doc.cadn.net.cn

@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注解:spring-doc.cadn.net.cn

@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 类型,如下例所示:spring-doc.cadn.net.cn

@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.spring-doc.cadn.net.cn

使用 GraalVM 编译为原生镜像时,隐式的@ModelAttribute上述支持不允许对相关数据进行适当的提前推理 绑定反射提示。因此,建议显式注释 method 参数替换为@ModelAttribute用于 GraalVM 原生映像。