最新の安定バージョンについては、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...
}
1 | Pet のインスタンスをバインドします。 |
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
fun processSubmit(@ModelAttribute pet: Pet): String { (1)
// method logic...
}
1 | Pet のインスタンスをバインドします。 |
上記の 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";
}
// ...
}
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 (Javadoc) によって決定される)単純な値型ではなく、他の引数リゾルバーによって解決されない引数は、@ModelAttribute
でアノテーションが付けられているかのように扱われます。
GraalVM を使用してネイティブイメージにコンパイルする場合、上記の暗黙的な @ModelAttribute サポートでは、関連するデータバインディングのリフレクションヒントを適切に事前推論できません。結果として、GraalVM ネイティブイメージで使用するためにメソッドパラメーターに @ModelAttribute のアノテーションを明示的に付けることをお勧めします。 |