最新の安定バージョンについては、Spring Framework 6.2.6 を使用してください!

@ModelAttribute

メソッドの引数で @ModelAttribute アノテーションを使用して、モデルの属性にアクセスしたり、存在しない場合はインスタンス化したりできます。モデル属性は、フィールド名と名前が一致する HTTP サーブレットリクエストパラメーターの値で上書きされます。これはデータバインディングと呼ばれ、個々のクエリパラメーターとフォームフィールドの解析と変換に対処する必要がなくなります。次の例は、その方法を示しています。

  • Java

  • Kotlin

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute Pet pet) { (1)
	// method logic...
}
1Pet のインスタンスをバインドします。
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
fun processSubmit(@ModelAttribute pet: Pet): String { (1)
	// method logic...
}
1Pet のインスタンスをバインドします。

上記の Pet インスタンスは、次のいずれかの方法で供給されます。

  • @ModelAttribute メソッドによって追加された可能性のあるモデルから取得されます。

  • モデル属性がクラスレベルの @SessionAttributes アノテーションにリストされている場合、HTTP セッションから取得されます。

  • モデル属性名がパス変数やリクエストパラメーターなどのリクエスト値の名前と一致する Converter を介して取得されます(次の例を参照)。

  • デフォルトのコンストラクターを使用してインスタンス化されます。

  • サーブレットリクエストパラメーターに一致する引数を使用して「プライマリコンストラクター」を介してインスタンス化されます。引数名は、JavaBeans @ConstructorProperties を介して、またはバイトコード内の実行時に保持されるパラメーター名を介して決定されます。

@ModelAttribute メソッドを使用してそれを提供するか、フレームワークに依存してモデル属性を作成する代わりの 1 つの方法は、Converter<String, T> を使用してインスタンスを提供することです。これは、モデル属性名がパス変数やリクエストパラメーターなどのリクエスト値の名前と一致し、String からモデル属性型への Converter がある場合に適用されます。次の例では、モデル属性名は URI パス変数 account と一致する account であり、データストアから Account をロードできる登録済み Converter<String, 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 のインスタンスをバインドします。

モデル属性インスタンスが取得された後、データバインディングが適用されます。WebDataBinder クラスは、サーブレットリクエストパラメーター名(クエリパラメーターとフォームフィールド)をターゲット Object のフィールド名に一致させます。必要に応じて、型変換が適用された後、一致するフィールドに値が入力されます。データバインディング(および検証)の詳細については、検証を参照してください。データバインディングのカスタマイズの詳細については、DataBinder を参照してください。

データバインディングはエラーになる可能性があります。デフォルトでは、BindException が発生します。ただし、コントローラーメソッドでこのようなエラーをチェックするには、次の例に示すように、@ModelAttribute のすぐ隣に BindingResult 引数を追加できます。

  • Java

  • Kotlin

@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result) { (1)
	if (result.hasErrors()) {
		return "petForm";
	}
	// ...
}
1@ModelAttribute の隣に BindingResult を追加します。
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
fun processSubmit(@ModelAttribute("pet") pet: Pet, result: BindingResult): String { (1)
	if (result.hasErrors()) {
		return "petForm"
	}
	// ...
}
1@ModelAttribute の隣に BindingResult を追加します。

場合によっては、データバインディングなしでモデル属性にアクセスしたい場合があります。このような場合、次の例に示すように、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";
	}
	// ...
}
1Pet インスタンスを検証します。
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
fun processSubmit(@Valid @ModelAttribute("pet") pet: Pet, result: BindingResult): String { (1)
	if (result.hasErrors()) {
		return "petForm"
	}
	// ...
}
1Pet インスタンスを検証します。

@ModelAttribute の使用はオプションです(たとえば、属性を設定するため)。デフォルトでは、(BeanUtils#isSimpleProperty (Javadoc) によって決定される)単純な値型ではなく、他の引数リゾルバーによって解決されない引数は、@ModelAttribute でアノテーションが付けられているかのように扱われます。

GraalVM を使用してネイティブイメージにコンパイルする場合、上記の暗黙的な @ModelAttribute サポートでは、関連するデータバインディングのリフレクションヒントを適切に事前推論できません。結果として、GraalVM ネイティブイメージで使用するためにメソッドパラメーターに @ModelAttribute のアノテーションを明示的に付けることをお勧めします。