@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不是JavaBean所以校验会失败,介绍三种解决办法

方法1:对List进行Wrapper

既然List不是JavaBean,那我们就把它封装成JavaBean,我们定义一个ListWrapper类如下:

import lombok.Getter;

import lombok.Setter;

import javax.validation.Valid;

import java.util.ArrayList;

import java.util.List;

@Setter

@Getter

public class ListWrapper {

@Valid

private List list;

public ListWrapper() {
list = new ArrayList<>();
} public ListWrapper(List<E> list) {
this.list = 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 ValidList implements List {

@Valid
private List<E> list; public ValidList() {
this.list = new ArrayList<>();
} public ValidList(List<E> list) {
this.list = list;
} public List<E> getList() {
return list;
} public void setList(List<E> list) {
this.list = list;
} @Override
public int size() {
return list.size();
} @Override
public boolean isEmpty() {
return list.isEmpty();
} ...

}

对比方法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

本文由博客一文多发平台 OpenWrite 发布!

@Validated和@Valid校验参数、级联属性、List的更多相关文章

  1. @Validated和@Valid的区别?校验级联属性(内部类)

    每篇一句 NBA里有两大笑话:一是科比没天赋,二是詹姆斯没技术 相关阅读 [小家Java]深入了解数据校验:Java Bean Validation 2.0(JSR303.JSR349.JSR380) ...

  2. 参数验证 @Validated 和 @Valid 的区别

    来源:blog.csdn.net/qq_27680317/article/details/79970590 整编:Java技术栈(公众号ID:javastack) Spring Validation验 ...

  3. @Validated和@Valid区别:Spring validation验证框架对入参实体进行嵌套验证必须在相应属性(字段)加上@Valid而不是@Validated

    Spring Validation验证框架对参数的验证机制提供了@Validated(Spring's JSR-303规范,是标准JSR-303的一个变种),javax提供了@Valid(标准JSR- ...

  4. valid 校验方式

    校验参数方法:1.最简单的方式是,使用Java bean注解校验(如 @NotEmpty...)2.适合复杂点的自定义校验(推荐) 2.1 先定义一个校验接口: public interface Va ...

  5. 使用Spring Validation优雅地校验参数

    写得好的没我写得全,写得全的没我写得好 引言 不知道大家平时的业务开发过程中 controller 层的参数校验都是怎么写的?是否也存在下面这样的直接判断? public String add(Use ...

  6. Spring 捕捉校验参数异常并统一处理

    使用 @Validated ,@Valid ,@NotBlank 之类的,请自行百度,本文着重与捕捉校验失败信息并封装返回出去 参考: https://mp.weixin.qq.com/s/EaZxY ...

  7. @Validated和@Valid区别

    注解地方 @Validated:可以用在类型.方法和方法参数上.但是不能用在成员属性(字段)上 @Valid:可以用在方法.构造函数.方法参数和成员属性(字段)上 两者是否能用于成员属性(字段)上直接 ...

  8. Hibernate 集合映射 一对多多对一 inverse属性 + cascade级联属性 多对多 一对一 关系映射

    1 . 集合映射 需求:购物商城,用户有多个地址. // javabean设计 // javabean设计 public class User { private int userId; privat ...

  9. 前端请求参数MD5加密校验,参数串解密

    首先引入MD5加密库:=>https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js; 步骤:=>1.请求前对参数进行字典升序排序,排 ...

随机推荐

  1. JAVA bean为何要实现序列化

    简而言之:序列化,就是为了在不同时间或不同平台的JVM之间共享实例对象.即序列化出于两个原因:①.用于持久化到磁盘上:②.用于作为数据流在网络上传输. 所谓的Serializable,就是java提供 ...

  2. 10-SQLServer中统计信息的使用

    一.总结 1.网址https://docs.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-stats-tr ...

  3. Hadoop-No.6之文件在HDFS中的位置

    在设计一种HDFS模式时,首先应该决定文件的位置.标准化的位置会使得团队之间更容易查找和共享数据. 推荐HDFS目录结构实例.目录结构简化了不同组和用户的权限分配 /user/{username} 只 ...

  4. FZU-1901-Period 2(KMP)

    链接: https://vjudge.net/problem/FZU-1901 题意: For each prefix with length P of a given string S,if S[i ...

  5. 【JZOJ5603】【NOI2018模拟3.27】Xjz

    题目描述 给定字符串 S 和 T. 串A和串B匹配的定义改为:存在一个字符的映射,使得A应用这个映射之后等于B,且这个映射必须为一个排列. A=121, B=313,当映射为{1->3, 2-& ...

  6. 设置Portainer管理Docker并且开启https(简单方法)

    1. 序言 Portainer是一个十分好用的docker图形化管理界面,可以很方便的查看容器状态,错误log等等. 2. 安装 安装portainer是十分简单的,只需要执行docker pull ...

  7. 【Python之路】特别篇--Python内置函数

    abs() 求绝对值 i = abs(-100) print(i) # 100 all() 循环里面的参数 如果每个元素都为真,那么all返回值为真  假: 0 False None "&q ...

  8. hadoop安装后运行一个单实例(测试MapReduce程序)

    1.安装hadoop 解压hadoop-1.2.1-bin.tar.gz包   tar -zxvf hadoop-1.2.1-bin.tar.gz  /opt/modules/ 解压后在/opt/mo ...

  9. The Semantics of Constructors: The Default Constructor (默认构造函数什么时候会被创建出来)

    本文是 Inside The C++ Object Model, Chapter 2的部分读书笔记. C++ Annotated Reference Manual中明确告诉我们: default co ...

  10. LabVIEW:可执行文件运行缺少运行库问题

    造冰箱的大熊猫@cnblogs 2018/5/11 上周调试设备网口犯了一个低级错误,今天又搞出一个笑话 目标机上没有LabVIEW开发环境,于是在开发机上将VI打包成可执行程序.在目标机上运行可执行 ...