JSR303 - Data Verification & unified response data format

Keywords: Java Spring Spring Boot

1. Introduction to jsr303

  • It is applicable to data verification on the server side
  • Java provides a standard framework for Bean data validity verification  
  • Spring MVC supports the verification framework of JSR 303 standard  
  • JSR 303 specifies the verification rules by marking the verification annotation on the Bean attribute
  • Spring itself does not provide the implementation of JSR 303. It is implemented by Hibernate Validator and integrated with spring

two   Common annotations related to JSR303

  • @Null(message): the annotated element must be null
  • @NotNull(message): the annotated element must not be null
  • @AssertTrue(message): the annotated element must be true
  • @Assert false (message): the annotated element must be false
  • @Min(value,message): the annotated element must be a number, and its value must be greater than or equal to the specified minimum value
  • @Max(value,message): the annotated element must be a number, and its value must be less than or equal to the specified maximum value
  • @Decimal min (value, message): the annotated element must be a number, and its value must be greater than or equal to the specified minimum value
  • @DecimalMax(value,message): the annotated element must be a number, and its value must be less than or equal to the specified maximum value
  • @Size(max, min,message): the size of the annotated element must be within the specified range
  • @Digits (integer, fraction,message): the annotated element must be a number and its value must be within an acceptable range
  • @Past(message): the annotated element must be a past date
  • @Future (message): the annotated element must be a future date
  • @Pattern(regexp = "regular expression", message)
  • @The annotated element of Email must be an Email address
  • @Length(max=5,min=1,message = "length in 1 ~ 5")    Check whether the length of the field is between min and Max, which can only be used for string
  • @Range   The annotated element must be within the appropriate range  
  • @CreditCardNumber   Make a general verification of the credit card number
  • @NotBlank   Cannot be empty. Spaces will be ignored during inspection
  • @NotEmpty   Cannot be null. Null here refers to an empty string
  • Attribute: message = "verification prompt"

3. Development steps

         01. Introduce related dependencies (the springboot version will be used by default when the version number is not written)

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

        02. Use annotation: add corresponding verification annotation to the attribute to be verified

    @NotNull(message = "User name cannot be empty")
	private String userName; //User name

	@Pattern(regexp = "^[a-zA-Z0-9]{6,8}$",message = "Password must be 6-8 A combination of digits and letters")
	private String userPassword; //User password

	@Past(message = "Birthdays can only be past dates")
	private Date birthday;  //date of birth

	@Min(value = 1, message = "The minimum age is 1")
	@Max(value = 120, message = "Age Max 120")
	private Integer age;

         03. Use the @ Valid annotation before the business method parameter list in the controller layer, and add the BindingResult parameter to the parameter value

         If there is no BindingResult parameter, spring will encounter an exception when the verification fails

    @PostMapping("/login2")
    public ReturnResult login2(@Valid @RequestBody User user, BindingResult result){
        . . . 
    }

         04. Common methods of bindingresult (verification result object):

  • hasFieldErrors("property name"): judge whether the corresponding property complies with the verification. The returned Boolean values are: true
  • hasErrors(): judge whether there are errors in the verification of all attributes using verification, and the returned Boolean values are: true
  • getFieldError("property name"): get the property object with error and return the FieldError type
  • fieldError.getDefaultMessage(): get the message prompt information of the error property object and return String type
  • SfieldError.getField(): get the property name of the error property object; return String type
  • getFieldErrors(): get all property objects that do not conform to validation, and return the type of list < fielderrors >

Code demonstration:

@PostMapping("/login2")
    public ReturnResult login2(@Valid @RequestBody User user, BindingResult result){
        ReturnResult returnResult=null;
        Map<String,Object> map = new HashMap<>();
        //Determine whether birthday is wrong
        System.out.println(result.hasFieldErrors("birthday"));
        //Determine whether the userPassword is wrong
        System.out.println(result.hasFieldErrors("userPassword"));
        //Judge whether there is a mistake
        if(result.hasErrors()){
            //Get all errors
            result.getFieldErrors().forEach((item)->{
                //Get error information
                String message = item.getDefaultMessage();
                //Get wrong property name
                String field = item.getField();
                map.put(field,message);
            });
        }
        return map;
    }

4. Encapsulate a unified return data format: returnresult < T >

         01. Create returnresult < T > class: a unified format class that interacts with the front end

package com.ck.vo;
import java.io.Serializable;
/***
 * created by lxl
 *  As long as this class will be used for data transfer (front end < - > back end)
 * Unified format for interaction with front-end interface
 */
public class ReturnResult<T> implements Serializable{

    //The user query is correct: {code: 200, message: the operation is successful, data: {user information}}
    //User query error: {code: 500, message: backend server error, data: null}

    //Status code customization
    private Integer code;
    //Prompt information
    private String message;
    //Return data
    private T data;

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

         02. Create ReturnResultUtils unified return tool class

package com.ck.vo;

/***
 * created by lxl
 *
 * Unified return tool class
 */
public class ReturnResultUtils{

    /***
     * Success without data
     * @return
     */
    public static ReturnResult returnSuccess(Integer code,String message){
        ReturnResult returnResult=new ReturnResult();
        returnResult.setCode(code);
        returnResult.setMessage(message);
        return returnResult;
    }
    /***
     * Successfully bring data
     * @return
     */
    public static ReturnResult returnSuccess(Integer code,String message,Object data){
        ReturnResult returnResult=new ReturnResult();
        returnResult.setCode(code);
        returnResult.setMessage(message);
        returnResult.setData(data);
        return returnResult;
    }
    /***
     * Failed without data
     * @return
     */
    public static ReturnResult returnFail(Integer code,String message){
        ReturnResult returnResult=new ReturnResult();
        returnResult.setCode(code);
        returnResult.setMessage(message);
        return returnResult;
    }

    /***
     * Failed with data
     * @return
     */
    public static ReturnResult returnFail(Integer code,String message,Object data){
        ReturnResult returnResult=new ReturnResult();
        returnResult.setCode(code);
        returnResult.setMessage(message);
        returnResult.setData(data);
        return returnResult;
    }
}

        03. Modify the return value of controller

    @PostMapping("/login2")
    public ReturnResult login2(@Valid @RequestBody User user, BindingResult result){
        ReturnResult returnResult=null;
        Map<String,Object> map = new HashMap<>();
        //Determine whether birthday is wrong
        System.out.println(result.hasFieldErrors("birthday"));
        //Determine whether the userPassword is wrong
        System.out.println(result.hasFieldErrors("userPassword"));
        //Judge whether there is a mistake
        if(result.hasErrors()){
            //Get all errors
            result.getFieldErrors().forEach((item)->{
                //Get error information
                String message = item.getDefaultMessage();
                //Get wrong property name
                String field = item.getField();
                map.put(field,message);
            });
            //Using the method with parameters, pass in the obtained verification error information map and respond to the front end
            returnResult= ReturnResultUtils.returnFail(500,"operation failed",map);
        }else{
            returnResult = ReturnResultUtils.returnSuccess(200,"Operation succeeded");
        }
        //Return returnResult unified format class
        return returnResult;
    }

Posted by mancroft on Thu, 09 Sep 2021 21:57:23 -0700