• 【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;
    
  • 相关阅读:
    jstat命令行工具监控JVM内存和垃圾回收
    SkyWalking 日志监控
    SkyWalking 数据持久化
    问题记录: java 19000101 08:05:43 时间偏移bug
    springboot jest链接es
    redisRedisLockRegistry 分布式锁
    es 索引别名
    springboot elasticsearchresthighlevelclient 连接es
    缓存穿透、缓存击穿和缓存雪崩 概念
    Navicat for MySQL 导出中文乱码问题
  • 原文地址:https://www.cnblogs.com/yickel/p/14500222.html
Copyright © 2020-2023  润新知