@Valid和@Validated
简介
@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;
}
然后我们在ItemController
的addItem函数
上再使用@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";}
}
@Valid和@Validated相关推荐
- 校验注解:@Valid 和 @Validated区别与用法(附详细案例)
一.案例对象 本文章会以案例为主,讲解@Valid 和 @Validated这两个注解的区别与用法. 1.首先,创建一个学生对象,如下: import lombok.Data;/*** 学生对象*/ ...
- @Valid和@Validated注解校验List<Object>
@Valid和@Validated注解校验List< Object> spring 4整合hibernate-validator6 1.导包 <dependency><g ...
- Java校验框架使用@Valid、@Validated、OVAL+Groovy
@Valid 与 @Validated Spring Validation验证框架对参数的验证机制提供了@Validated; javax提供了@Valid,配合BindingResult可以直接提供 ...
- 常用校验注解@NotEmpty,@NotBlank,@NotNull,@Valid,@Validated用法区别,以及搭配 BindingResult使用,嵌套验证等《使用|CSDN创作打卡》
文章目录 一.常用注解@NotEmpty,@NotBlank,@NotNull介绍 二.@Valid与@Validated的使用与区别 2.1@Valid与@Validated区别: 2.2嵌套验证 ...
- @Valid和@Validated验证List集合--网络踩坑记录
基于Springboot框架验证list只需要一下两步: 在Controller上添加@Validated注解,方法上添加@Valid注解,就能验证了 实体类: 情况二.只是用@Valid,并且不是S ...
- 一文探知@Valid和@Validated 的区别
使用spring boot开发的道友们,或许或多或少有用到过这两个注解,那么今天我们就来探查一下这两者的异同. 两者都可以使开发人员写的注解校验规则生效,例如在某一个字段上加上@NotNull.@No ...
- Spring中@NotEmpty,@NotBlank,@NotNull,@Valid,@Validated注解简介及简单使用
前言 在开发中,为了代码的稳定性不报空指针异常,经常需要判断前端传过来的值是否为空,为空的话就返回前端值为空的提示,才能进行下一步的操作 Maven依赖的引入: springboot 2.3.0 以后 ...
- @Validated注解详解,分组校验,嵌套校验,@Valid和@Validated 区别,Spring Boot @Validated
技术栈: spring boot 2.3.3.RELEASE hibernate-validator 文末附项目源代码 目录 简述 项目依赖 全局异常处理类 基础参数校验 实体类 控制类 测试 嵌套参 ...
- @Valid与@Validated区别
1.@Valid与@Validated作用 @Valid与@Validated都是用来校验接收参数的.@Valid是使用Hibernate validation的时候使用@Validated是只用Sp ...
最新文章
- java对象序列化克隆_JAVA 对象克隆和序列化
- java 扩展类加载器_java实现自定义类加载器
- 对码农的忠告---内心不强大者绕道勿看-来自某CTO的演讲
- C++ :学习(类、指针)
- linux安装python3.6_Linux环境下安装python3.6
- 十、Hadoop学习笔记————Hive与Hbase以及RDBMS(关系型数据库)的关系
- 20145319 第五周学习总结
- NoPause/NoEmgAbort的任务 与后台任务的区别
- WebDriver API元素的定位
- fast rcnn 论文解读(附代码链接)
- 何以笙箫默,一部有剧情的创意广告集?
- 3D引擎多线程:资源异步加载
- python能做什么-学会Python后都能做什么?网友们的回答简直不要太厉害
- 获取窗口句柄 c语言,VC++编程获取窗口句柄的方法小结分享
- LDA模型原理学习及应用
- Springboot企业出纳系统的设计与实现7k9je计算机毕业设计-课程设计-期末作业-毕设程序代做
- 少数派实测报告:AI巨无霸模型GPT-3 | 附送API 调用方法「AI核心算法」
- selinux-001
- JavaScript:一个非常有趣的猜数小游戏
- uniapp 简陋易懂版仿抖音视频播放