preface

In the process of our actual project development, it is unavoidable to check the parameters. The check of general parameters can be divided into the following situations. 1. Front-end direct verification; 2. Verify separately at the Controller layer; 3. Verification through the integration verification framework; Obviously, among the three methods, we generally suggest that the combination of 1+3 is more reasonable and safe for parameter verification. In this chapter we will focus on the application of parameter validation in HTTP requests

Several ways to receive parameters for a Controller

Before introducing the validation framework, let’s look at the way parameters are received through Controller; At present, most parameters are received through annotations. The mainstream ones are as follows

Request path parameter

  • @pathvariable Gets path parameters. Url /{id}.
  • RequestParam retrieves query parameters. The url? Name = of the form

The code form is as follows:

GET http://localhost:8080/demo/SN20201011021211? name=hank

The corresponding receiving code is as follows:

@GetMapping("/demo/{sn}")
public void demo(@PathVariable(name = "sn") String sn, @RequestParam(name = "name") String name) {
    System.out.println("sn="+sn);
    System.out.println("name="+name);
}
Copy the code

Body parameters

The Body argument is typically a POST request in two main ways

  • Received in JSON format, the corresponding parameters can be obtained via @requestBody
  • Submitted in form form, no annotation adaptation, can be directly received by the object

JSON parameter reception

For example, to add a user interface,PostMan requests the following information

Corresponding to back-end code 1, received via Map

@PostMapping(value = "/user/map")
public ResultVO createUser(@RequestBody Map<String,Object> user){
    String name=user.get("name").toString();
    return RV.success(user);
}
Copy the code

Corresponding descendant code 2 receives through the defined object

@PostMapping(value = "/user")
public ResultVO createUser2(@RequestBody User user){
    System.out.println("User Info:"+user.toString());
    return RV.success(user);
}
Copy the code

FORM parameter receiving

In form mode, the corresponding parameters in PostMan are as follows

The corresponding back-end code is as follows:

@PostMapping(value = "/user/form")
public ResultVO createUser3(User user){
    System.out.println("User Info:"+user.toString());
    return RV.success(user);
}
Copy the code

Request header and Cookie parameters

  • @requesTheader gets the Header parameters directly from the HttpServletRequest object
  • @Cookievalue can directly retrieve parameters from the Cookies in the HttpServletRequest object

Obtained by means of annotations as follows

@GetMapping("demo3")
public void demo3(@RequestHeader(name = "myHeader") String myHeader,
        @CookieValue(name = "myCookie") String myCookie) {
    System.out.println("myHeader=" + myHeader);
    System.out.println("myCookie=" + myCookie);
}
Copy the code

The method of obtaining by hard coding is

@GetMapping("/demo3")
public void demo3(HttpServletRequest request) {
    System.out.println(request.getHeader("myHeader"));
    for (Cookie cookie : request.getCookies()) {
        if ("myCookie".equals(cookie.getName())) { System.out.println(cookie.getValue()); }}}Copy the code

As can be seen from the above, annotations can greatly simplify coding and make our code beautiful and elegant. It can also be obtained directly from the Request object. This mainly depends on what kind of requirements we have. Therefore, we prefer to get parameters directly through annotations in projects.

File upload

File uploads are based on @requestParam combined with MultipartFile objects; The following is an example;

Note that the incoming front-end needs to be submitted as a form and added to the content-Type of the Head with the following information

Content-Type: application/x-www-form-urlencoded
Copy the code

The corresponding back-end code is as follows

@Value("${file.upload.url}")
private String filePath;

@RequestMapping("/upload")
public ResultVO httpUpload(@RequestParam("files") MultipartFile files[]){
    for(int i=0; i<files.length; i++){ String fileName = files[i].getOriginalFilename();/ / file name
        File dest = new File(filePath+'/'+fileName);
        if(! dest.getParentFile().exists()) { dest.getParentFile().mkdirs(); }try {
            files[i].transferTo(dest);
        } catch (Exception e) {
            log.error("{}",e);
            returnRV.result(ErrorCode.UPLOAD_FILE_ERROR,e); }}return RV.success(null);
}
Copy the code

Parameter calibration

JSR stands for Java Specification Requests, which stands for Java Specification proposals. The latest update to data Validation is JSR380, also known as Bean Validation 2.0. Bean Validation 2.0 is JSR Standard no. 380. The standard connection is as follows: www.jcp.org/en/egc/view… Bean Validation can be performed at github.com/hibernate/h…

Parameter verification at the Controller layer can be divided into two scenarios: single parameter verification and entity parameter verification

Single parameter check

Introduction of depend on

<dependency>
  <groupId>jakarta.validation</groupId>
  <artifactId>jakarta.validation-api</artifactId>
</dependency>
Copy the code

The back-end code is as follows

@RestController
@Validated
public class ValidateController {

    @GetMapping("/getUser")
    public ResultVO getUserStr(@notnull (message = "name cannot be empty ") String name,
                               @max (value = 99, message = "cannot be older than 99 ") Integer age) {
        return RV.success("name: " + name + " ,age:"+ age); }}Copy the code

In the Postman request below, you can see that the request returns a system exception, which should be intercepted by a global exception

Let’s look at the logs printed in the background

If there are many places in our system are used to parameter calibration, so we had better be able to in the global intercept in direct interception ConstraintViolationException anomaly, and unified processing, can be in the previous section we talked about, Add the following intercepting new methods to the GlobalException class annotated with @RestControllerAdvice; Because ConstraintViolationException inherited the thrown exception classes, so we can intercept the superclass abnormal directly, directly for a number of different check exception processing

@RestControllerAdvice
public class GlobalException {

    /** * Description: Form exception blocking *@param [e]
     * @date 2020/11/22
     * @Author Hank
     **/
    @ExceptionHandler(value = ValidationException.class)
    public  ResultVO validationException(ValidationException e){
        Map map=new HashMap();
        if(e instanceofConstraintViolationException){ ConstraintViolationException exs = (ConstraintViolationException) e; Set<ConstraintViolation<? >> violations = exs.getConstraintViolations();for(ConstraintViolation<? > item : violations) {// Prints the information that does not pass the verificationSystem.out.println(item.getMessage()); map.put(item.getPropertyPath(),item.getMessage()); }}returnRV.result(ErrorCode.FORM_VALIDATION_ERROR,map) ; }}Copy the code

Similarly, after a Postman request, the following result is obtained

Entity parameter check

In general, we pass in fewer parameters, we directly use the above method to verify, but if we pass in an object, it is a little ugly to directly set the properties on the method, so we generally encapsulate an object that receives parameters. To add a user interface, as provided in the example below, we set the validation rules for the variables of the user object as follows

@Data
class Person {
    @notnull (message = "name cannot be empty ")
    @max (value = 30, message = "name cannot exceed 30 characters ")
    String name;
    @max (value = 200, message = "can't be over 200 ")
    @notnull (message = "Age cannot be empty ")
    Integer age;
    @notnull (message = "Address message cannot be empty ")
    String address;
}
Copy the code

In the Controller class, we add a method to add users. Note that we just need to add the @valid annotation to the Person object corresponding to the method

    /** * Description: Add a Person *@param [person]
     * @date 2020/11/22
     * @Author Hank
     **/
    @PostMapping(value = "/person")
    public ResultVO<Person> addPerson(@RequestBody @Valid Person person) {
        // Skip the business code here...
        return RV.success(person);
    }
Copy the code

In fact, you might say, well, what kind of exception should be thrown if the parameter check is different, so when we run the code like this and set the parameter out of range, we can see the exception on the back end like this

As you can see, here is thrown MethodArgumentNotValidException very different from the above abnormal; The same reason, I’m still in GlobalException class to add to the abnormal MethodArgumentNotValidException global intercept

    /** * Description: Method parameter verification exception interception *@param [e]
     * @date 2020/11/22
     * @Author Hank
     **/
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public  ResultVO methodArgumentNotValidException(MethodArgumentNotValidException e){
        List<ObjectError> errors = e.getBindingResult().getAllErrors();
        String[] errMessage=new String[errors.size()];
        for (int i = 0; i < errors.size(); i++) {
            ObjectError error=errors.get(i);
            errMessage[i]=error.getDefaultMessage();
            System.out.println(error.getCode()+":"+error.getDefaultMessage());
        }
        return RV.result(ErrorCode.METHOD_ARGS_VALID_ERROR,errMessage) ;
    }
Copy the code

Validated is different from Valid

  • @Validated: The nested verification function cannot be provided separately for method inputs. Cannot be used on member attributes (fields), nor can it prompt the framework for nested validation. Can be nested with the @valid annotation for nested validation.
  • Valid: cannot provide nested validation on method input arguments alone. Can be used on member attributes (fields) to prompt the validation framework for nested validation. Can be nested with the @valid annotation for nested validation.

If there is another object inside the Person object, such as Person, and you need this nested validation during the submission process, you need to use Valid nested validation to modify the code as follows:

@Data
class Person {
    @notnull (message = "name cannot be empty ")
    @size (min = 2, Max = 30, message = "name length is limited between 2 and 30 ")
    String name;
    @max (value = 200, message = "can't be over 200 ")
    @notnull (message = "Age cannot be empty ")
    Integer age;
    @notnull (message = "Address message cannot be empty ")
    String address;
    @Valid
    Person p;
}
Copy the code

Annotations for checking common parameters

Here we mainly introduce several parameter verification methods in Springboot. Common comments for parameter verification are as follows:

  • The element annotated by @AssertFalse must be of Boolean type and value false
  • The annotated element @assertTrue must be of Boolean type and have a value of true
  • The annotated element @decimalmax must be a number with a value less than or equal to the given value
  • The annotated element @decimalmin must be a number with a value greater than or equal to the given value
  • The annotated element at @digits must be a number, and the value must be the specified number of Digits
  • The annotated element @future must be a Future date
  • The element annotated by @max must be a number with a value less than or equal to the given value
  • The element annotated by @min must be a number with a value less than or equal to the given value
  • The annotated element at @range must be within the specified Range
  • @notnull the annotated element value cannot be null
  • The annotated element value @notblank has content
  • @null The annotated element value is Null
  • The annotated element @past must be a date in the Past
  • The annotated element @pastorpresent must be a PastOrPresent date
  • The element annotated by @pattern must satisfy the given regular expression
  • The element annotated by @size must be a String, collection, or array, and the Size must be within a given range
  • @email annotated elements must meet the Email format

summary

This chapter mainly focuses on two aspects of the content of a detailed introduction

  • Parameter receiving mode of Controller
  • Request path parameter
  • Body arguments (JSON\FORM\ request header and Cookie arguments)
  • File upload
  • Verification of parameters
  • Single parameter check
  • Entity parameter check
  • Verification of nested parameters and the difference between Validated and Valid

The above examples are described in detail, hoping to be helpful to your later development work; If you have different experience in this field, feel free to leave a comment in the comments section.

Refer to the article

Blog.csdn.net/w57685321/a…

JSR specification reference blog.csdn.net/choushi9178…