【2023】Introduction and use of @NotNull annotation and @NotBlank annotation in Spring Validation

Preface

Usually when we write code, we always need a lot of if tests to prevent many null pointer problems. like:

if(name!=null){
    
    
	return "账号不能为空,请重新输入";
}
else if(password!=null){
    
    
	return "密码不能为空,请重新输入";
}

This will look very low and very unsightly, but using the @NotNull annotation can directly implement verification through the annotation.

1. Introduction

Spring provides us with @NotNull, @NotEmpty and other annotations to achieve automatic verification of interface parameters.

Its implementation is mainly based on the specification JSR 303 (JSR (Java Specification Request) refers to a Java technical specification request submitted by one or more members of the Java community). The main goal of JSR 303 is to provide developers with
a A common mechanism for data validation in applications without writing extensive validation code. It defines a set of annotations and APIs for validating Java objects, which can be used to validate object properties, method parameters, return values, etc.

  • Annotations: JSR 303 defines a set of annotations for verification, such as @NotNull, @Size, @Pattern, @Min, @Max, etc. By adding these annotations on the properties of Java objects, you can specify validation conditions and constraints.
  • Common frameworks that use JSR 303 include Hibernate Validator, Spring Validationetc.

Early Spring Web Hibernate Validatorimplemented these verification specifications based on . In the later stage, Spring separated this part of the verification into a module spring-validation, and additional dependencies were required to implement related solution verification.

spring-validationCommon annotations for frameworks

annotation illustrate
@Null The annotated element must be null
@NotNull The annotated element cannot be null
@AssertTrue The annotated element must be true
@AssertFalse Annotated elements must be false
@Min(value) The annotated element must be a number whose value must be greater than or equal to the specified minimum value
@Max(value) The annotated element must be a number and its value must be less than or equal to the specified maximum value
@DecimalMin(value) The annotated element must be a number whose value must be greater than or equal to the specified minimum value
@DecimalMax(value) The annotated element must be a number and its value must be less than or equal to the specified maximum value
@Size(max,min) The size of the annotated element must be within the specified range
@Digits(integer,fraction) The annotated element must be a number and its value must be within an acceptable range
@Past The annotated element must be a past date
@Future The annotated element must be a future date
@Pattern(value) The annotated element must match the specified regular expression

Notice:

  • The following annotations can use the message attribute to return exception errors. like:@NotNull(message = "name不能为空")

  • When verifying request parameters, you need to add @Validor @Validatedannotate before the parameters that need to be verified in the controller method, otherwise the verification annotations in the Form will not work.

  • If the inner object needs to be verified, it needs to be added before the inner object @valid, so that it can be verified no matter how nested it is (including object generics).

The difference between @Valid and @Validated

  • @Valid: Can be used on methods, constructors, method parameters and member properties (fields)
  • @Validated: Can be used on types, methods and method parameters. However, it cannot be used on member attributes (fields), and @Validated provides a grouping function, which can use different verification mechanisms according to different groups when entering parameters for verification.

2. Code implementation

Add dependencies

Springboot 2.3.0 can be used directly before, but versions after 2.3.0 will not automatically introduce jar packages, so you need to add the following maven

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

1. Examples of entities

import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.Valid;
import javax.validation.constraints.*;
import java.util.Date;

@Data
public class User {
    
    
    @NotBlank(message = "姓名不能为空")
    private String name;

    @Max(value = 30,message = "姓名不能超过30岁")
    private Integer age;
    
    private Integer password;

    private String sex;

    @Past(message = "只能是过去的时间!")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date date;

    @Email(message = "邮箱格式错误")
    private String email;
    /**如果引用了其他的对象要想其他的对象的生效,需要在引用时加上注解*/
    @Valid
    private School school;
}

2. Controller layer:

import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;

/**
 * @author zhengfuping
 * @version 1.0
 * @description: TODO 测试 validation
 */
@RestController
@RequestMapping("/test")
public class TestController {
    
    
    
    /**
     * @Param * @param u 实例对象
     * @param result validation提供的异常处理类
     * @return * @return Object
     */
    @PostMapping("/save_user")
    @ResponseBody
    public Object saveUser(@Valid @RequestBody User u , BindingResult result) {
    
    
//        判断是否有异常,进行返回
        if (result.hasErrors()){
    
    
            FieldError fieldError = result.getFieldError();
            System.out.println(fieldError);
            return fieldError;
        }
//          没有异常打印日志返回
        System.out.println(u);
        return u;
    }
}

3. Unified exception handling

If you don’t want to write a judgment method in each Controller layer method, you can define a global exception class for unified processing.

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Objects;

/**
 * @author zhengfuping
 * @version 1.0
 * @description: TODO统一处理实体字段验证错误返回
 */
@ControllerAdvice
@Slf4j
public class ControllerException {
    
    
    
    @ResponseBody
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Object handleValidException(MethodArgumentNotValidException e){
    
    
        log.error(Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage());
//            正常开发会有统一返回对象
//         return Result.error(500, Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage());
        return e.getBindingResult().getFieldError().getDefaultMessage();
    }
}

After adding unified exception handling, the Controller code can be simplified to (rewritten for differentiation)

    @PostMapping("/save_user2")
    @ResponseBody
    public Object saveUser2(@Valid @RequestBody User u) {
    
    
        System.out.println(u);
        return "验证通过";
    }

4. Result return

Return after verification

Insert image description here

Return if verification fails

Insert image description here

Guess you like

Origin blog.csdn.net/weixin_52315708/article/details/132497204