@Validated和@Valid校验参数、级联属性、List
@Validated和@Valid的区别
在Controller中校验方法参数时,使用@Valid和@Validated并无特殊差异(若不需要分组校验的话): @Valid:标准JSR-303规范的标记型注解,用来标记验证属性和方法返回值,进行级联和递归校验 @Validated:Spring的注解,是标准JSR-303的一个变种(补充),提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制
方法级别: @Validated注解可以用于类级别,用于支持Spring进行方法级别的参数校验。@Valid可以用在属性级别约束,用来表示级联校验。 @Validated只能用在类、方法和参数上,而@Valid可用于方法、字段、构造器和参数上
校验参数、级联属性
1、校验参数 当入参为实体对象时,需要在方法上加@Valid或@Validated或者在参数前加@Valid或@Validated,或者在类上加@Validated
@Valid @GetMapping("/exam-info") public Boolean getInfo(User user){......}
@GetMapping("/exam-info") public Boolean getInfo(@Valid User user){......}
@Validated @GetMapping("/exam-info") public Boolean getInfo(User user){......}
@GetMapping("/exam-info") public Boolean getInfo(@Validated User user){......}
public Class User{ @NotNull("id不能为空") private Integer id; }
2、嵌套验证 @valid作用于属性上有嵌套验证作用,@validated不能作用于属性上,如下代码在User类的属性car上添加@valid注解,当传参id为空时会报错。
@GetMapping("/exam-info") public Boolean getInfo(@Valid User user){.....}
public class User{ @Valid @NotNull("car不能为空") private Car car; } public class Car{ @NotNull("id不能为空") private Integer id; }
校验List
@Valid只能校验JavaBean,而List<E>不是JavaBean所以校验会失败,介绍三种解决办法
方法1:对List进行Wrapper
既然List不是JavaBean,那我们就把它封装成JavaBean,我们定义一个ListWrapper类如下:
public class ListWrapper<E> { @Valid
@NotEmpty(message="列表不能为空!", groups = {Creation.class, Modification.class})private List<E> list;public ListWrapper() {list = new ArrayList<>();}public ListWrapper(List<E> list) {this.list = list;}public setList(List<E> list){this.list = list;}public getList(){return list;}
}
同时修改一下controller对应的方法:
// 使用包装类对list进行验证
@PostMapping("/insert/all")
public ServerResponse<String> insertList(@Valid @RequestBody ListWrapper<UserEntity> listWrapper, BindingResult bindingResult) {if(bindingResult.hasErrors()) {log.error(bindingResult.getFieldError().toString());return ServerResponse.createByErrorMessage(bindingResult.getFieldError().getDefaultMessage());}userService.insertList(listWrapper.getList());return ServerResponse.createBySuccess();
}
这样就可以对list进行校验了
注意:
由于对list进行了包装,如果我们传参的时候
[{},{}..]要改为{“list”: [{},{}..]}
方法2:使用@Validated+@Valid
在controller类上面增加@Validated注解,并且删除方法参数中的BindingResult bindingResult(因为这个参数已经没有用了,异常统一有controller返回了)
然后我们运行一下测试一下
可以看到可以对参数进行校验了,但还还有一个问题,那就是这个不是我们想要的返回格式,它controller自己返回的格式,所以我们需要做一个统一异常处理,代码如下:
import com.wyq.firstdemo.common.ServerResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;@Slf4j
@RestControllerAdvice
public class ControllerExceptionHandler {@ExceptionHandler
@ResponseBody
public ServerResponse<String> handle(ConstraintViolationException exception) {log.error(String.valueOf(exception));Set<ConstraintViolation<?>> violations = exception.getConstraintViolations();StringBuilder builder = new StringBuilder();for (ConstraintViolation violation : violations) {builder.append(violation.getMessage());break;}return ServerResponse.createByErrorMessage(builder.toString());
}
}
}经过统一异常处理,我们这边的返回结果就是我们想要的格式了
方法3:自定义一个List
先上代码后说明,先定义一个ValidList
import javax.validation.Valid;
import java.util.*;public class ValidationList<E> implements List<E> {@Valid
@NotEmpty(message="列表不能为空!", groups = {Creation.class, Modification.class})private List<E> list;public ValidationList() {this.list = new ArrayList<>();}@Overridepublic int size() {return list.size();}@Overridepublic boolean isEmpty() {return list.isEmpty();}@Overridepublic boolean contains(Object o) {return list.contains(o);}@Overridepublic Iterator<E> iterator() {return list.iterator();}@Overridepublic Object[] toArray() {return list.toArray();}@Overridepublic <T> T[] toArray(T[] a) {return list.toArray(a);}@Overridepublic boolean add(E e) {return list.add(e);}@Overridepublic boolean remove(Object o) {return list.remove(o);}@Overridepublic boolean containsAll(Collection<?> c) {return list.containsAll(c);}@Overridepublic boolean addAll(Collection<? extends E> c) {return list.addAll(c);}@Overridepublic boolean addAll(int index, Collection<? extends E> c) {return list.addAll(index, c);}@Overridepublic boolean removeAll(Collection<?> c) {return list.removeAll(c);}@Overridepublic boolean retainAll(Collection<?> c) {return list.retainAll(c);}@Overridepublic void clear() {list.clear();}@Overridepublic E get(int index) {return list.get(index);}@Overridepublic E set(int index, E element) {return list.set(index, element);}@Overridepublic void add(int index, E element) {list.add(index, element);}@Overridepublic E remove(int index) {return list.remove(index);}@Overridepublic int indexOf(Object o) {return list.indexOf(o);}@Overridepublic int lastIndexOf(Object o) {return list.lastIndexOf(o);}@Overridepublic ListIterator<E> listIterator() {return list.listIterator();}@Overridepublic ListIterator<E> listIterator(int index) {return list.listIterator(index);}@Overridepublic List<E> subList(int fromIndex, int toIndex) {return list.subList(fromIndex, toIndex);}public List<E> getList() {return list;}public void setList(List<E> list) {this.list = list;}}
对比方法3和方法1,有没有觉得代码有点相似,新建一个类,并且让他实现List接口,使这个类即具有了JavaBean的特性,又具有了List的特性,比方法1简单优雅很多。
只需要把List换成ValidList就可以了,还不需要多统一异常处理。
参考:https://my.oschina.net/fangshixiang/blog/3081366
https://stackoverflow.com/questions/28150405/validation-of-a-list-of-objects-in-spring/36313615#36313615
https://my.oschina.net/fangshixiang/blog/3081366
转自https://my.oschina.net/u/3635618/blog/3119870
@Validated和@Valid校验参数、级联属性、List相关推荐
- @Validated和@Valid校验参数
@Validated和@Valid校验参数 参考: @Validated和@Valid校验参数.级联属性.List java valid payload_Spring Validation最佳实践及其 ...
- @Validated与@Valid校验
痛点:开发接口的时候,对于请求参数,往往需要进行校验,这个时候可以采用如下方式校验请求参数id和number,显然这种方式难以维护,即便封装成方法,依旧麻烦. @PostMapping("/ ...
- validated 验证数组_@Validated和@Valid的区别?校验级联属性(内部类)
NBA里有两大笑话:一是科比没天赋,二是詹姆斯没技术.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以 ...
- springMVC 优雅的校验参数(@Valid和@Validated)
很痛苦遇到大量的参数进行校验,在业务中还要抛出异常或者不断的返回异常时的校验信息,在代码中相当冗长, 充满了if-else这种校验代码,今天我们就来学习spring的javax.validation ...
- notnull注解_参数校验注解Validated和Valid的区别,这次终于有人说清楚了
Spring Validation验证框架对参数的验证机制提供了@Validated(Spring's JSR-303规范,是标准JSR-303的一个变种),javax提供了@Valid(标准JSR- ...
- @valid 校验_一文带你快速入手 Spring Boot 参数校验
点击上方"Java专栏",选择"置顶或者星标" 第一时间阅读精彩文章! ☞ 程序员进阶必备资源免费送「21种技术方向!」 点击查看☜ 作者:狂乱的贵公子 来源: ...
- 面试:说说参数验证 @Validated 和 @Valid 的区别?
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | blog.csdn.net/qq_276803 ...
- 参数验证 @Validated 和 @Valid 的区别,Java Web 开发必备。
Spring Validation验证框架对参数的验证机制提供了@Validated(Spring's JSR-303 规范,是标准 JSR-303 的一个变种),javax提供了@Valid(标准J ...
- Spring Validation验证框架参数验证 @Validated 和 @Valid 的区别
参数验证 @Validated 和 @Valid 的区别 Spring Validation验证框架对参数的验证机制提供了@Validated(Spring's JSR-303 规范,是标准 JSR- ...
最新文章
- 这10道Java面试题!95%的人回答不出来!
- python爬虫如何从一个页面进入另一个页面-爬虫入门(一)——如何打开一个网页...
- 关于《设计模式》这本书(三)——Proxy模式
- Python爬虫,通过特定的函数来筛选标签
- STM32 SPI NSS 引脚为不能拉高问题
- 现代密码学1.4--现代密码的三大原则
- 【学习笔记】17、函数(Function)的定义和调用
- docker desktop 镜像_Spring Boot实战工具4 - Docker
- 【杂项】原来有两种单引号(单引号和反引号)
- 天津2021年高考成绩查询入口,2021年天津高考成绩查询时间安排 什么时候出分
- 数据库-优化-每个字段的说明
- GB28181开放流媒体服务平台LiveGBS实际测试时问题排查
- 微博关注者数量在计算中的作用
- 如何支撑企业快速构建数字孪生体
- CUDA——调试“ImportError: libcudart.so.9.2: cannot open shared object file: No such file or directory”
- GDB中打印pthread_internal_t的方法
- Adobe产品序列号
- 计算机一级插入页眉,计算机一级考试,设置页眉为“汉字的交换码”
- MTK-EngineeMode-Hardware Testing
- 1800 Flying to the Mars 大数 最多不上升序列 简化题意