对于最新的稳定版本,请使用 Spring Framework 6.2.0! |
@ModelAttribute
您可以使用@ModelAttribute
对 method 参数的注释来访问属性
模型,如果不存在,则对其进行实例化。model 属性还覆盖了
其名称与字段名称匹配的 HTTP Servlet 请求参数的值。这是指
to 作为数据绑定,并且它使您不必处理解析和转换单个
查询参数和表单字段。以下示例显示了如何执行此作:
-
Java
-
Kotlin
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute Pet pet) { (1)
// method logic...
}
1 | 绑定 的实例Pet . |
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
fun processSubmit(@ModelAttribute pet: Pet): String { (1)
// method logic...
}
1 | 绑定 的实例Pet . |
这Pet
上述实例通过以下方式之一获取:
-
从可能已通过 @ModelAttribute 方法添加的模型中检索。
-
如果 model 属性列在 类级别
@SessionAttributes
注解。 -
通过
Converter
其中 model 属性名称与 请求值,例如 path 变量或 request 参数(请参阅下一个示例)。 -
使用其默认构造函数实例化。
-
通过具有与 Servlet 匹配的参数的 “primary constructor” 实例化 request 参数。参数名称是通过 JavaBeans 确定的
@ConstructorProperties
或通过字节码中运行时保留的参数名称。
使用 @ModelAttribute 方法的一种替代方法
提供它或依赖框架来创建 model 属性,就是要有一个Converter<String, T>
以提供实例。这在 model 属性
name 与请求值的名称匹配,例如 path 变量或 request
参数,并且有一个Converter
从String
设置为 model 属性类型。
在以下示例中,模型属性名称为account
与 URI 匹配
path 变量account
,并且有一个已注册的Converter<String, Account>
哪
可以加载Account
从数据存储:
-
Java
-
Kotlin
@PutMapping("/accounts/{account}")
public String save(@ModelAttribute("account") Account account) { (1)
// ...
}
1 | 绑定 的实例Account 使用显式属性名称。 |
@PutMapping("/accounts/{account}")
fun save(@ModelAttribute("account") account: Account): String { (1)
// ...
}
1 | 绑定 的实例Account 使用显式属性名称。 |
获取 model 属性实例后,将应用数据绑定。这WebDataBinder
class 匹配 Servlet 请求参数名称(查询参数和表单
fields) 添加到目标上的字段名称Object
.匹配字段在 type 之后填充
必要时应用 conversion。有关数据绑定(和验证)的更多信息,请参阅验证。有关自定义数据绑定的更多信息,请参阅DataBinder
.
数据绑定可能会导致错误。默认情况下,BindException
被提升。但是,要检查
对于 controller 方法中的此类错误,您可以添加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 在@ModelAttribute . |
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
fun processSubmit(@ModelAttribute("pet") pet: Pet, result: BindingResult): String { (1)
if (result.hasErrors()) {
return "petForm"
}
// ...
}
1 | 添加BindingResult 在@ModelAttribute . |
在某些情况下,您可能希望访问没有数据绑定的 model 属性。对于这样的
cases,您可以注入Model
放入控制器并直接访问它,或者,
或者,将@ModelAttribute(binding=false)
,如下例所示:
-
Java
-
Kotlin
@ModelAttribute
public AccountForm setUpForm() {
return new AccountForm();
}
@ModelAttribute
public Account findAccount(@PathVariable String accountId) {
return accountRepository.findOne(accountId);
}
@PostMapping("update")
public String update(@Valid AccountForm form, BindingResult result,
@ModelAttribute(binding=false) Account account) { (1)
// ...
}
1 | 设置@ModelAttribute(binding=false) . |
@ModelAttribute
fun setUpForm(): AccountForm {
return AccountForm()
}
@ModelAttribute
fun findAccount(@PathVariable accountId: String): Account {
return accountRepository.findOne(accountId)
}
@PostMapping("update")
fun update(@Valid form: AccountForm, result: BindingResult,
@ModelAttribute(binding = false) account: Account): String { (1)
// ...
}
1 | 设置@ModelAttribute(binding=false) . |
您可以通过在数据绑定后自动应用验证,方法是添加jakarta.validation.Valid
注解或 Spring 的@Validated
注解
(Bean 验证和 Spring 验证)。以下示例显示了如何执行此作:
-
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 | 验证Pet 实例。 |
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
fun processSubmit(@Valid @ModelAttribute("pet") pet: Pet, result: BindingResult): String { (1)
if (result.hasErrors()) {
return "petForm"
}
// ...
}
1 | 验证Pet 实例。 |
请注意,使用@ModelAttribute
是可选的(例如,设置其属性)。
默认情况下,任何不是简单值类型的参数(由 BeanUtils#isSimpleProperty 确定)
并且未由任何其他参数解析 resolver 被视为已批注
跟@ModelAttribute
.
使用 GraalVM 编译为原生镜像时,隐式的@ModelAttribute 上述支持不允许对相关数据进行适当的提前推理
绑定反射提示。因此,建议显式注释
method 参数替换为@ModelAttribute 用于 GraalVM 原生映像。 |