@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. 解决使用vue打包时vendor文件过大或者是app.js文件很大的问题

    这篇文章主要介绍了使用vue打包时vendor文件过大或者是app.js文件很大问题的解决方法,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下 第一次使用vue2.0开发,之前都是用的angu ...

  2. POI导出Excel不弹出保存提示_通过ajax异步请求(post)到后台通过POI导出Excel

    实现导出excel的思路是:前端通过ajax的post请求,到后台处理数据,然后把流文件响应到客户端,供客户端下载 文件下载方法如下: public static boolean downloadLo ...

  3. python Print 输出

    print 默认输出是换行的,如果要实现不换行需要在变量末尾加上逗号 , #!/usr/bin/python # -*- coding: UTF-8 -*- x="a" y=&qu ...

  4. noi.ac #528 神树和排列

    题目链接:戳我 #include<iostream> #include<cstring> #include<cstdio> #include<algorith ...

  5. 灰度图像--图像分割 Canny边缘检测

    学习DIP第48天 **转载请标明本文出处:http://blog.csdn.net/tonyshengtan ,出于尊重文章作者的劳动,转载请标明出处!文章代码已托管,欢迎共同开发: https:/ ...

  6. C#如何生成setup安装文件

    当前项目状况如图: ,如何把test1打包成setup文件,用户安装后即可完成相应功能. 第一,右击“解决方案test1”->添加“新建项目”->“其他项目类型”->“安装和部署”- ...

  7. TNS-12560: TNS: 协议适配器错误

    TNS-12560: TNS: 协议适配器错误   Microsoft Windows [版本 5.2.3790] (C) 版权所有 1985-2003 Microsoft Corp. C:\Docu ...

  8. AcWing:172. 立体推箱子(bfs)

    立体推箱子是一个风靡世界的小游戏. 游戏地图是一个N行M列的矩阵,每个位置可能是硬地(用”.”表示).易碎地面(用”E”表示).禁地(用”#”表示).起点(用”X”表示)或终点(用”O”表示). 你的 ...

  9. javaScript用正则来获取url传递的参数

    用window.location.href获取url再js正则来获得需要的参数: 这个正则有多种写法,这里我选择这样写,要查找的属性名我直接以参数的形式传进去,用正则查找,以"?&# ...

  10. MySQL_(Java)【连接池】简单在JDBCUtils.java中创建连接池

    MySQL_(Java)[事物操作]使用JDBC模拟银行转账向数据库发起修改请求 传送门 MySQL_(Java)[连接池]使用DBCP简单模拟银行转账事物 传送门 Java应用程序访问数据库的过程: ...