当前位置: 首页 > news >正文

SpringBoot使用validator进行参数校验

  1. @Validated、@Valid和BindingResult

Bean Validation是Java定义的一套基于注解的数据校验规范,比如@Null、@NotNull、@Pattern等,它们位于 javax.validation.constraints这个包下。

hibernate validator是对这个规范的实现,并增加了一些其他校验注解,如 @NotBlank、@NotEmpty、@Length等,它们位于org.hibernate.validator.constraints这个包下。

依赖

hibernate validator框架已经集成在 spring-boot-starter-web中,所以无需再添加其他依赖。如果不是Spring Boot项目,需要添加如下依赖。

@Valid和@Validated 区别

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

javax提供了@Valid,配合BindingResult可以直接提供参数验证结果(标准JSR-303规范)。

@Validation对@Valid进行了二次封装,在使用上并没有区别,但在分组、注解位置、嵌套验证等功能上有所不同

  • 分组

@Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制。

@Valid:没有分组校验的功能。

  • 注解地方

@Validated:用在类型、方法和方法参数上(类, 方法, 参数)。但不能用于成员属性。

@Valid:可以用在方法、构造函数、方法参数和成员属性上(方法, 构造器, 参数,字段, 泛型),可以用@Valid实现嵌套验证

两者是否能用于成员属性(字段)上直接影响能否提供嵌套验证的功能
如A类中引用B类,且A、B二类都有内部校验,为了使B类也生效,在A类中引用B类时,在B类变量上加@Valid注解,如果B类为集合等类型且不能为空还需要再加@NotEmpty。

BindingResult

BindingResult用在实体类校验信息返回结果绑定。

该类作为方法入参,要写在实体对象后面。

@PostMapping("/menus")
public Result addMenu(@RequestBody @Valid Menu menu, BindingResult result) {}
  1. 规则注解

validator内置注解

hibernate validator扩展注解

分类

空与非空

注解

支持Java类型

说明

@Null

Object

为null

@NotNull

Object

不为null

@NotBlank

CharSequence

不为null,且必须有一个非空格字符

@NotEmpty

CharSequence、Collection、Map、Array

不为null,且不为空(length/size>0)

Boolean

注解

支持Java类型

说明

备注

@AssertTrue

boolean、Boolean

为true

为null有效

@AssertFalse

boolean、Boolean

为false

为null有效

日期

注解

支持Java类型

说明

备注

@Future

Date、

Calendar、

Instant、

LocalDate、

LocalDateTime、

LocalTime、

MonthDay、

OffsetDateTime、

OffsetTime、

Year、

YearMonth、

ZonedDateTime、

HijrahDate、

JapaneseDate、

MinguoDate、

ThaiBuddhistDate

验证日期为当前时间之后

为null有效

@FutureOrPresent

Date、

Calendar、

Instant、

LocalDate、

LocalDateTime、

LocalTime、

MonthDay、

OffsetDateTime、

OffsetTime、

Year、

YearMonth、

ZonedDateTime、

HijrahDate、

JapaneseDate、

MinguoDate、

ThaiBuddhistDate

验证日期为当前时间或之后

为null有效

@Past

Date、

Calendar、

Instant、

LocalDate、

LocalDateTime、

LocalTime、

MonthDay、

OffsetDateTime、

OffsetTime、

Year、

YearMonth、

ZonedDateTime、

HijrahDate、

JapaneseDate、

MinguoDate、

ThaiBuddhistDate

验证日期为当前时间之前

为null有效

@PastOrPresent

Date、

Calendar、

Instant、

LocalDate、

LocalDateTime、

LocalTime、

MonthDay、

OffsetDateTime、

OffsetTime、

Year、

YearMonth、

ZonedDateTime、

HijrahDate、

JapaneseDate、

MinguoDate、

ThaiBuddhistDate

验证日期为当前时间或之前

为null有效

数值

注解

支持Java类型

说明

备注

@Max

BigDecimal、BigInteger,

byte、short、int、long以及包装类

小于或等于

为null有效

@Min

BigDecimal、BigInteger,

byte、short、int、long以及包装类

大于或等于

为null有效

@DecimalMax

BigDecimalBigInteger、CharSequence,

byte、short、int、long以及包装类

小于或等于

为null有效

@DecimalMin

BigDecimal、BigIntegerCharSequence,

byte、short、int、long以及包装类

大于或等于

为null有效

@Negative

BigDecimal、BigInteger,

byte、short、int、long、float、double以及包装类

负数

为null有效,0无效

@NegativeOrZero

BigDecimal、BigInteger,

byte、short、int、long、float、double以及包装类

负数或零

为null有效

@Positive

BigDecimal、BigInteger,

byte、short、int、long、float、double以及包装类

正数

为null有效,0无效

@PositiveOrZero

BigDecimal、BigInteger,

byte、short、int、long、float、double以及包装类

正数或零

为null有效

@Digits(integer = 3, fraction = 2)

BigDecimal、BigInteger、CharSequence,

byte、short、int、long以及包装类

整数位数和小数位数上限

为null有效

@Length

String

字符串长度范围

@Length

@Range

数值类型和String

指定范围

@Range

其他

注解

支持Java类型

说明

备注

@Pattern

CharSequence

匹配指定的正则表达式

为null有效

@Email

CharSequence

邮箱地址

为null有效,默认正则 '.*'

@Size

CharSequence、Collection、Map、Array

大小范围(length/size>0)

为null有效

@URL

URL地址验证

@URL

  1. 使用

单参数校验

需要在参数前添加注解,而且controller类上必须添加@Validated注解。

@RestController
@RequestMapping("/menu")
@Validated // 单参数校验需要加的注解
public class SysMenuController {@DeleteMapping("/menus")public Result deleteMenu(@NotNull(message = "id不能为空") Long id) {}
}

对象参数校验

先在对象的校验属性上添加注解,然后在Controller方法的对象参数前添加@Valid、@Validated

// 对象
public class Menu {private Long menuId;@NotNull(message =parentId不能为空")private Long parentId;
}
@PostMapping("/menus")
public Result addMenu(@RequestBody @Valid Menu menu, BindingResult result) {
}

对象嵌套

// 对象
public class PagedQueryReqBody<T> {private Integer page_no;private Integer page_row_no;@NotNullprivate String page_flg;@Validprivate T data_request;
}public class DataReqPQ {@NotNullprivate String car_no;
}
// 接口
@PostMapping(value = "/queryParameter")
public Result queryParameter(@RequestBody @Validated PagedQueryReqBody<DataReqPQ> requestMsg, BindingResult result){
}

分组校验

新建组

Validated有自己默认的组 Default.class

public interface Update {
}
public interface Add  extends Default {
}
// 对象
public class User {@NotBlank(message = "id不能为空",groups = {Update.class})private String id;private String name;@NotBlank(message = "密码不能为空",groups = {Add.class})private String password;
}
id属性的校验属于Update分组的校验
password属性的校验属于Add、Default分组的校验

使用分组

使用默认分组:Add分组继承Default,所以校验password,不校验id

@PostMapping("/addUser")
public Resp addUser(@Validated @RequestBody User uer) {
}

使用Update分组:只校验id,不校验password

@PostMapping("/updateUser")
public Resp updateUser(@Validated(Update.class) @RequestBody User user) {
}
  1. 异常处理

全局异常处理类

缺少参数抛出的异常是MissingServletRequestParameterException

单参数校验失败后抛出的异常是ConstraintViolationException

get请求的对象参数校验失败后抛出的异常是BindException

post请求的对象参数校验失败后抛出的异常是MethodArgumentNotValidException

不同异常对象的结构不同,对异常消息的提取方式也就不同。

@Slf4j
@RestControllerAdvice
public class ExceptionAdvice {@ResponseBody@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)// 设置状态码为500@ExceptionHandler(MethodArgumentNotValidException.class)public String postExceptionHandler(MethodArgumentNotValidException e){log.error("执行异常",e);BindingResult exceptions = e.getBindingResult();if (exceptions.hasErrors()) {}}@ResponseBody@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)// 设置状态码为500@ExceptionHandler(ConstraintViolationException.class)public String paramExceptionHandler(ConstraintViolationException e){log.error("执行异常",e);}
}

BindingResult异常

Controller方法的中处理

@PostMapping("addUser")
public Result addUser(@RequestBody @Valid User user,BindingResult result){//校验到错误if (result.hasErrors()) {//获得错误信息列表List<String> errMsgs = result.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(toList());String lists = StringUtils.join(lists, ";");return new Result(“” "", lists);}return new Result(“”, "", null);
}

AOP校验

/**
*将此注解加在需要进行参数校验的方法上,
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ParamValid {
}
@Aspect
@Component
public class ParamValidAspect {private static final Logger log = LoggerFactory.getLogger(ParamValidAspect.class);@Before("@annotation(paramValid)")public void paramValid(JoinPoint point, ParamValid paramValid){Object[] paramObj = point.getArgs();if (paramObj.length > 0){Arrays.stream(paramObj).forEach(e ->{if (e instanceof BindingResult) {BindingResult result = (BindingResult) e;Result errorMap = this.validRequestParams(result);if (errorMap != null){ServletRequestAttributes res = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletResponse response = res.getResponse();response.setCharacterEncoding("UTF-8");response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);response.setStatus(HttpStatus.BAD_REQUEST.value());OutputStream output = null;try {output = response.getOutputStream();String error = objectMapper.writeValueAsString(errorMap);//响应错误信息output.write(error.getBytes("UTF-8"));}catch (IOException e){log.error(e.getMessage());}finally{try{if (output != null){output.close();}} catch (IOException e) {log.error(e.getMessage());}}}}});}}/*** 校验*/private Result validRequestParams(BindingResult result) {if (result.hasErrors()) {List<String> errMsgs = result.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(toList());String lists = StringUtils.join(lists, ";");return new Result("", "", lists);}return null;}
}

相关文章:

SpringBoot使用validator进行参数校验

Validated、Valid和BindingResultBean Validation是Java定义的一套基于注解的数据校验规范&#xff0c;比如Null、NotNull、Pattern等&#xff0c;它们位于 javax.validation.constraints这个包下。hibernate validator是对这个规范的实现&#xff0c;并增加了一些其他校验注解…...

论文复现:风电、光伏与抽水蓄能电站互补调度运行(MATLAB-Yalmip全代码)

论文复现:风电、光伏与抽水蓄能电站互补调度运行(MATLAB-Yalmip全代码) 针对风电、光伏与抽水蓄能站互补运行的问题,已有大量通过启发式算法寻优的案例,但工程上更注重实用性和普适性。Yalmip工具箱则是一种基于MATLAB平台的优化软件工具箱,被广泛应用于工程界优化问题和…...

FastCGI sent in stderr: "PHP message: PHP Fatal error

服务器php7.2卸载安装7.4之后,打开网站一直无法访问,查看nginx错误日志发现一直报这个错误:2023/02/23 11:12:55 [error] 4735#0: *21 FastCGI sent in stderr: &#xff02;PHP message: PHP Fatal error: Uncaught ReflectionException: Class translator does not exist in …...

【数字IC基础】跨时钟域(CDC,Clock Domain Crossing)

文章目录 一、什么是跨时钟域?二、跨时钟域传输的问题?2、1 亚稳态(单bit:两级D触发器(双DFF))2、2 数据收敛(多bit亚稳态)(格雷码编码、握手协议、异步FIFO、DMUX)2、3 多路扇出:(先同步后扇出)2、4 数据丢失(延长输入数据信号):类似脉冲展宽2、5 异步复位(…...

UNI-APP学习

uni-app的基本使用 uni-app介绍 官方网页 uni-app 是一个使用 Vue.js 开发所有前端应用的框架&#xff0c;开发者编写一套代码&#xff0c;可发布到iOS、Android、H5、以及各种小程序&#xff08;微信/支付宝/百度/头条/QQ/钉钉&#xff09;等多个平台。 即使不跨端&#xf…...

编译原理【运行时环境】—什么是活动记录、 活动记录与汇编代码的关系

系列文章戳这里&#x1f447; 什么是上下文无关文法、最左推导和最右推导如何判断二义文法及消除文法二义性何时需要消除左递归什么是句柄、什么是自上而下、自下而上分析什么是LL(1)、LR(0)、LR(1)文法、LR分析表LR(0)、SLR(1)、LR(1)、LALR(1)文法之间的关系编译原理第三章习…...

【Windows Server 2019】发布服务器 | 远程桌面服务的安装与配置 Ⅰ——理论,实验拓扑和安装基于RemoteAPP的RDS

目录1. 理论1.1 什么是远程桌面服务2. 实验拓扑2.1 拓扑说明3. 安装基于RemoteAPP的RDS1. 理论 1.1 什么是远程桌面服务 远程桌面服务 (RDS) 是一个卓越的平台&#xff0c;可以生成虚拟化解决方案来满足每个最终客户的需求&#xff0c;包括交付独立的虚拟化应用程序、提供安全…...

Bootstrap入门到精通(最全最详细)

文章目录前言一、Bootstrap是什么&#xff1f;二、Bootstrap安装方式一&#xff1a;将压缩包下载到本地引入使用方式二&#xff1a;使用Bootstrap官方cdn二.Bootstrap容器下面是屏幕宽度在不同大小时不同容器的显示状态三.Bootstrap栅格系统bootstrap网格系统有以下六个类网格系…...

C/C++每日一练(20230223)

目录 1. 数据合并 2. 回文链表 3. 完美矩形 1. 数据合并 题目描述 将两个从小到大排列的一维数组 (维长分别为 m,n , 其中 m,n≤100) 仍按从小到大的排列顺序合并到一个新的一维数组中&#xff0c;输出新的数组. 输入描述 第 1 行一个正整数 m , 表示第一个要合并的一维…...

c语言中const 是什么意思?(面试)

const关键字使用非常的灵活&#xff0c;在c中&#xff0c;const因位置不同有不同的作用&#xff0c;因情景不同有不同的角色&#xff0c;使用起来也是非常的灵活。 可以定义const常量&#xff0c;具有不可变性。 例如&#xff1a;const int Max100; Max会产生错误; 便于进行类…...

网络工程(三)ensp配置静态路由

配置静态路由 这里选择的路由器是AR2220 因为有三个GE接口 下面说拓扑图 一、定义AR路由ip地址和下一条 AR1system-viewsysname AR1interface g0/0/0ip address 10.0.0.254 8interface g0/0/1ip address 50.0.0.1 8下一条代码[AR1]ip route-static 0.0.0.0 0 50.0.0.2AR2 s…...

深入浅出C++ ——手撕红黑树

文章目录一、红黑树的概念二、红黑树的性质三、红黑树节点的定义四、红黑树的插入操作五、红黑树的验证五、红黑树的删除六、红黑树与AVL树的比较七、红黑树的应用八、红黑树模拟实现一、红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存…...

Linux服务:Nginx服务重写功能

目录 一、重写功能 1、重写功能作用 2、rewrite指令 ①if指令 ②return指令 ③ set指令 ④break指令 3、rewrite标志 ①redirect标志 ②permanent标志 ③break标志 ④last标志 ⑤rewrite标志实验 一、重写功能 1、重写功能作用 重写功能(rewrite)用于实现URL的重…...

3.知识图谱概念和相关技术简介[知识抽取、知识融合、知识推理方法简述],典型应用案例介绍国内落地产品介绍。一份完整的入门指南,带你快速掌握KG知识,芜湖起飞!

1. 知识图谱(KG)的概念 知识图谱(KG)得益于Web的发展(更多的是数据层面),有着来源于KR、NLP、Web、AI多个方面的基因。知识图谱是2012年后的提法,基础还是语义网和本体论。 知识图谱的本质包含: 知识表示——Knowledge Representation基于知识表示的知识库——Knowledge…...

iOS 绿幕技术

绿幕&#xff08;green screen&#xff09;技术&#xff0c;又称 chroma key effect&#xff0c;实际上是将图片上指定颜色设置为透明的图形处理技术&#xff0c;这些透明区域也可以被任意背景图片替换。 这种技术在 视频合成中被广泛使用。iOS 中&#xff0c;通过 CoreImage …...

git 的使用方法(上 - 指令)

目录前言&#xff1a;一、Git 是什么&#xff1f;二、SVN与Git的最主要的区别&#xff1f;三、Git 安装四、git 配置1. 创建仓库 - repository2. 配置3. 工作流与基本操作五、Git 的使用流程1. 仓库中创建 1.txt文件2. 查看工作区的文件状态3. 添加工作区文件到暂存区4. 创建版…...

Windows 平台 oracle11g 单机 打补丁(33883353)

一、从oracle官网下载最新补丁包和打包工具 二、 对数据库及软件作全备 略 三、解压p33883353_112040_MSWIN-x86-64.zip 在33883353文件夹中打开README.html 2.1 OPatch Utility You must use the OPatch utility version 11.2.0.3.34 or later to apply this patch. 必须…...

1个寒假能学会多少网络安全技能?

现在可以看到很多标题都声称三个月内就可以转行网络安全领域&#xff0c;并且成为月入15K的网络工程师。那么&#xff0c;这个寒假的时间能学多少网络安全知识&#xff1f;是否能入门网络安全工程师呢&#xff1f; 答案是肯定的。 虽然网络完全知识是一门广泛的学科&#xff…...

六、肺癌检测-训练指标和数据增强

上一篇文章讲了训练过程和tensorboard可视化&#xff0c;这一篇文章记录下训练指标和数据增强的东西。 五、肺癌检测-数据集训练 training.py model.py_wxyczhyza的博客-CSDN博客 一、目标 1. 记录精度、召回率、F1分数 2. 样本均衡和样本随机化 3. 数据增强 二、要点 1…...

儿童饰品发夹发卡出口美国办理什么认证?

亚马逊美国站上传新产品&#xff0c;很多时候都是需要类目审核的&#xff0c;后台给出要求提供认证&#xff0c;产品类目不同&#xff0c;所需要提供的认证证书是不一样&#xff0c;儿童产品需要提交的是CPC认证&#xff0c;玩具&#xff0c;母婴用品&#xff0c;儿童书包&…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...

深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向

在人工智能技术呈指数级发展的当下&#xff0c;大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性&#xff0c;吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型&#xff0c;成为释放其巨大潜力的关键所在&…...

算法打卡第18天

从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,7…...