@Valid注解

@Valid 注解通常用于对象属性字段的规则检测

 


 

下面我们以新增一个员工为功能切入点,以常规写法为背景,慢慢烘托出 @Valid 注解用法详解。

那么,首先,我们会有一个员工对象 Employee,如下 :

 1 public class Employee {
 2  
 3     /** 姓名 */
 4     public String name;
 5  
 6     /** 年龄 */
 7     public Integer age;
 8  
 9     public String getName() {
10         return name;
11     }
12  
13     public void setName(String name) {
14         this.name = name;
15     }
16  
17     public Integer getAge() {
18         return age;
19     }
20  
21     public void setAge(Integer age) {
22         this.age = age;
23     }
24  
25 }

然后 Cotroller 中会有一个对应都新增方法 add(),如下:

 1 @Controller
 2 public class TestController {
 3  
 4     @RequestMapping("/add")
 5     @ResponseBody
 6     public String add(Employee employee) {
 7         // TODO 保存到数据库
 8         return "新增员工成功";
 9     }
10 }

现在要求:员工的名称不能为空,且长度不能超过10个字符,那么我们以前的做法大致如下:

 1 @Controller
 2 public class ValidTest {
 3     @RequestMapping("/add")
 4     @ResponseBody
 5     public String add(Employee employee) {
 6         String name = employee.getName();
 7         if(name == null || name.trim().length() == 0){
 8             return "员工名称不能为空";
 9         }
10         if(name.trim().length()>10){
11             return "员工名称长度不能超过10";
12         }
13         return "新增员工成功";
14     }
15 }

除了名称外,我们规定年龄也是必填项,且范围在1到100岁,那么此时,我们需要增加对应判定代码如下:

 1 @Controller
 2 public class ValidTest {
 3     @RequestMapping("/add")
 4     @ResponseBody
 5     public String add(Employee employee) {
 6         String name = employee.getName();
 7         if(name == null || name.trim().length() == 0){
 8             return "员工名称不能为空";
 9         }
10         if(name.trim().length()>10){
11             return "员工名称长度不能超过10";
12         }
13         Integer age = employee.getAge();
14         if(age == null){
15             return "员工年龄不能为空";
16         }
17         if(age<1 || age>100){
18             return "员工年龄范围不对";
19         }
20         return "新增员工成功";
21     }
22 }

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

那么如何解决呢?首先大家应该会想到将对应的验证过程抽成一个验证方法,如下:

这样来看,我们的业务方法就清爽多了。

@Controller
public class ValidTest {
    @RequestMapping("/add")
    @ResponseBody
    public String add(Employee employee) {
        if(valid(employee) != null){
            return "Error";
        }
        return "新增员工成功";
    }

    private String valid(Employee employee){
        String name = employee.getName();
        if(name == null || name.trim().length() == 0){
            return "员工名称不能为空";
        }
        if(name.trim().length()>10){
            return "员工名称长度不能超过10";
        }
        Integer age = employee.getAge();
        if(age == null){
            return "员工年龄不能为空";
        }
        if(age<1 || age>100){
            return "员工年龄范围不对";
        }
        return null;
    }
}

但这种方式只是抽了一个方法,有一种换汤不换药的感觉,虽然业务方法看起来清爽了很多,但书写代码量并没有下降,反而还多出了一个方法,这也不是我们理想中的样子。

此时,我们引出 Spring 中的 @valid 注解,这些问题就可以迎刃而解了,具体如下:

首先,我们在 Maven 配置中引入 @valid 的依赖:

如果你是 springboot 项目,那么可以不用引入了,已经引入了,他就存在于最核心的 web 开发包里面。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.0.5.RELEASE</version>
</dependency>

如果你不是 springboot 项目,那么引入下面依赖即可:

<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>

那么针对上面情景,我们可以对我们的代码进行优化了。

首先我们在 Employee 类的属性上打上如下注解:

 1 public class Employee {
 2 
 3     /** 姓名 */
 4     @NotBlank(message = "请输入名称")
 5     @Length(message = "名称不能超过个 {max} 字符", max = 10)
 6     public String name;
 7 
 8     /** 年龄 */
 9     @NotNull(message = "请输入年龄")
10     @Range(message = "年龄范围为 {min} 到 {max} 之间", min = 1, max = 100)
11     public Integer age;
12 
13     public String getName() {
14         return name;
15     }
16 
17     public void setName(String name) {
18         this.name = name;
19     }
20 
21     public Integer getAge() {
22         return age;
23     }
24 
25     public void setAge(Integer age) {
26         this.age = age;
27     }
28 }

然后再 Controller 对应方法上,对这个员工标上 @Valid 注解,表示我们对这个对象属性需要进行验证,

1 @Controller
2 public class ValidTest {
3     @RequestMapping("/add")
4     @ResponseBody
5     public String add(@Valid Employee employee) {
6         return "新增员工成功";
7     }
8 }

既然验证,那么就肯定会有验证结果,所以我们需要用一个东西来存放验证结果,做法也很简单,在参数直接添加一个BindingResult,具体如下:

 

@Controller
public class ValidTest {
    @RequestMapping("/add")
    @ResponseBody
    public String add(@Valid Employee employee, BindingResult bindingResult) {
        if(bindingResult.hasErrors()){
            return bindingResult.getAllErrors().get(0).getDefaultMessage();
        }
        return "新增员工成功";
    }
}

 

posted @ 2022-04-11 17:56  r1-12king  阅读(693)  评论(0编辑  收藏  举报