The annotation-based programming model provided by Spring MVC greatly simplifies the development of Web applications. Among them, @controller and @restcontroller annotated components use @requestmapping, @exceptionhandler and other annotations to express RequestMapping, request input, exception handling, etc., so that developers can focus on writing business logic. Improved development efficiency. Annotated controllers have flexible method signatures without having to extend base classes or implement specific interfaces.

Controller beans can be defined using the standard Spring bean definition in the Servlet’s WebApplicationContext. All classes with the @Controller annotation are automatically detected, just as Spring normally scans the @Component classes in the classpath and automatically registers the bean definitions for them. It also acts as a stereotype for the annotation class, indicating that it can be used as a Web component.

A Method annotated with @requestMapping is called Handler Method – a Handler Method whose parameters can come from many places, such as ServletRequest, ServletResponse, HttpSession, etc.

@ModelAttribute

Adding the @ModelAttribute annotation to the controller’s processor method parameters gives you access to attributes in the model, and if the model does not exist, it will automatically instantiate to produce a new model. Model properties are covered from the HTTP Servlet request parameters to match the value of the field name, the name of the request parameter is if and domain of the variables in the model class is consistent, these request parameters will be automatically bound to the object model, this is called data binding, avoiding the parsing and transformation each request parameters and form fields such code. Such as:

@PostMapping("/componies/{componyId}/departments/{departmentId}/edit")
public String processSubmit(@ModelAttribute Department department) {}Copy the code

The department parameter in this handler method is matched and bound from several sources:

  • Model methods that have been defined (with@ModelAttributeMethod, explained later)
  • HTTP Session methods that match field names (with@SessionAttributeIs similar to the model method, but with different scope.
  • Path variables parsed by the URL converter
  • The default constructor for the model class
  • Call the “primary constructor” with parameters that match the Servlet request parameters; Parameter name through JavaBeans@ConstructorPropertiesOr by the runtime retention parameter name in the bytecode.

While the Model method is typically used to populate the Model with attributes, another approach relies on Converter

recognizing URI path variables to bind. In the following example, the model attribute name “user” matches the URI path variable “user” and generates the create model by passing the user name of type String to the registered Converter

:
,>
,t>

@PutMapping("/users/{user}")
public String saveUser(@ModelAttribute("user") User user) {
    // ...
}
Copy the code

After the model property instance is obtained, the request data is bound to the model property. The WebDataBinder is responsible for matching Servlet request parameter names (query parameters or form fields) with field names on the target model object. If necessary, convert the type of the attribute before populating the corresponding field.

Data binding is no guarantee against errors, and when errors occur, BindException is thrown by default, but to identify these errors in processor methods, you need to add a parameter of type BindingResult to @ModelAttribute. Note that: This parameter must be adjacent to the ModelAttribute parameter (the @modelattribute parameter) as follows:

@PostMapping("/owners/{componyId}/departments/{departmentId}/edit")
public String processSubmit(@ModelAttribute("compony") Compony compony, BindingResult result) {
    if (result.hasErrors()) {
        return "componyForm";
    }
    // ...
}
Copy the code

This example shows that the view componyForm is returned if the form submitted by the user does not match the expected rules.

Sometimes we need to get a model property without data binding, that is, we need to instantiate an object in a processor method using the new keyword. But in Spring MVC we don’t have to do that. We can inject the model into the controller and access it directly, or we can add @modelAttribute (binding = false) to indicate that we don’t need to bind data, as follows:

@ModelAttribute
public UserForm setUpForm(a) {
    return new UserForm();
}

@ModelAttribute
public User findUser(@PathVariable String userId) {
    return userRepository.findOne(userId);
}

@PostMapping("update")
public String update(@Valid UserUpdateForm form, BindingResult result,
        @ModelAttribute(binding=false) User user) {
    // ...
}
Copy the code

To use field validation after data binding, add the Javax.validation. Valid annotation or Spring’s @Validated annotation to the parameters, like this:

@PostMapping("/componies/{componyId}/departments/{departmentId}/edit")
public String processSubmit(@Valid @ModelAttribute("department") Department department, BindingResult result) {
    if (result.hasErrors()) {
        return "departmentForm";
    }
    // ...
}
Copy the code

This is equivalent to writing Model.addattribute (” Compony “,compony) in the method body.

Note that if the @ModelAttribute annotation is not added, parameters that do not belong to simple types are automatically treated as ModelAttribute based on the isSimpleProperty method in BeanUtils.

Welcome to Paul Cheng’s blog