Spring MVC @ModelAttribute method

2019-01-17 22:27发布

问题:

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";
}   

回答1:

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.



回答2:

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.