此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Framework 6.2.0spring-doc.cadn.net.cn

@ModelAttribute

@ModelAttributemethod parameter annotation 绑定请求参数、URI 路径变量、 和请求标头添加到模型对象上。例如:spring-doc.cadn.net.cn

@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.

请求参数是一个 Servlet API 概念,它包括来自请求正文的表单数据。 和 query 参数。URI 变量和标头也包含在内,但前提是它们不包含 覆盖具有相同名称的请求参数。破折号将从标题名称中去除。spring-doc.cadn.net.cn

Pet实例可能是:spring-doc.cadn.net.cn

如上所述,一个Converter<String, T>可用于获取 Model 对象,如果 模型属性名称与请求值的名称匹配,例如路径变量或 request 参数,并且有一个兼容的Converter<String, T>.在下面的示例中, 模型属性名称accountmatches URI 路径变量account,并且有一个 注册Converter<String, Account>这可能会从 Persistence Store 中检索它:spring-doc.cadn.net.cn

@PutMapping("/accounts/{account}")
public String save(@ModelAttribute("account") Account account) { (1)
	// ...
}
@PutMapping("/accounts/{account}")
fun save(@ModelAttribute("account") account: Account): String { (1)
	// ...
}

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

使用构造函数绑定时,您可以通过@BindParam注解。例如:spring-doc.cadn.net.cn

class Account {

    private final String firstName;

	public Account(@BindParam("first-name") String firstName) {
		this.firstName = firstName;
	}
}
class Account(@BindParam("first-name") val firstName: String)
@BindParam也可以放置在与 constructor 对应的字段上 参数。而@BindParam支持开箱即用,您还可以使用 different 注解,方法是将DataBinder.NameResolverDataBinder

构造函数绑定支持List,Map和数组参数从 单个字符串(例如逗号分隔的列表)或基于索引键(如accounts[2].nameaccount[KEY].name.spring-doc.cadn.net.cn

在某些情况下,您可能希望访问没有数据绑定的 model 属性。对于这样的 cases,您可以注入Model放入控制器并直接访问它,或者, 或者,将@ModelAttribute(binding=false),如下例所示:spring-doc.cadn.net.cn

@ModelAttribute
public AccountForm setUpForm() {
	return new AccountForm();
}

@ModelAttribute
public Account findAccount(@PathVariable String accountId) {
	return accountRepository.findOne(accountId);
}

@PostMapping("update")
public String update(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(form: AccountForm, result: BindingResult,
		   @ModelAttribute(binding = false) account: Account): String { (1)
	// ...
}
1 设置@ModelAt\tribute(binding=false).

如果数据绑定导致错误,则默认情况下MethodArgumentNotValidException被提升, 但您也可以添加BindingResult参数紧邻@ModelAttribute为了在 controller 方法中处理此类错误。例如: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@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.

您可以通过在数据绑定后自动应用验证,方法是添加jakarta.validation.Valid注解或 Spring 的@Validated注解。 请参见 Bean 验证Spring 验证。例如: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 验证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实例。

如果没有BindingResult参数@ModelAttribute然后MethodArgumentNotValueException会引发验证错误。但是,如果方法 验证适用,因为其他参数具有@jakarta.validation.Constraint附注 然后HandlerMethodValidationException而是引发。有关更多详细信息,请参阅验证部分。spring-doc.cadn.net.cn

@ModelAttribute是可选的。默认情况下,任何不是简单 由 BeanUtils#isSimpleProperty 确定的值类型,并且未由任何其他参数解析器解析的 value 类型被视为隐式@ModelAttribute.
使用 GraalVM 编译为原生镜像时,隐式的@ModelAttribute上述支持不允许对相关数据进行适当的提前推理 绑定反射提示。因此,建议显式注释 method 参数替换为@ModelAttribute用于 GraalVM 原生映像。