前言

在开发中,为了代码的稳定性不报空指针异常,经常需要判断前端传过来的值是否为空,为空的话就返回前端值为空的提示,才能进行下一步的操作

Maven依赖的引入:

springboot 2.3.0 以后不会自动引入jar包,所以要添加以下maven
2.3以前则不需要引入maven包

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

常用注解@NotEmpty,@NotBlank,@NotNull介绍

包的位置:

import javax.validation.constraints.*;

@NotEmpty: 主要用在集合类上面
加了@NotEmpty的String类、Collection、Map、数组,是不能为null而且长度必须大于0(" ","  ")

(String Collection Map的isEmpty()方法)

@NotBlank: 只能用在String字符串类型上,而且调用trim()后,长度必须大于0(size>0)

@NotNull: 主要用在基本数据类型上(int,Integer,Double)不能为null,但可以为empty(""," ","  "),没有Size的约束

此包下的其他注解: (赶紧收藏!!!)

注解含义
@Null元素必须为null
@NotNull元素不能null
@AssertTrue元素必须为true
@AssertFalse元素必须是false
@Min(value)元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value)元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value)元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value)元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max,min)元素的大小必须在指定的范围内
@Digits(integer,fraction)元素必须是一个数字,其值必须在可接受的范围内
@Past元素必须是一个过去的日期
@Future元素必须是一个将来的日期
@Pattern(value)元素必须符合指定的正则表达式
@Email元素必须是电子邮箱地址
@Length字符串的大小必须在指定的范围内
@NotEmpty字符串必须非空
@Range元素必须在合理的范围内

搭配@Valid或者@Validated使用

@Valid、@Validated 注解可以实现数据的验证,你可以定义实体,在实体的属性上添加校验规则
校验规则如上@NotEmpty,@NotBlank,@NotNull等等的注解就是,不加上就不会生效!
@Valid 包位置:

import javax.validation.Valid;

@Validated 包位置:

import org.springframework.validation.annotation.Validated;

是@Valid 的一次封装,是Spring提供的校验机制使用。
相同点:

在检验Controller的入参是否符合规范时,使用@Validated或者@Valid都可以实现,并且需要传入BindingResult对象,用于获取校验失败情况下的反馈信息

不同点:2个方面如下

(1)、分组上:@Valid 不支持分组, @Validated则支持分组验证。

(2)、使用位置:

@Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上
@Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上

使用方法如下:

1.实体类需要判断的字段上面加上@NotEmpty注解,并且message配置提示语句

//实体类
@Data
public class CProject {
 
    @NotEmpty(message = "专案名称不能为空")
    private String projName;
 
    @NotEmpty(message = "专案类型不能为空")
    private String projType;
 
    private String projRes1;
 
    private String projRes2;
 
    private String creater;
 
    private Date gmtCreate;
}

 2.controller接口的方法参数加入@Valid注解,表示当前的实体类接收的参数需要根据配置的@NotEmpty注解判断

@PostMapping("saveProj")
	public String saveProj(@Valid @RequestBody CProject project,BindingResult results) {
		ResultVO rs=new ResultVO();
		if (results.hasErrors()) {
			rs.setCode(0);
			rs.setData(results.getFieldError().getDefaultMessage());
			rs.setMessage("请求参数异常");
		}else {
			projectService.SaveProj(project);
			rs.setCode(1);
			rs.setMessage("数据保存成功");
		}
		return ResultUtils.aesEncry(key,rs);
	}

问题又来了,难道我们每个Controller层的方法里面都要写一个判断方法?

当然不,这时候就要用到全局异常类了:GlobalExceptionHandler 

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler  {
 	
    @ExceptionHandler(BindException.class)
    public ErrorResult exceptionHandler(BindException e, HttpServletRequest request) {
 
        String failMsg = e.getBindingResult().getFieldError().getDefaultMessage();
        ErrorResult error = ErrorResult.fail(500, e, failMsg);
        log.error("URL:{} ,绑定异常:{} ", request.getRequestURI(),failMsg);
 
        return error;
    }
 
}

这样的话不需要写BindingResult 也可以返回message

@PostMapping("saveProjTest")
	public String saveProj(@Valid @RequestBody CProject project) {
 
		ResultVO rs=new ResultVO();
 
		projectService.SaveProj(project);
 
		rs.setCode(1);
		rs.setMessage("数据保存成功");
		
		return ResultUtils.aesEncry(key,rs);
	}

补充说明@Valid  @Validated验证

嵌套验证,必须手动在Person实体的son字段上明确指出这个字段里面的实体也要进行验证,代码如下:

class Person {
    @NotNull
    private Integer id;
 
    @NotNull
    /**
     * @Validated不允许使用在成员属性上,所以只能用@Valid
     * 如果不加  @Valid 就不会对 Son类进行校验,只会判断 @NotNull,List<Son>是否为空,并不会Son类里面的成员属性
     */
    @Valid //嵌套验证
    private List<Son> son;
}
 
class Son {
    @NotNull
    private Integer sid;
 
    @NotBlank(message = "姓名不能为空")
    private String name;
 
}
 
class MemberController {
 
    @ApiOperation(value = "会员注册")
    @PostMapping("register")
                              //使用@Validated或者@Valid都可以,这样就完成了嵌套验证
    public JSONResult register(@Validated @RequestBody Person person, BindingResult bindingResult){
 
        if (bindingResult.hasErrors()) {
            System.out.println(bindingResult.getFieldError().getDefaultMessage());
            return JSONResult.error().message(bindingResult.getFieldError().getDefaultMessage());
        }
        return JSONResult.ok();
    }
 
}