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

@Valid 和 @Validated 注解用法详解

时间:2023-04-24 17:57:55浏览次数:50  
标签:校验 我们 Valid 注解 Validated public 详解

 

目录

案例引入

@Valid 详解

@Validated 详解

@Valid 和 @Validated 比较

 

 

案例引入

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

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

/**
 * 员工对象
 * 
 * @author sunnyzyq
 * @since 2019/12/13
 */
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;
    }
 
}

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

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

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

 写完,我们启动项目测试下,和我们料想中的一样,毫无问题。

但是,除了名称外,我们规定年龄也是必填项,且范围在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>
</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 类的属性上打上如下注解:

package com.zyq.beans;
 
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
 
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;
 
/**
 * 员工对象
 * 
 * @author sunnyzyq
 * @since 2019/12/13
 */
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 注解,表示我们对这个对象属性需要进行验证,

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

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

 OK ! 万事俱备 !我们进行测试...代码不但简洁了很多,结果和预期的也一模一样!

常用注解:

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

 

 

@Validated 详解

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

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

 

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

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

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

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

 

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

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

 

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

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

 

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

org.springframework.validation.BindException 的异常。

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

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

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

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

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

package com.zyq.config;
 
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
 
@RestControllerAdvice
public class ValidExceptionHandler {
 
    @ExceptionHandler(BindException.class)
    public String validExceptionHandler(BindException exception) {
        return exception.getAllErrors().get(0).getDefaultMessage();
    }
}

那么,我们现在重启程序,然后重新请求,就可以发现界面已经不报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

https://www.cnblogs.com/Marydon20170307/p/15707793.html

 

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

相关文章

  • Validating multiple properties with FluentValidation(FluentValidator多个相关属性
    Sourcelink:ValidatingmultiplepropertieswithFluentValidation|TheCodetripper(wordpress.com)publicclassFooBarRequestValidator:AbstractValidator<FooBarRequest>{privatereadonlyIRepositoryrepository;publicFooBarRequestValid......
  • Apple 的 plist 编辑器入门指南:基础操作与高级功能详解
     PlistEditPro是一款专为macOS编写的最高级属性列表Plist编辑器。对于Mac和IOS开发人员来说,编写应用程序时必须编辑各种列表文件。PlistEditPro通过提供直观且功能强大的界面,使编辑这些文件更加容易。它不仅能够复制和粘贴或拖放属性列表数据,还提供强大的搜索和替换功能,并......
  • 一文详解RocketMQ-Spring的源码解析与实战
    摘要:这篇文章主要介绍SpringBoot项目使用rocketmq-springSDK实现消息收发的操作流程,同时笔者会从开发者的角度解读SDK的设计逻辑。本文分享自华为云社区《RocketMQ-Spring:实战与源码解析一网打尽》,作者:勇哥java实战分享。RocketMQ是大家耳熟能详的消息队列,开源项目......
  • 地统计学的基本概念及公式详解
      本文对插值、平稳假设、变异函数、克里格等常用的地学计算概念加以介绍,并对相关公式进行推导。目录1引言2空间插值3几个重要假设3.1平稳假设3.2二阶平稳性假设3.3本征假设3.4不同假设对比4变异函数5克里格插值6回归克里格1引言  最近的几篇博客,分别从遥感的实......
  • istio 请求超时相关详解
    虚拟服务中这段代码含义虚拟服务中这段代码含义“spec:gateways:-magicboard-meshhosts:-magicboard-magicboard.lh.prodhttp:-name:defaultretries:attempts:3retryOn:'reset,connect-failure,retriable-......
  • 详解Python当中的pip常用命令
    相信对于大多数熟悉Python的人来说,一定都听说并且使用过pip这个工具,但是对它的了解可能还不一定是非常的透彻,今天小编就来为大家介绍10个使用pip的小技巧,相信对大家以后管理和使用Python当中的标准库会有帮助。安装当然在Python3.4版本之后以及Python2.7.9版本之后,官网的安装......
  • pg_setting详解
    示例参数max_connectionsselect*frompg_settingswherename='max_connections';-[RECORD1]---+-----------------------------------------------------name|max_connectionssetting|14unit|category|Connect......
  • 【v4l2】Linux多媒体框架 - videobuf2详解
    框架分析框架可以分为两部分看:控制流+数据流,之前已经大概的描述了控制流,数据流部分就是videobuffer,V4l2buffer的管理是通过videobuf2来完成的,它充当于用户空间和驱动空间之间的中间层,并提供模块化的内存管理功能。上图大体包含了videobuf2的框架1.vb2_queue:核心的数据结构,......
  • 【c&c++】vector 详解(C++)
    C++STL中的verctor好比是C语言中的数组,但是vector又具有数组没有的一些高级功能。与数组相比,vector就是一个可以不用再初始化就必须制定大小的边长数组,当然了,它还有许多高级功能。1.头文件#include<vector>2.初始化 如果vector的元素类型是int,默认初始化为0;如果vector元......
  • 【C++入门】类和对象(一) 详解(class、struct、类的定义、类的实例化、类的封装、对象
    1.面向过程和面向对象初步认识面向过程更加关注解决问题的过程和步骤。而面向对象关注的是对象,对一个事情拆分成不同的对象,靠对象之间的交互实现。例如:外卖系统面向过程:上架→点餐→派单→送餐注重过程步骤面向对象:(更加贴近现实之间的业务逻辑交互)骑手→商家←用户注重对象和对象......