zoukankan      html  css  js  c++  java
  • 【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;
    
  • 相关阅读:
    Kinect 开发 —— 硬件设备解剖
    Kinect 开发 —— 引言
    (转)OpenCV 基本知识框架
    OpenCV —— 摄像机模型与标定
    OpenCV —— 跟踪与运动
    OpenCV —— 图像局部与分割(二)
    OpenCV —— 图像局部与部分分割(一)
    OpenCV —— 轮廓
    OpenCV —— 直方图与匹配
    OpenCV —— 图像变换
  • 原文地址:https://www.cnblogs.com/yickel/p/14500222.html
Copyright © 2011-2022 走看看