首页 > 其他分享 >@Valid 和 @Validated 注解用法详解

@Valid 和 @Validated 注解用法详解

时间:2023-02-14 10:56:08浏览次数:44  
标签:校验 我们 Valid 注解 Validated public 详解

案例引入

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

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

 1 /**
 2  * 员工对象
 3  * 
 4  * @author sunnyzyq
 5  * @since 2019/12/13
 6  */
 7 public class Employee {
 8  
 9     /** 姓名 */
10     public String name;
11  
12     /** 年龄 */
13     public Integer age;
14  
15     public String getName() {
16         return name;
17     }
18  
19     public void setName(String name) {
20         this.name = name;
21     }
22  
23     public Integer getAge() {
24         return age;
25     }
26  
27     public void setAge(Integer age) {
28         this.age = age;
29     }
30  
31 }

然后 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  
11 }

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

 

 

 

写完,我们启动项目测试下:

 

(1)名称为空情况

 

 

 

(2)正常情况

 

 

 

(3)超过长度情况

 

 

 

可以看到,和我们料想中的一样,毫无问题。

 

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

 

 

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

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

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

 

 

 

 

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

 

@Valid 详解
此时,我们引出 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 package com.zyq.beans;
 2  
 3 import javax.validation.constraints.NotBlank;
 4 import javax.validation.constraints.NotNull;
 5  
 6 import org.hibernate.validator.constraints.Length;
 7 import org.hibernate.validator.constraints.Range;
 8  
 9 /**
10  * 员工对象
11  * 
12  * @author sunnyzyq
13  * @since 2019/12/13
14  */
15 public class Employee {
16  
17     /** 姓名 */
18     @NotBlank(message = "请输入名称")
19     @Length(message = "名称不能超过个 {max} 字符", max = 10)
20     public String name;
21  
22     /** 年龄 */
23     @NotNull(message = "请输入年龄")
24     @Range(message = "年龄范围为 {min} 到 {max} 之间", min = 1, max = 100)
25     public Integer age;
26  
27     public String getName() {
28         return name;
29     }
30  
31     public void setName(String name) {
32         this.name = name;
33     }
34  
35     public Integer getAge() {
36         return age;
37     }
38  
39     public void setAge(Integer age) {
40         this.age = age;
41     }
42  
43 }

 

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

 

 

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

 

 

 

对应获取验证结果的代码如下:

 

 

 

OK ! 万事俱备 !我们进行测试下:

 

(1)名称为空

 

 

 

(2)名称正常,年龄为空

 

 

 

(3)名称超出范围,年龄正常

 

 

 

(4)名称正常,年龄超出范围

 

 

 

可以看到,代码不但简洁了很多,结果和预期的也一模一样!很棒吧!!

 

常用注解:

除了刚刚都注解,最后再附加2个常用注解,我就直接贴图了,基本上这6个注解可以解决99%的字段,其他注解我就不贴图了,如果不满足,自己问百度。

 

 

 

@Validated 详解
上面,我们讲述了 @Valid 注解,现在我们来说说 @Validated 这个注解,在我看来,@Validated 是在 @Valid 基础上,做的一个升级版。

我们可以看到,我们在使用 @Valid 进行验证的时候,我们需要用一个对象去接收校验结果,最后根据校验结果判断,从而提示用户。

 

 

如果我们把手动校验的这段代码删除或注释掉,那么即使当我们的字段不满足规则时,方法种的程序也是能够被执行的。

比如,我们将字段值置空时,正常情况是会进行提示的。

 

 

 当我们把校验逻辑注释掉后,再次执行上面的请求后。

 

 

 

可以看到我们的程序继续往后面去执行完成了。 

 

 

 

现在,我们去掉方法参数上的 @Valid 注解和其配对的 BindingResult 对象,

然后再校验的对象前面添加上 @Validated 注解。

 

 

 

这个时候,我们再次请求,可以看到,我们请求报400错误了。

 

 

 

而我们通过程序的异常日志来看,提示说是 age 和 name 字段为了空,致使请求失败。

 

 

 

 

 

那么,从这里我们可以得知,当我们的数据存在校验不通过的时候,程序就会抛出

org.springframework.validation.BindException 的异常。

在实际开发的过程中,我们肯定不能讲异常直接展示给用户,而是给能看懂的提示。

于是,我们不妨可以通过捕获异常的方式,将该异常进行捕获。

首先我们创建一个校验异常捕获类 ValidExceptionHandler ,然后打上 @RestControllerAdvice 注解,该注解表示他会去抓所有 @Controller 标记类的异常,并在异常处理后返回以 JSON 或字符串的格式响应前端。

 

 

算了,我直接将这段代码贴出来吧。

在异常捕捉到后,我们同上面的 @valid 校验一样,只返回第一个错误提示。

 

 1 package com.zyq.config;
 2  
 3 import org.springframework.validation.BindException;
 4 import org.springframework.web.bind.annotation.ExceptionHandler;
 5 import org.springframework.web.bind.annotation.RestControllerAdvice;
 6  
 7 @RestControllerAdvice
 8 public class ValidExceptionHandler {
 9  
10     @ExceptionHandler(BindException.class)
11     public String validExceptionHandler(BindException exception) {
12         return exception.getAllErrors().get(0).getDefaultMessage();
13     }
15 }

那么,我们现在重启程序,然后重新请求,就可以发现界面已经不报400错误了,而是直接提示了我们的错误信息。

 

 

 

@Valid 和 @Validated 比较
最后我们来对 @Valid 和 @Validated 两个注解进行总结下:

(1)@Valid 和 @Validated 两者都可以对数据进行校验,待校验字段上打的规则注解(@NotNull, @NotEmpty等)都可以对 @Valid 和 @Validated 生效;

(2)@Valid 进行校验的时候,需要用 BindingResult 来做一个校验结果接收。当校验不通过的时候,如果手动不 return ,则并不会阻止程序的执行;

(3)@Validated 进行校验的时候,当校验不通过的时候,程序会抛出400异常,阻止方法中的代码执行,这时需要再写一个全局校验异常捕获处理类,然后返回校验提示。

(4)总体来说,@Validated 使用起来要比 @Valid 方便一些,它可以帮我们节省一定的代码,并且使得方法看上去更加的简洁。

原文链接:https://blog.csdn.net/sunnyzyq/article/details/103527380

标签:校验,我们,Valid,注解,Validated,public,详解
From: https://www.cnblogs.com/lipengtao/p/17118823.html

相关文章

  • springboot自动配置原理以及spring.factories文件的作用详解
    一、springboot自动配置原理先说说我们自己的应用程序中Bean加入容器的办法:packagecom.ynunicom.dc.dingdingcontractapp;importcom.alibaba.druid.spring.boot.au......
  • 详解数据计算能力的四种类型
    我们将计算能力根据场景抽象分成四大类:批计算、流计算、在线查询和即席分析。不同场景配合不同的存储和计算框架来实现,以满足业务的复杂需求。1、批计算随着数据量的不断增......
  • Docker参数命令大全详解
    哦,docker就是那个鲸鱼哇,集装箱技术,我是这么理解的。那我觉得这部分知识有什么好记好背的,用到了直接CTRL+F搜索,然后CTRL+C复制,再然后CTRL+V粘贴就好了,就没了,基础的流......
  • redux-toolkit详解
    简述redux-toolkit是 Redux官方强烈推荐,开箱即用的一个高效的Redux开发工具集,本质是对redux的封装,方便我们写reducer、actioncreator和继承类似thunk的中间件。......
  • Python中如何求1-100的奇数和?方法详解!
    在之前的文章中,老男孩IT教育小编为大家介绍过Python的特点、优势、用途以及薪资待遇等知识,而为了帮助大家更好的掌握Python,小编将为大家讲解一些实战案例,比如:Python中如......
  • Linux最常见的4个截取命令详解!
    在Linux系统中截取命令有很多,但比较常用的截取命令一般包含:cut命令、printf命令、awk命令、sed命令,接下来我们通过这篇文章为大家详细的介绍一下这四个命令。1、cut......
  • python常用的搜索字符内容函数详解:re.findall/findfiter
    区别findall返回listfinditer返回一个MatchObject类型的iterator详细举例介绍1、findall在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返......
  • jquery.validate清除表单的验证结果
    文章目录​​发现bug:​​​​分析bug:​​​​解决bug:​​发现bug:jquery.validate无法清除同表单的上次验证结果,如下:分析bug:查阅官方文档之后,观察validate的返回类型,可以发......
  • 【JVM】JVM各个内存模型存储内容详解
    1 前言JVM的内存模型,想必大概都清楚了,可以看之前的文章,有讲解。那么JVM每个内存模型里都存哪些内容呢,本文来追一下。2 内存模块存储内容运行时数据区大概分5部分,方......
  • linux uniq命令详解
    Linuxuniq命令读取输入文件,并比较相邻的行。在正常情况下,第二个及以后更多个重复行将被删去,行比较是根据所用字符集的排序序列进行的。该命令加工后的结果写到输出文件中......