【SpringBoot】-@valid、@NotBlank、@NotEmpty、@NotNull注解使用场景及差别

一、什么时候使用@NotBlank注解

来源:https://blog.csdn.net/sunnyzyq/article/details/103527380
在Spring项目中,微服务之间常采用Restful接口。那么问题来了,当前段调用后端接口,或者后端微服务接口被其它微服务调用时,我们不可能只依赖接口调用方对参数准确性进行检查,接口提供方也需要在入口对参数准确进行检查。

如:接口中关键参数是个一个员工对象Employee为例,员工对象实体类定义如下:

public class Employee {
     /** 姓名 */
    public String name; 
    /** 年龄 */
    public Integer age;
 
    public String getName() {
        return name;
    } 
    public void setName(String name) {
        this.name = name;
    } 
    public Integer getAge() {
        return age;
    }
 
    public void setAge(Integer age) {
        this.age = age;
    }
 }

Contoller中定义一个增加员工的add接口,如下:

@Controller
public class TestController {
    @RequestMapping("/add")
    @ResponseBody
    public String add(Employee employee) {
        //TODO 保存到数据库
        return "新增员工成功";
    } 
}

现在,我们需要对接口参数进行检查,需员工的名称不能为空、且长度不超过10个字符,如何做呢?Controller中增加判断如下:

@Controller
public class TestController {
    @RequestMapping("/add")
    @ResponseBody
    public String add(Employee employee) {
        String name =  employee.getName();
        if(name == Null || name.trim().length() == 0) {
           return "员工名称不能为空";
        }
        if(name.trim().length() > 0) {
           return "员工名称不能超过10个字符";
        }

        //TODO 保存到数据库
        return "新增员工成功";
    } 
}

运行测试,可以发现检查结果符合预期。

现在,我们又需要增加对员工年龄的限制,必须在20~50岁。怎么办呢?继续在Controller中添加判断:

@Controller
public class TestController {
    @RequestMapping("/add")
    @ResponseBody
    public String add(Employee employee) {
        String name =  employee.getName();
        if(name == Null || name.trim().length() == 0) {
           return "员工名称不能为空";
        }
        if(name.trim().length() > 0) {
           return "员工名称不能超过10个字符";
        }

        Integer age = employee.getAge();
       if(age == Null) {
           return "员工年龄不能为空";
        }
        if(age < 20 || age > 50) {
           return "员工年龄不能小于20或大于50";
        }

        //TODO 保存到数据库
        return "新增员工成功";
    } 
}

那么问题来了,现在员工对象Employee就2个字段,我们就写了10多行的代码验证,要是有20个字段,岂不是要写100多行代码?通常来说,当一个方法中的无效业务代码量过多时,往往代码设计有问题,当然这不是我们所想看到都结果。
有人会说,把对应的校验过程抽象成独立的验证方法吧:

@Controller
public class TestController {
    @RequestMapping("/add")
    @ResponseBody
    public String add(Employee employee) {
        String result = vaild(employee);
        if(result != Null) {
           return result ;
        }

        //TODO 保存到数据库
        return "新增员工成功";
    } 
}

String valid(Employee employee) {
    String name =  employee.getName();
    if(name == Null || name.trim().length() == 0) {
       return "员工名称不能为空";
    }
    if(name.trim().length() > 0) {
       return "员工名称不能超过10个字符";
    }

    Integer age = employee.getAge();
    if(age == Null) {
        return "员工年龄不能为空";
    }
    if(age < 20 || age > 50) {
       return "员工年龄不能小于20或大于50";
    }

    return null;
}

这样来看,我们的Controller业务方法就清爽多了。但本质上编码量没有减少,只是换了位置封装。

Spring提供的@NotBlank、@valid很好实现如上消息valid检查

  1. 使用@valid首先要要引入其依赖
  • 如果是SpringBoot项目,引入web开发包,就不需要再单独引入@valid依赖了、因为他存在于Web开发包中的最核心之中
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency>
  • 如果不是SpringBoot项目,要在Maven的Pom中显式引入@valid依赖,如下:
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.1.0.Final</version>
</dependency>
 
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.4.1.Final</version>
</dependency>
  1. 引入依赖后,如何使用呢?
  • 在Employee实体类上加上注解:

public class Employee {
    /** 姓名 */
    @NotBlank(message = "请输入名称")
    @Length(message = "名称不能超过个 {max} 字符", max = 10)
    public String name;
 
    /** 年龄 */
    @NotNull(message = "请输入年龄")
    @Range(message = "年龄范围为 {min} 到 {max} 之间", min = 1, max = 100)
    public Integer age;
 
    public String getName() {
        return name;
    } 
    public void setName(String name) {
        this.name = name;
    } 
    public Integer getAge() {
        return age;
    } 
    public void setAge(Integer age) {
        this.age = age;
    }
}
  • 在Controller对应的参数上,加上@valid注解,如下:
public class TestController {
    @RequestMapping("/add")
    @ResponseBody
    public String add(@valid Employee employee) {
        //TODO 保存到数据库
        return "新增员工成功";
    } 
}

此时,Controller方法就会对@valid注解的参数 根据 类中的@NotBlank等注解进行检查,检查失败,返回注解中message指定的消息。效果与前面自己写代码检查一致。

【注】:@NotBlank等注解时,一定要和@valid一起使用,不然@NotBlank不起作用。

  • 既然对参数进行了检查,就肯定会有检查结果。如果我们需要用一个东西来存放验证结果,做法也很简单,在参数直接添加一个BindingResult。如下:
public class TestController {
    @RequestMapping("/add")
    @ResponseBody
    public String add(@valid Employee employee, BindingResult bindingResult) {
        //TODO 保存到数据库
        return "新增员工成功";
    } 
}

*如果想获取保存的验证结果,样例如下:

public class TestController {
    @RequestMapping("/add")
    @ResponseBody
    public String add(@valid Employee employee, BindingResult bindingResult) {
        //检查所有字段是否验证通过
        if(bindingResult.hasErrors()) {
             //验证失败,返回第一条错误信息
             return bindingResult.getALLErrors().get(0).getDefaultMessage();
        }

        //TODO 保存到数据库
        return "新增员工成功";
    } 
}

二、类似@NotBlank使用方式的注解

@NotNull:不能为null,但可以为empty
@NotEmpty:不能为null,而且长度必须大于0
@NotBlank:只能作用在String上,不能为null,而且调用trim()后,长度必须大于0。(trim()删除字符串的头尾空白符)
样例辅助理解:

1.String name = null;则注解检查结果:
@NotNull: false
@NotEmpty:false 
@NotBlank:false 

2.String name = "";则注解检查结果:
@NotNull:true
@NotEmpty: false
@NotBlank: false

3.String name = " ";则注解检查结果:
@NotNull: true
@NotEmpty: true
@NotBlank: false

4.String name = "Great answer!";则注解检查结果:
@NotNull: true
@NotEmpty:true
@NotBlank:true

其他注解:

    @Length(message = "名称不能超过个 {max} 字符", max = 10)
    public String name;
 
    /** 年龄 */
    @Range(message = "年龄范围为 {min} 到 {max} 之间",min = 1,max = 100)
    public Integer age;

    @Size(message = "兴趣最多选择{max}个", max = 5)
    private List<String> hobbyList;
posted @ 2021-03-08 16:04  小拙  阅读(7412)  评论(0编辑  收藏  举报