“Offer comes, ask friends to take it! I am participating in the 2022 Spring Recruit Punch card campaign. Click here for more details.”

1. Spring MVC project construction

  1. Create a Maven project and add Spring MVC dependencies
  2. Add a Web Application
  3. Configure web. XML
  4. Configure the Spring MVC configuration file dispatcher-servlet.xml
  5. Create a New Controller, add HelloController, add Hello method, return page/success.jsp page
  6. Create a pages directory in web-INF. Add success.jsp to this directory
  7. Open the Artifact and create a new lib package that will import all the dependencies into the lib package
  8. Configure tomcat, start tomcat, enter localhost:8080/hello, and return to the success.jsp page

Data binding in Spring MVC

Spring MVC converts the page request data to a custom type, such as “employeeName= Stark&age =40&gender=1&[email protected]” of the page submitted POST form data to an Employee object.

Spring MVC binds custom objects to page requests by doing the following:

  • Data type conversion, the page is submitted to the string, to convert the string into a custom object of different types of properties
  • Formatting issues, such as date format conversion, etc
  • Data verification, verify the data submitted on the page

Debug How an Employee’s email is assigned to the Employee object when an Employee is added

// Encapsulate the data submitted for the page in Java beans
bindRequestParameters(binder, request);
Copy the code

Data conversion, formatting, and validation occur during encapsulation

WebDataBinder: data binder, responsible for data binding, involving type conversion, formatting, data validation, etc

  • ConversionService component: Responsible for data type conversion and formatting
  • The Validators component is responsible for data validation
  • The bindingResult component: is responsible for storing errors from data validation during data binding resolution

Spring MVC parses the target method through reflection, binding the request data to the input parameter of the processing method. The core of the data binding is DataBinder.

Custom type converters

The ConversionService component is responsible for data conversion and formatting. There are many Converter converters in ConversionService that can convert String data submitted by a page into various types of data. You can also customize type converters by implementing the Converter interface.

Copy the spring-MVC-CRUD project and rename it spring-MVC-data; Add the Add Employee form to the list page and submit data of the type “[email protected]” to the background QuickAdd method

<form action="/quickadd"> <%-- fill in the employee information to automatically encapsulate the object --%> <input name="empinfo" value="[email protected]">
    <input type="submit" value="Quick Add">
</form>
Copy the code

Add quickAdd method to Controller method

@RequestMapping("/quickadd")
public String quickAdd(@RequestParam("empinfo") Employee employee){
    // The output wrapper object is null
    System.out.println("Encapsulated object :"+ employee);
    return "redirect:/emps";
}
Copy the code

Restart Tomcat and perform quick add operations on the List page

Spring MVC cannot convert a String “[email protected]” to Employee, so you need to define a type converter to convert String to Employee

Spring defines three types of converter interface, implement as a converter interface can be registered as a custom converter to ConversionServiceFactoryBean:

  • Converter

    : Convert S type to T type
    ,t>
  • ConverterFactory: Encapsulates multiple homogeneous Converters of the same series and can be used if you want to convert an object of one type to an object of another type and its subclasses
  • GenericConverter: Type conversions are performed based on context information in the host class of the source and target class objects

3-1 Implement a custom type converter

The newly built converter package, increase the converter class StringToEmployeeConverter String converted to the Employee

public class StringToEmployeeConverter implements Converter<String.Employee> {

    @Autowired
    private DepartmentDao departmentDao;

    @Override
    public Employee convert(String source) {
        
        System.out.println("Convert the submitted String type to Employee");
        if(! source.contains("-")) {return null;
        }
        String[] empInfo = source.split("-");
        Employee employee = new Employee();
        employee.setLastName(empInfo[0]);
        employee.setEmail(empInfo[1]);

        employee.setGender(Integer.parseInt(empInfo[2]));

        Department department = departmentDao.getDepartment(Integer.parseInt(empInfo[3]));
        employee.setDepartment(department);
        returnemployee; }}Copy the code

Conversion is achieved by implementing the Converter interface. The interface’s generics are source and target data types. The convert method returns the class to be converted, and implements the String-to-Employee conversion by splitting the String type and assigning it to a newly created Employee object.

Register custom converters

<mvc:annotation-driven conversion-service="conversionServiceFactory"></mvc:annotation-driven>

<! -- Use custom ConverterService-->
<bean id="conversionServiceFactory" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <! Add custom converters to converters -->
    <property name="converters">
        <set>
            <bean class="com.citi.converter.StringToEmployeeConverter"></bean>
        </set>
    </property>
</bean>
Copy the code

Complete the quickAdd method in EmployeeController

@RequestMapping("/quickadd")
public String quickAdd(@RequestParam("empinfo") Employee employee){
    // The output wrapper object is null
    System.out.println("Encapsulated object :"+ employee);
    employeeDao.save(employee);
    return "redirect:/emps";
}
Copy the code

Restart Tomcat to add the Tomcat

Custom converter steps

  1. Realize Converter interface, realize convert method
  2. Configure the custom Converter in ConversionService
  3. Register a ConversionService that adds a custom Converter

3-2 MVN: annotation – driven label

The MVN :annotation-driver tag supports the following functions:

  • Automatic registration RequestMappingHandlerMapping, RequestMappingHandlerAdapter and ExceptionHandlerExceptionResolver three components
  • ConversionService instances are supported for type conversion of form parameters
  • Support @NumberFormat and @DatatimeFormat annotations to complete data type formatting
  • The @VALID annotation is supported for Bean data validation
  • Support @RequstBody and @responseBody annotations

Iv. Data formatting and verification

4-1 Data formatting

  • Spring in formatting module defines a FormattingConversionService implementing the ConversionService interface implementation class, the implementation class extends the GenericConversionService, So it also does type conversion and it also does formatting.
  • FormattingConversionService have a FormattingConversionServiceFactory factory class, which is used for the Spring context structure.

Using time formatting as an example, add the employee form to the add.jsp page to add the birth property

Add the Birth property column to the list.jsp page and add the Birth property to the Employee entity class

To run add employee, enter the time format yyyY-MM-DD

This parameter can be added only when the time format is YYYY /MM/DD

How to correctly handle YYYY-MM-DD? Use the @datatimeFormate annotation to specify the format of the date

Add the @DateTimeFormat annotation to the Birth property of the Employee entity class to specify the format for the time

@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birth;
Copy the code

The addition failed only because the conversionService we are using does not have the formatting function registered in the Spring MVC configuration file

org.springframework.context.support.ConversionServiceFactoryBean
Copy the code

Switch to

org.springframework.format.support.FormattingConversionServiceFactoryBean
Copy the code
<! -- Use custom ConverterService-->
<bean id="conversionServiceFactory" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <! -- No change in middle content -->
</bean>
Copy the code

Retest can add successfully

FormattingConversionServiceFactoryBean internal registration for the following components

  • NumberFormatAnnotationFormatterFactory: support the use of the properties of digital type@NumberFormatannotations
  • Using JodaDateTimeFormatAnnotationFormatterFactory: support for date type of attribute@DateTimeFormatannotations

The @numerbformat annotation allows you to set attributes of numeric types. The annotation itself has two attributes style: numberFormat. style specifies the style type. Pattern: The type is String. You can customize the pattern, such as “#,###,###”

4-2 Data verification

JSR is Java Specification Requests for validation of Bean data. JSR specifies validation rules for Bean attributes by adding @notnull, @NULL, @max annotations to Bean attributes. In addition, you can customize the verification failure message. Hibernate Validator implements JSR and extends @email, @Length, @Notempty, and @range annotations.

The introduction and use of the verification framework can also refer to whether you have used these programming operations (II) – verification framework parts A, B, AND C

Using the validation framework in Spring MVC starts with the introduction of validation dependencies and Hibernate implementations, as well as the specification and implementation of EL expressions

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.0.1. The Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.16. The Final</version>
</dependency>
<dependency>
    <groupId>javax.el</groupId>
    <artifactId>javax.el-api</artifactId>
    <version>3.0.0</version>
</dependency>
<dependency>
    <groupId>org.glassfish.web</groupId>
    <artifactId>javax.el</artifactId>
    <version>2.2.6</version>
</dependency>
Copy the code

After adding dependencies, PUT all the Jar packages into the lib directory

Add validation annotations to attributes of the Employee entity class

@NotEmpty
@Length(min = 5,max = 8)
private String lastName;

@Email
private String email;
Copy the code

Add an @valid annotation to the method input to validate the incoming arguments and use BindingResult to hold the validation result

@RequestMapping(value = "/emp", method = RequestMethod.POST)
public String addEmp(@Valid Employee employee, BindingResult result){

    System.out.println("Employee information to add :" + employee);
    boolean hasErrors = result.hasErrors();
    if (hasErrors){
        System.out.println("Attribute verification error");
        return "add";
    }
    employeeDao.save(employee);
    // Return to the list page
    return "redirect:/emps";
}
Copy the code

The verification result is parsed in the JSP page

LastName:<form:input path="lastName"/><form:errors path="lastName" /><br/>
Email:<form:input path="email"/><form:errors path="email"/><br/> <! --> Birth :<form:input path="birth" /><form:errors path="birth" /><br>
Copy the code

Restart Tomcat to add the Tomcat

How do I retrieve error messages in other ways

Modify the addEmp method to fetch the specific error message and output the error code through the getFieldErrors method of BindingResult

@RequestMapping(value = "/emp", method = RequestMethod.POST)
public String addEmp(@Valid Employee employee, BindingResult result, Model model){
    Map<String, Object> errorMap = new HashMap<>();

    System.out.println("Employee information to add :" + employee);
    boolean hasErrors = result.hasErrors();
    if (hasErrors){
        System.out.println("Attribute verification error");
        // Get detailed error information
        List<FieldError> fieldErrors = result.getFieldErrors();
        for (FieldError fieldError : fieldErrors) {
            System.out.println("Error field is:" + fieldError.getField() + ", error message:" + fieldError.getDefaultMessage());
            // Get the error code used as the Key for the internationalization configuration
            String[] codes = fieldError.getCodes();
            for (String code : codes) {
                System.out.println(code);
            }
            errorMap.put(fieldError.getField(),fieldError.getDefaultMessage());

        }
        model.addAttribute("errorMap", errorMap);
        return "add";
    }
    System.out.println(result);
    employeeDao.save(employee);
    // Return to the list page
    return "redirect:/emps";
}
Copy the code

Restart Tomcat to add the Tomcat

A FieldError object is generated for each property in the event of a data binding and validation error. When a property fails validation, the validation framework generates four message codes for that property, prefixed by the validation annotation class name, Multiple corresponding message codes are generated by combining modelAttribute, attribute name, and attribute type name

The output error messages are in English, which can be configured to display error messages according to the language of the browser. When using Spring MVC, the Spring MVC will check whether the Web context is configured with an internationalization message, and display the internationalization message if so, and display the default message if not

Add internationalization configuration files error_zh_CN. Properties and error_en_us.properties in Chinese and English in the resources directory

Email.email=email wrong, retry
NotEmpty=can't be empty
Length.java.lang.String=length incorrect
Past=must be a past time
Copy the code
Email.email=\u90AE\u7BB1\u4E0D\u5BF9
NotEmpty=\u4E0D\u80FD\u4E3A\u7A7A
Length.java.lang.String= \u957F\u5EA6\u4E0D\u5BF9
Past=\u65F6\u95F4\u5FC5\u987B\u662F\u8FC7\u53BB\u7684
typeMismatch.birth=\u751F\u65E5\u7684\u683C\u5F0F\u4E0D\u6B63\u786E
Copy the code

Add internationalization configuration to the Spring MVC configuration file

<! -- Internationalization configuration -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename" value="error"></property>
</bean>
Copy the code

Restart Tomcat to add the Tomcat

How do I display incorrect field values in error messages?

Take the Internationalization profile in Chinese as an example

Email.email=\u90AE\u7BB1\u4E0D\u5BF9 - {0} 
NotEmpty=\u4E0D\u80FD\u4E3A\u7A7A - {0} 
Length.java.lang.String= \u957F\u5EA6\u4E0D\u5BF9 - {0} {1} {2}
Past=\u65F6\u95F4\u5FC5\u987B\u662F\u8FC7\u53BB\u7684 - {0}
typeMismatch.birth=\u751F\u65E5\u7684\u683C\u5F0F\u4E0D\u6B63\u786E - {0}
Copy the code
  • {0} : always represents the name of the property currently validated
  • {1} and {2} represent the values of the attributes set in the annotation, in alphabetical order

Restart Tomcat and perform the add operation