|
This version is still in development and is not considered stable yet. For the latest stable version, please use Spring Framework 6.2.12! |
Model
You can use the @ModelAttribute annotation:
-
On a method argument in
@RequestMappingmethods to create or access an Object from the model and to bind it to the request through aWebDataBinder. -
As a method-level annotation in
@Controlleror@ControllerAdviceclasses, helping to initialize the model prior to any@RequestMappingmethod invocation. -
On a
@RequestMappingmethod to mark its return value as a model attribute.
This section discusses @ModelAttribute methods, or the second item from the preceding list.
A controller can have any number of @ModelAttribute methods. All such methods are
invoked before @RequestMapping methods in the same controller. A @ModelAttribute
method can also be shared across controllers through @ControllerAdvice. See the section on
Controller Advice for more details.
@ModelAttribute methods have flexible method signatures. They support many of the same
arguments as @RequestMapping methods (except for @ModelAttribute itself and anything
related to the request body).
The following example uses a @ModelAttribute method:
-
Java
-
Kotlin
@ModelAttribute
public void populateModel(@RequestParam String number, Model model) {
model.addAttribute(accountRepository.findAccount(number));
// add more ...
}
@ModelAttribute
fun populateModel(@RequestParam number: String, model: Model) {
model.addAttribute(accountRepository.findAccount(number))
// add more ...
}
The following example adds one attribute only:
-
Java
-
Kotlin
@ModelAttribute
public Account addAccount(@RequestParam String number) {
return accountRepository.findAccount(number);
}
@ModelAttribute
fun addAccount(@RequestParam number: String): Account {
return accountRepository.findAccount(number);
}
When a name is not explicitly specified, a default name is chosen based on the type,
as explained in the javadoc for Conventions.
You can always assign an explicit name by using the overloaded addAttribute method or
through the name attribute on @ModelAttribute (for a return value).
|
Spring WebFlux, unlike Spring MVC, explicitly supports reactive types in the model
(for example, Mono<Account> or io.reactivex.Single<Account>). Such asynchronous model
attributes can be transparently resolved (and the model updated) to their actual values
at the time of @RequestMapping invocation, provided a @ModelAttribute argument is
declared without a wrapper, as the following example shows:
-
Java
-
Kotlin
@ModelAttribute
public void addAccount(@RequestParam String number) {
Mono<Account> accountMono = accountRepository.findAccount(number);
model.addAttribute("account", accountMono);
}
@PostMapping("/accounts")
public String handle(@ModelAttribute Account account, BindingResult errors) {
// ...
}
import org.springframework.ui.set
@ModelAttribute
fun addAccount(@RequestParam number: String) {
val accountMono: Mono<Account> = accountRepository.findAccount(number)
model["account"] = accountMono
}
@PostMapping("/accounts")
fun handle(@ModelAttribute account: Account, errors: BindingResult): String {
// ...
}
In addition, any model attributes that have a reactive type wrapper are resolved to their actual values (and the model updated) just prior to view rendering.
You can also use @ModelAttribute as a method-level annotation on @RequestMapping
methods, in which case the return value of the @RequestMapping method is interpreted as a
model attribute. This is typically not required, as it is the default behavior in HTML
controllers, unless the return value is a String that would otherwise be interpreted
as a view name. @ModelAttribute can also help to customize the model attribute name,
as the following example shows:
-
Java
-
Kotlin
@GetMapping("/accounts/{id}")
@ModelAttribute("myAccount")
public Account handle() {
// ...
return account;
}
@GetMapping("/accounts/{id}")
@ModelAttribute("myAccount")
fun handle(): Account {
// ...
return account
}