Blasting column - springboot2 X series of tutorials using InitBinder to handle the binding of request parameters

Posted by boombanguk on Mon, 27 Dec 2021 04:55:30 +0100

preface

When we develop the project, we need close cooperation between the front and rear ends to ensure the stability and efficiency of the project. The front end passes the request parameters to the back end through the URL interface, and the back end returns the corresponding response information according to these different request parameters. So what happens in the process of transmitting and returning response information? Can we do some intervention in this process? For example, if we want to add a student's age information, the front end passes a negative number as the age parameter, which is obviously illegal. Can the back end deal with this illegal parameter?

So today, I'll take you to learn some skills that can handle request parameters in SpringBoot to ensure that our back-end interface is more secure and robust.

I Spring MVC request parameter binding process

1. Request parameter binding process

When we are developing, we often pass the request parameters from html, jsp and other pages to the back end through the request object. However, it is often encountered that after the data parameters passed from the front end arrive at the back end, the data parameters need to be properly extracted, transformed and verified, and then assembled into objects of another format. This transformation can be completed by the @ InitBinder annotation provided by spring MVC.

2. Binding of request parameters in spring MVC

Spring MVC can automatically bind the request parameters in the request to each property attribute of the object, but it will only bind some simple data types (such as String, int, float, etc.) to the corresponding properties. However, if you are faced with complex objects, you need to use the interface PropertyEditor to complete data binding.

The PropertyEditor interface provides two methods: one is to convert the value of String type into the data type corresponding to property, and the other is to convert a property property property into String, as shown in the following figure:

3. CustomDateEditor inheritance relationship

Next, I will combine CustomDateEditor and InitBinder to explain how to format and verify the date type parameters passed from the front end. Let's first look at the structural relationship of the CustomDateEditor class, as shown in the following figure:

4. Example code

Here, I will first put a sample code to verify the format of the front-end date type parameter. Later, we will use this code to verify the date parameter passed in from the front-end.

@InitBinder
public void InitBinder(WebDataBinder binder) {
    //The time format passed in from the front end must be "yyyy MM DD" effect!
    DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
    CustomDateEditor dateEditor = new CustomDateEditor(df, true);
    binder.registerCustomEditor(Date.class, dateEditor);
}

II@ InitBinder details

Before starting today's content, let me introduce you to an @ InitBinder annotation.

1. Introduction to @ initbinder annotation

@The InitBinder annotation can be used on the method of @ Controller, which means that a property editor is registered for the current Controller to initialize WebDataBinder, and is only valid for the current Controller.

2. @InitBinder execution timing

@The InitBinder annotation is parsed before the method in which it is located is requested to execute. At the same time, the method of @ InitBinder annotation can be executed multiple times, that is, @ InitBinder resolution will be executed once for a request.

3. @InitBinder execution principle

After the first request on a Controller is matched to the Controller by the spring MVC front-end Controller, find all methods marked with @ InitBinder annotation according to the class type of the Controller and store them in the initBinderCache cache in the Request Mapping Handler Adapter. Before the next request to execute the corresponding business method, the initBinderCache cache will be used instead of parsing @ InitBinder.

III@ InitBinder implementation process

Next, we write a case to format and verify the date parameters passed from the front end.

First, let's create a Web program. Please refer to the previous case for the creation process, which is omitted here!

1. Create Controller test interface

In the created Web project, I create a Controller interface. The interface method can accept Date type parameters.

package com.yyg.boot.web;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.support.WebBindingInitializer;
import org.springframework.web.context.request.WebRequest;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description Description
 * @Author One brother Sun
 * @Date Created in 2020/3/23
 */
@Slf4j
@RestController
public class BindController {

    @GetMapping(value = "/bind")
    public Map<String, Object> getFormatData(Date date) throws ParseException {
        log.warn("date={}", date);
        Map<String, Object> map = new HashMap<>();
        map.put("name", "One brother");
        map.put("age", 30);
        map.put("date", date);
        return map;
    }

}

I also skipped the creation of the project entry class. You can create it yourself.

2. Start the program for testing

After starting the project, we can enter the following address in Postman for testing: http://localhost:8080/bind?date=2020-09-09

The effects in Postman are as follows:

After testing, it is found that the 400 status code is generated at this time. We know that the reason for the 400 status code is that the front and rear parameters are inconsistent. Specifically, the time String of String type passed from the front end cannot be converted to Date type! Because the front end does not have a Date type, the Date parameters passed by the front end can only be understood as a String type. By default, the Date data of this String type cannot be directly converted to a Date type.

How to solve this problem?

3. Add @ InitBinder code

Next, we add a new code to the Controller created above, as follows:

/**
     * @InitBinder The marked method is only valid for the current Controller!
     * If there is no such method, a 400 status code will be generated!
     * MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.util.Date!
     */
    @InitBinder
    public void InitBinder(WebDataBinder binder) {
        //The time format passed in from the front end must be "yyyy MM DD" effect!
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        CustomDateEditor dateEditor = new CustomDateEditor(df, true);
        binder.registerCustomEditor(Date.class, dateEditor);
    }

The complete Controller class is shown in the following figure:

4. Restart the project for testing

After adding the code, we restart the project, and then we re-enter the following address in Postman: http://localhost:8080/bind?date=2020-09-09

The test results of Postman are as follows:

It can be found that the time string passed from the front end is successfully passed to the back end and successfully converted to Date type! The above is the principle and usage of @ InitBinder!

Note: @ InitBinder is a Controller level Attribute Editor, not a global level Attribute Editor (for all @ controllers), that is, a @ InitBinder is only valid for the current Controller, but not for other controllers! What if there are multiple controllers in our project that need date format conversion? Please think about it first.

5. Project structure diagram

The final code structure is shown in the figure below. You can create it for reference.

If you need more tutorials, just scan the code on wechat

 

👆👆👆

Don't forget to scan the code to get the information [HD Java learning roadmap]

And [full set of learning videos and supporting materials of various disciplines]

 

 

Topics: Java Front-end Spring Boot