首页 > 其他分享 >@Validated和@Valid校验参数

@Validated和@Valid校验参数

时间:2023-12-21 14:49:25浏览次数:27  
标签:验证 List list 校验 Valid Validated public

@Validated和@Valid的区别

在Controller中校验方法参数时,使用@Valid和@Validated并无特殊差异(若不需要分组校验的话):
@Valid:标准JSR-303规范的标记型注解,用来标记验证属性和方法返回值,进行级联和递归校验
@Validated:Spring的注解,是标准JSR-303的一个变种(补充),提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制

方法级别:
@Validated注解可以用于类级别,用于支持Spring进行方法级别的参数校验。@Valid可以用在属性级别约束,用来表示级联校验。
@Validated只能用在类、方法和参数上,而@Valid可用于方法、字段、构造器和参数上

内置的验证约束注解 :

空检查
@Null 验证对象是否为null
@NotNull 验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.
@NotEmpty 检查约束元素是否为NULL或者是EMPTY.

Booelan检查
@AssertTrue 验证 Boolean 对象是否为 true
@AssertFalse 验证 Boolean 对象是否为 false

长度检查
@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内
@Length(min=, max=) Validates that the annotated string is between min and max included.

日期检查
@Past 验证 Date 和 Calendar 对象是否在当前时间之前
@Future 验证 Date 和 Calendar 对象是否在当前时间之后
@Pattern 验证 String 对象是否符合正则表达式的规则

数值检查,建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng为"",Integer为null
@Min 验证 Number 和 String 对象是否大等于指定的值
@Max 验证 Number 和 String 对象是否小等于指定的值
@DecimalMax 被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度
@DecimalMin 被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度
@Digits 验证 Number 和 String 的构成是否合法
@Digits(integer=,fraction=) 验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。

@Range(min=, max=) 检查数字是否介于min和max之间.
@Range(min=10000,max=50000,message="range.bean.wage")
private BigDecimal wage;

@Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证)
@CreditCardNumber信用卡验证
@Email 验证是否是邮件地址,如果为null,不进行验证,算通过验证。
@ScriptAssert(lang= ,script=, alias=)
@URL(protocol=,host=, port=,regexp=, flags=)

限制 说明
@Null 限制只能为null
@NotNull 限制必须不为null
@AssertFalse 限制必须为false
@AssertTrue 限制必须为true
@DecimalMax(value) 限制必须为一个不大于指定值的数字
@DecimalMin(value) 限制必须为一个不小于指定值的数字
@Digits(integer,fraction) 限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction
@Future 限制必须是一个将来的日期
@Max(value) 限制必须为一个不大于指定值的数字
@Min(value) 限制必须为一个不小于指定值的数字
@Past 限制必须是一个过去的日期
@Pattern(value) 限制必须符合指定的正则表达式
@Size(max,min) 限制字符长度必须在min到max之间
@Past 验证注解的元素值(日期类型)比当前时间早
@NotEmpty 验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@NotBlank 验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格
@Email 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式

校验参数、级联属性

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类如下:

import lombok.Getter;
import lombok.Setter;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;

@Setter
@Getter
public class ListWrapper<E> {
@Valid
private List<E> 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返回了)


  file
  file

然后我们运行一下测试一下


  file

可以看到可以对参数进行校验了,但还还有一个问题,那就是这个不是我们想要的返回格式,它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());
}

}
经过统一异常处理,我们这边的返回结果就是我们想要的格式了


  file

方法3:自定义一个List

先上代码后说明,先定义一个ValidList

import javax.validation.Valid;
import java.util.*;

public class ValidList<E> implements List<E> {

@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就可以了,还不需要多统一异常处理。


  file

参考: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://www.jianshu.com/p/17323904fd72
 

标签:验证,List,list,校验,Valid,Validated,public
From: https://www.cnblogs.com/xd502djj/p/17918977.html

相关文章

  • Spring Validation使用小结
    目录1、背景2、常用注解2.1、BeanValidation2.0注解2.1.1、校验空值2.1.2、校验大小2.1.3、校验布尔值2.1.4、校验日期和时间2.1.5、正则表达式2.1.5.1、验证IP地址2.1.5.1、验证手机号码3、使用3.1、当方法入参为@PathVariable、@RequestParam注解的简单参数时,需要在Cont......
  • Addressables资源如何进行完整性校验
    1)Addressables资源如何进行完整性校验2)使用SpriteAtlas时出现冗余精灵,如何指定用哪一个图集3)anim文件进行精度处理后某些信息丢失这是第365篇UWA技术知识分享的推送,精选了UWA社区的热门话题,涵盖了UWA问答、社区帖子等技术知识点,助力大家更全面地掌握和学习。UWA社区主页:communi......
  • Git — husky + eslint 实现提交前校验与规范提交
    node版本:=14.21.3||>16.0.0一、配置ESlint1.1安装eslintnpminstalleslint-D1.2初始化eslint,生成配置文件npxeslint--init1.3在编辑器安装ESlint插件1.4通过执行命令检测文件代码规范#./src为需要检测的文件路径npxeslint./src二、配置husky2.1安......
  • 动态表单如何校验?
    记录一下,直接上代码,核心代码就一行。注:prop需要定位到表单项的值,如下定义为[${index}].value,即校验canConfigList[${index}].value的值<el-form:inline="true"ref="addChannelRef":model="canConfigList"label-width="110px"><e......
  • 我是如何解决java.security.cert.CertPathValidatorException异常的
    在rocky8.5上,有个jdk8跑的程序连接windows上SQLServer2012失败了,环境如下:[zcm@rockymicroService]$cat/etc/redhat-releaseRockyLinuxrelease8.5(GreenObsidian)[root@rockysecurity]#java-versionopenjdkversion"1.8.0_302"OpenJDKRuntimeEnvironment(......
  • SpringBoot-Validate优雅实现参数校验
    1、是什么?它简化了JavaBeanValidation的集成。JavaBeanValidation通过JSR380,也称为BeanValidation2.0,是一种标准化的方式,用于在Java应用程序中对对象的约束进行声明式验证。它允许开发人员使用注解来定义验证规则,并自动将规则应用于相应的字段或方法参数为了我们......
  • 解决UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0xd3 in position 238:
    解决UnicodeDecodeError:'utf-8'codeccan'tdecodebyte0xd3inposition238:invalidcontinuationbyte在处理文本数据时,经常会遇到​​UnicodeDecodeError​​错误,特别是当使用​​utf-8​​编码读取文件时。这个错误通常表示文件中包含无法解码的字符,导致解码失败。在本......
  • 参数校验与国际化:提高代码稳定性和可维护性的重要方法
    在我们日常的工作中,参数校验是一项非常重要的任务。它能够帮助我们确保代码的稳定性和可靠性,避免因为参数错误而导致的意外情况发生。参数校验通常包括对输入参数的合法性、格式的检查等。而为了提高代码的可维护性和可重用性,我们可以使用一些常见的参数校验方法。另外,国际化也是......
  • Vue2 校验不通过的表单,赋正确的值后,再次校验结果不变
    前言在工作中遇到了这个问题,多次排查,耗费了不少时间才解决这个问题。问题的解决很简单,但发现根本原因还是有点困难,因此在此做个记录,以防忘记。问题发现步骤例如有以下AntDesignVue表单<a-form-modelref="formRef":model="model"><a-form-model-itemlabel="姓名"pr......
  • MIRO相关的增强,EXTENSION,校验替代
    EXTENSION:  校验替代: BADI:INVOICE_UPDATE点击保存按钮或模拟过账,校验直接message报错,替代改内存 ......