Question about Spring MVC
@ModelAttribute
methods, Setting model attributes in a controller @RequestMapping
method verses setting attribute individually with @ModelAttribute
methods, which one is considered better and is more used?
From design point of view which approach is considered better from the following:
Approach 1
@ModelAttribute("message")
public String addMessage(@PathVariable("userName") String userName, ModelMap model) {
LOGGER.info("addMessage - " + userName);
return "Spring 3 MVC Hello World - " + userName;
}
@RequestMapping(value="/welcome/{userName}", method = RequestMethod.GET)
public String printWelcome(@PathVariable("userName") String userName, ModelMap model) {
LOGGER.info("printWelcome - " + userName);
return "hello";
}
Approach 2
@RequestMapping(value="/welcome/{userName}", method = RequestMethod.GET)
public String printWelcome(@PathVariable("userName") String userName, ModelMap model) {
LOGGER.info("printWelcome - " + userName);
model.addAttribute("message", "Spring 3 MVC Hello World - " + userName);
return "hello";
}
One is not better then the other. They both serve another purpose.
- Method: If you need the model for a particular controller to be always populated with certain attributes the method level
@ModelAttribute
makes more sense.
- Parameter: Use it on a parameter when you want to bind data from the request and add it to the model implicitly.
To answer your question on the better approach
I would say approach 2 is better since the data is specific to that handler.
The @ModelAttribute annotation
serves two purposes depending on how it is used:
At Method level
Use @ModelAttribute
at the method level to provide reference data for the model. @ModelAttribute annotated methods are executed before the chosen @RequestMapping
annotated handler method. They effectively pre-populate the implicit model with specific attributes, often loaded from a database. Such an attribute can then already be accessed through @ModelAttribute
annotated handler method parameters in the chosen handler method, potentially with binding and validation applied to it.
In other words; a method annotated with @ModelAttribute
will populate the specified “key” in the model. This happens BEFORE the @RequestMapping
At Method Parameter level
At Method Parameter level
When you place @ModelAttribute
on a method parameter, @ModelAttribute
maps a model attribute to the specific, annotated method parameter. This is how the controller gets a reference to the object holding the data entered in the form.
Examples
Method Level
@Controller
public class MyController {
@ModelAttribute("productsList")
public Collection<Product> populateProducts() {
return this.productsService.getProducts();
}
}
So, in the above example, “productsList
” in the Model is populated before the the @RequestMapping
is performed.
Method parameter level
@Controller
public class MyController {
@RequestMapping(method = RequestMethod.POST)
public String processSubmit(@ModelAttribute("product") Product myProduct, BindingResult result, SessionStatus status) {
new ProductValidator().validate(myProduct, result);
if (result.hasErrors()) {
return "productForm";
}
else {
this.productsService.saveProduct(myProduct);
status.setComplete();
return "productSaved";
}
}
}
Look here for detailed information with examples.