@Valid和@Validated

article/2025/9/9 8:49:36

简介

@Validation是一套帮助我们继续对传输的参数进行数据校验的注解,通过配置Validation可以很轻松的完成对数据的约束,配合BindingResult可以直接提供参数验证结果

所有参数注解含义

在这里插入图片描述
参考
@Validated注解详解,分组校验,嵌套校验,@Valid和@Validated 区别,Spring Boot @Validated

区别

javax.validation.Valid.@Valid

① 首先需要在实体类的相应字段上添加用于充当校验条件的注解,如:@Min,如下代码(age属于Girl类中的属性):

@Min(value = 18,message = "未成年禁止入内")  
private Integer age;  

② 其次在controller层的方法的要校验的参数上添加@Valid注解,并且需要传入BindingResult对象,用于获取校验失败情况下的反馈信息,如下代码:

@PostMapping("/girls")  
public Girl addGirl(@Valid Girl girl, BindingResult bindingResult) {  if(bindingResult.hasErrors()){  System.out.println(bindingResult.getFieldError().getDefaultMessage());  return null;  }  return girlResposity.save(girl);  
}  

bindingResult.getFieldError.getDefaultMessage()用于获取相应字段上添加的message中的内容,如:@Min注解中message属性的内容

javax.validation.@Validated

@Validated是@Valid 的一次封装,是Spring提供的校验机制使用。@Valid不提供分组功能

分组

当一个实体类需要多种验证方式时,例:对于一个实体类的id来说,新增的时候是不需要的,对于更新时是必须的。 可以通过groups对验证进行分组

package com.valid.pojo;  import javax.validation.constraints.Size;  
import org.hibernate.validator.constraints.NotEmpty;  import com.valid.interfaces.First;  public class People {  //在First分组时,判断不能为空  @NotEmpty(groups={First.class})  private String id;  //name字段不为空,且长度在3-8之间  @NotEmpty  @Size(min=3,max=8)  private String name;  public String getName() {  return name;  }  public void setName(String name) {  this.name = name;  }  public String getId() {  return id;  }  public void setId(String id) {  this.id = id;  }  public interface First {}
}  
(1)不分配groups,默认每次都要进行验证(2)对一个参数需要多种验证方式时,也可通过分配不同的组达到目的。例:@NotEmpty(groups={First.class})  
@Size(min=3,max=8,groups={Second.class})  
private String name; 
@Controller  
public class FirstController {  @RequestMapping("/addPeople")  //不需验证ID  public @ResponseBody String addPeople(@Validated People p,BindingResult result) {  ...}  @RequestMapping("/updatePeople")  //需要验证ID  public @ResponseBody String updatePeople(@Validated({First.class}) People p,BindingResult result) {  ...}  
}  

@Validated没有添加groups属性时,默认验证没有分组的验证属性,如该例子:People的name属性。如果所有参数的验证类型都设置了分组(即本例中People的name的@NotEmpty@Size都添加groups属性),则不验证任何参数

注意

controller 接口中使用 @Validated@Validated(groups = A.class) 设置了 groups 属性,则只有 配置了 groups = A.class 的效验注解会生效,没有配置的全不生效
@Validated  没有设置 groups 属性,则所有效验注解都会生效

controller中,不使用@Valid注解,而是要使用@Validated,里面value代表的是,在User类里面@NotNull注解里面配置了groups里面有TestNotNull.class的字段判断会生效
那么当前配置的话,就只会判断username是否为空,而password因为没有配置同样的groups属性,所以不会生效

@GetMapping("test")
public Result test(@Validated(value = {TestNotNull.class}) User user) {System.out.println("测试@notNull注解");//验证密码操作省略return Result.suc();
}

在这里插入图片描述这里没有传password,代码没有抛异常,说明@Validated注解不会判断groups属性没有当前class的注解,再试一下不传username会不会抛异常
在这里插入图片描述
这里没有传username,返回的是用户名不能为空,说明配置成功了,如果以后开发中,在多个接口中有不同的判断体系,可以用groups的方式分组

验证多个对象

一个功能方法上处理多个模型对象时,需添加多个验证结果对象

@Controller  
public class FirstController {  @RequestMapping("/addPeople")  public @ResponseBody String addPeople(@Validated People p,BindingResult result,@Validated Person p2,BindingResult result2) {  ...}  
}  

总结

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Valid {
}
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validated {Class<?>[] value() default {};
}
@Valid:没有分组的功能。@Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上
@Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制@Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上
@Validated:用在方法入参上无法单独提供嵌套验证功能。不能用在成员属性(字段)上,也无法提示框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证。@Valid:用在方法入参上无法单独提供嵌套验证功能。能够用在成员属性(字段)上,提示验证框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证。

嵌套验证

public class Item {@NotNull(message = "id不能为空")@Min(value = 1, message = "id必须为正整数")private Long id;@NotNull(message = "props不能为空")@Size(min = 1, message = "至少要有一个属性")private List<Prop> props;
}

Item带有很多属性,属性Prop里面有属性id,属性值vid,属性名和属性值,如下所示:

public class Prop {@NotNull(message = "pid不能为空")@Min(value = 1, message = "pid必须为正整数")private Long pid;@NotNull(message = "vid不能为空")@Min(value = 1, message = "vid必须为正整数")private Long vid;@NotBlank(message = "pidName不能为空")private String pidName;@NotBlank(message = "vidName不能为空")private String vidName;
}

属性Prop这个实体也有自己的验证机制,比如属性和属性值vid不能为空,属性名和属性值不能为空等。
现在我们有个ItemController接受一个Item的入参,想要对Item进行验证,如下所示:

@RestController
public class ItemController {@RequestMapping("/item/add")public void addItem(@Validated Item item, BindingResult bindingResult) {doSomething();}
}

如果Item实体的props属性不额外加注释只有@NotNull和@Size,无论入参采用@Validated还是@Valid验证,Spring Validation框架只会对Item的id和props做非空和数量验证不会对props字段里的Prop实体进行字段验证

也就是@Validated@Valid加在方法参数前,都不会自动对参数进行嵌套验证

也就是说如果传的List<Prop>中有Prop的pid为空或者是负数,入参验证不会检测出来。

为了能够进行嵌套验证,必须手动Item实体的props字段上 明确指出这个字段里面的实体也要进行验证

所以 
request  中的参数 尽量不要是其他的 dto , 可以是 enum ,如果必须用其他 dto,可以作为 静态内部类 

由于@Validated不能用在成员属性(字段)上,但是@Valid能加在成员属性(字段)上,而且@Valid类注解上也说明了它支持嵌套验证功能

那么我们能够推断出:

@Valid加在方法参数时并不能够自动进行嵌套验证
而是用在需要嵌套验证类的相应字段上,来配合方法参数上@Validated@Valid来进行嵌套验证
public class Item {@NotNull(message = "id不能为空")@Min(value = 1, message = "id必须为正整数")private Long id;@Valid // 嵌套验证必须用@Valid@NotNull(message = "props不能为空")@Size(min = 1, message = "props至少要有一个自定义属性")private List<Prop> props;
}

然后我们在ItemControlleraddItem函数上再使用@Validated或者@Valid,就能对Item的入参进行嵌套验证。此时Item里面的props如果含有Prop的相应字段为空的情况,Spring Validation框架就会检测出来bindingResult就会记录相应的错误

好的实现方式

List<包装类>包装类的效验

@Data
@ApiModel
public class xxx {@ApiModelProperty("xxx")@Size(max = 100)@NotEmptyprivate List<@NotBlank String> xxx;
}

自定义封装全局异常类

package com.example.apps.advice;import com.example.apps.result.ServiceResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;@RestControllerAdvice
public class GlobalControllerAdvice {@ExceptionHandler(value = ConstraintViolationException.class)public ServiceResult errorHandler(ConstraintViolationException ex) {ServiceResult serviceResult = new ServiceResult(400);Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();if (!CollectionUtils.isEmpty(constraintViolations)) {StringBuilder stringBuilder = new StringBuilder();for (ConstraintViolation constraintViolation : constraintViolations) {stringBuilder.append(constraintViolation.getMessage()).append(",");}String errorMessage = stringBuilder.toString();if (errorMessage.length() > 1) {errorMessage = StringUtils.removeEnd(errorMessage, ",");serviceResult.setMessage(errorMessage);return serviceResult;}}serviceResult.setMessage(ex.getMessage());return serviceResult;}@ExceptionHandler(value = MethodArgumentNotValidException.class)public ServiceResult errorHandler(MethodArgumentNotValidException ex) {ServiceResult serviceResult = new ServiceResult(400);List<ObjectError> objectErrors = ex.getBindingResult().getAllErrors();if(!CollectionUtils.isEmpty(objectErrors)) {StringBuilder builder = new StringBuilder();for (ObjectError objectError : objectErrors) {builder.append(objectError.getDefaultMessage()).append(",");}String errorMessage = builder.toString();if (errorMessage.length() > 1) {errorMessage = StringUtils.removeEnd(errorMessage,",");}serviceResult.setMessage(errorMessage);return serviceResult;}serviceResult.setMessage(ex.getMessage());return serviceResult;}
}

对Controller里的方法的多个参数进行校验

Controller里的方法的多个参数进行校验(扁平化参数):在Controller类上加注解@Validated

@RestController
@RequestMapping
@Validated
public class HelloController {@PutMapping("/hello/id/{id}/status/{status}")public Object helloGet(@Max(5) @PathVariable Integer id, @Min(5) @PathVariable Integer status) {return "hello world";}
}

http://chatgpt.dhexx.cn/article/gDX76Xwn.shtml

相关文章

@Valid与@Validated注解

之前项目中参数的校验&#xff0c;都是自己写的判断方法进行校验&#xff0c;这次采用了spring提供的注解进行参数的校验&#xff0c;更为的方便&#xff0c;简洁。 Valid&#xff1a;常见用在方法&#xff0c;类中字段上进行校验 Validated&#xff1a;是spring提供的对Valid…

Validform.js jQuery验证插件 使用说明

官网原文&#xff1a;http://validform.rjboy.cn/demo.html Validform常用功能示例 申请VIP 您可以享受到&#xff1a; 及时的技术支持(1年)一对一的使用培训第一手的版本更新信息和讲解 申请条件&#xff1a; 1年365天&#xff0c;每天1元钱&#xff0c;您只需支付365元就能获…

Validform表单验证框架详解

Validform是另外一种表单验证框架&#xff0c;也是基于jQuery框架&#xff0c;用法比较灵活。 这里使用该框架的版本号为&#xff1a; Validform_v5.3.2 官网&#xff1a;http://validform.rjboy.cn/ 目前已经打不开了&#xff0c;本文最后会将官方的的demo打包 。 下面来看看…

Validform表单验证总结

近期项目里用到了表单的验证&#xff0c;选择了Validform_v5.3.2。 先来了解一下一些基本的参数&#xff1a; 通用表单验证方法&#xff1a;Demo: $(".demoform").Validform({//$(".demoform")指明是哪一表单需要验证,名称需加在form表单上; btnSubmit:&qu…

数据分析方法与模型

文章目录 1 数据分析1.1 占比分析1.2 趋势分析1.3 对比分析1.4 象限分析1.5 排名分析1.6 维度分析 2 分析模型2.1 费米问题-大致估算2.2 七问分析法-思考角度的拓展2.3 互联网通用模型AARRR、八角分析法2.3.1 AARRR2.3.2 游戏化用户增长策略-八角模型 本文来源&#xff0c;为接…

在mysql中数据模型三要素_数据模型三要素是什么?

展开全部 数据模型三要素是数据结构、数据操作、数据约束。 1、数据结构 是计算机存储、62616964757a686964616fe78988e69d8331333431376634组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合,即带“结构”的数据元素的集合。。通常情况下&#xff…

数据库系统常用的数据模型

数据库系统常用的数据模型 一、层次模型二、网状模型三、关系模型 数据库的发展经历了初始阶段、萌芽阶段、初级阶段、中级阶段、高级阶段&#xff0c;这个过程也产生了多个不同的数据模型&#xff0c;接下来我们讲详细介绍数据库的模型 数据库的发展史 数据库的发展史 初始阶段…

(常见)数据模型

文章目录 数据模型概述一、数据模型概要1.模型、建模与抽象2.数据模型3.两类数据模型 二、数据库模型的组成要素1.数据结构2.数据操作3.数据的完整性约束 三、概念模型1.概要2.基本概念3.概念模型的表示方法 常用数据模型一、层次模型1.简介2.数据结构3.数据操纵与完整性约束4.…

2、机器学习三要素之数据、模型、算法

注&#xff1a; 本系列 课程源于李烨 (微软高级软件工程师)老师的文档 在gitbook 上可以买到李老师课程。 机器学习三要素包括数据、模型、算法。简单来说&#xff0c;这三要素之间的关系&#xff0c;可以用下面这幅图来表示&#xff1a; 总结成一句话&#xff1a;算法通过…

数据库系统的三种数据模型

数据模型&#xff1a; 数据模型&#xff08;Data Model&#xff09;是数据特征的抽象。数据&#xff08;Data&#xff09;是描述事物的符号记录&#xff0c;模型&#xff08;Model)是现实世界的抽象。数据模型从抽象层次上描述了系统的静态特征、动态行为和约束条件&#xff0c…

数据模型简介

一张地图、售楼处小区的沙盘、一架精巧的航模飞机都是具体的模型&#xff0c;可以让人联想到真是生活中的事物&#xff0c;模型是对现实世界中某个对象特性的模拟和抽象。 数据模型&#xff08;data model&#xff09;也是一种模型&#xff0c;是对现实世界数据特征的抽象。人…

mysql数据模型三要素_数据模型的作用及三要素是什么?

展开全部 数据模型三要素是数据结构、数据操作、数据约束。 1、数据结构 是计算机存储636f707962616964757a686964616f31333431376634、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合,即带“结构”的数据元素的集合。。通常情况下&#xff0c;精…

数据库的三种模型

前言 数据模型是数据库系统的核心&#xff0c;本文简要介绍三种主要的数据库模型。 一、格式化模型 格式化模型是层次模型和网状模型的统称 1.层次模型 ① 层次数据模型的概念 层次模型用属性结构来表示各类实体以及实体间的联系 ② 层次模型的数据结构 特点&#xff1a…

关系数据模型的三个组成部分(关系数据模型的三个组成部分)

关系数据模型由什么组成 关系数据模型由含有相同数据类型的若干行组成。每一行有若干个字段。每一个字段各自可以有不同的数据类型。关系模型中的数据操作是集合操作&#xff0c;操作对象和操作结果都是关系&#xff0c;即若干元组的集合&#xff0c;而不象非关系模型中那样是单…

三种数据模型

数据库的类型是根据数据模型来划分的&#xff0c;而任何一个DBMS也是根据数据模型有针对性地设计出来的&#xff0c;这就意味着必须把数据库组织成符合DBMS规定的数据模型。目前成熟地应用在数据库系统中的数据模型有&#xff1a;层次模型、网状模型和关系模型。它们之间的根本…

数据模型组成要素

最近在看工作机会,目前的公司涨薪的机会渺茫,加上通勤过长。看来换份工作势在必行了。言归正传更新最新学习笔记。 一、数据模型的组成要素 精确地描述了系统的静态特性、动态特性和完整性约束条件三部分组成: 数据结构–描述系统的静态特性 刻画数据模型性质的重要方面 …

java stream 遍历map_遍历map的五种方法介绍

日常开发中Map集合遍历是经常使用的&#xff0c;下面介绍几种遍历方法的差异。 (推荐教程&#xff1a;java课程) 1、IteratorentrySet写法【推荐JDK8以下】&#xff0c;Map.Entry是Map接口的内部接口&#xff0c;获取迭代器&#xff0c;然后依次取出每个迭代器里面的Map.EntryI…

Java中如何遍历Map对象

欢迎支持笔者新作&#xff1a;《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》&#xff0c;同时欢迎关注笔者的微信公众号&#xff1a;朱小厮的博客。 欢迎跳转到本文的原文链接&#xff1a;https://honeypps.com/java/java-how-to-traverse-map-object/ 博主有时…

java遍历map(java遍历map的key)

java中map集合怎么遍历 遍历方法代码如下&#xff1a; import java.util.HashMap; import java.util.Map; public class App01 { public static void main(String[] args) { Map map1 new HashMap (); map1.put("A", "ABC"); map1.put("B", &qu…

js遍历map(js遍历map对象)

javascript怎么遍历map var map new HashMap();map.put(a,1);map.put(b,2);遍历&#xff1a;var key map.keySet();for (var i in key){ alert(map.get(key[i]));&#xff5d;注&#xff1a;js 中使用map&#xff0c;要先导入一个HashMap.js文件 没要求&#xff0c;引入这个文…