spring中使用@Validated,什么是JSR 303数据校验,spring boot中怎么使用数据校验
文章目录
- 一、JSR 303后台数据校验
- 1.1 什么是 JSR303?
- 1.2 为什么使用 JSR 303?
- 二、Spring Boot 中使用数据校验
- 2.1 基本注解校验
- 2.1.1 使用步骤
- 2.1.2 举例
- @Valid注解
- 全局统一异常处理
- 2.2 分组校验
- 2.2.1 使用步骤
- 2.2.2 举例
- @Validated注解
- @Validated和@Valid的区别
- 2.3 自定义校验注解
- 2.3.1 使用步骤
- 2.3.2 举例
- 2.4 相关注解
- 2.4.1 空检查相关注解
- 2.4.2 长度检查
- 2.4.3 布尔值检查
- 2.4.4 日期检查
- 2.4.5 数值检查
- 2.4.6 其他
一、JSR 303后台数据校验
1.1 什么是 JSR303?
JSR 是 Java Specification Requests 的缩写,即 Java 规范提案。存在各种各样的 JSR,简单的理解为 JSR 是一种 Java 标准。JSR 303 是其中数据检验的一个标准(Bean Validation 1.0 (JSR 303))。
1.2 为什么使用 JSR 303?
-
处理一段业务逻辑,首先要确保数据输入的正确性,所以需要先对数据进行检查,保证数据在语义上的正确性,再根据数据进行下一步的处理。
-
前端可以通过 js 程序校验数据是否合法,后端同样也需要进行校验。而后端最简单的实现就是直接在业务方法中对数据进行处理,但是不同的业务方法可能会出现同样的校验操作,这样就出现了数据的冗余。
-
为了解决这个情况,JSR 303 出现了。JSR 303 使用 Bean Validation,即在 Bean 上添加相应的注解,去实现数据校验。这样在执行业务方法前,都会根据注解对数据进行校验,从而减少自定义的校验逻辑,减少代码冗余。
二、Spring Boot 中使用数据校验
2.1 基本注解校验
之前在 Spring MVC 中介绍了数据校验,也例举了常用的注解。但是使注解生效必须要在 springmvc.xml 中配置,假如没有配置文件(比如在 spring boot)中怎么办?----> 下面详细介绍
spring boot 中需要引入依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2.1.1 使用步骤
1、在相关的 Bean 上标注需要处理的注解,并指定需要提示的信息(若不指定,会从默认配置文件中读取默认的信息)。
2、在相关的方法上,使用 @Valid 注解(或者 @Validated 指定组名)标记需要被校验的数据,否则会不生效。
注意:检测到数据异常后,系统会向外抛出异常,如果做了统一异常处理,可以根据 postman 测试的结果,找到控制台打印出的相应的异常,并处理。
3、处理异常。
-
使用 BindingResult 处理;
-
也可以使用 全局统一异常 处理(@RestControllerAdvice 与 @ExceptionHandler)
全局统一异常处理后续会讲
2.1.2 举例
1、在相关的 Bean 上标注注解,并写上指定信息。
@Data
public class Emp {@NotNull(message = "id 不能为 null")private Integer id;@NotNull(message = "name 不能为 null")private String name;
}
@Valid注解
2、Controller层中使用 @Valid 注解标记需要检测的数据。
@RestController
public class EmpController {@PostMapping("/emp")public String createEmp(@Valid @RequestBody Emp emp) {return "ok";}
}
3、测试时,假如不传 id、name,会抛出 MethodArgumentNotValidException 异常。使用 BindingResult 可以处理异常信息,但 通常使用统一异常处理。
① 使用 BindingResult:
@RestController
public class EmpController {@PostMapping("/emp")public Map createEmp(@Valid @RequestBody Emp emp, BindingResult result) {if (result.hasErrors()) {Map<String, String> map = new HashMap<>();// 获取校验结果,遍历获取捕获到的每个校验结果result.getFieldErrors().forEach(item -> {// 获取校验的信息String message = item.getDefaultMessage(); // 也获取message的值String field = item.getField(); //获取属性名// 存储得到的校验结果map.put(field, message);});return map;}return "ok";}
}
问题:通过上面的步骤,已经可以捕获异常、处理异常,但是每次都是在业务方法中手动处理逻辑,这样的实现,代码肯定会冗余。可以将其抽出,使用 统一异常处理,每次异常发生时,将其捕获。
全局统一异常处理
② 全局统一异常处理:@RestControllerAdvice、@ExceptionHandler
@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(MethodArgumentNotValidException.class)public Map handlerValidException(MethodArgumentNotValidException e) {BindingResult result = e.getBindingResult();Map<String, String> map = new HashMap<>();// 获取校验结果,遍历获取捕获到的每个校验结果result.getFieldErrors().forEach(item ->{// 存储得到的校验结果map.put(item.getField(), item.getDefaultMessage());});return map;}
}
Controller 中不需要再用 BindingResult 去处理数据了。
2.2 分组校验
1、为什么使用 分组校验?
上面的过程,如果出现多个方法,都需要校验 Bean,且校验规则不同的时候,怎么办呢?分组校验就可以去解决该问题,每个分组指定不同的校验规则,不同的方法执行不同的分组,就可以得到不同的校验结果。
2、JSR 303 的每个注解都默认具备三个属性:
- message 用来定义数据校验失败后的提示消息,默认读取配置文件的内容。idea 全局搜索
ValidationMessages.properties
,可以看到默认的信息。 - groups 用来定义分组,它是一个 class 数组,可以指定多个分组。
- payload()
String message() default "{javax.validation.constraints.NotNull.message}";Class<?>[] groups() default { };Class<? extends Payload>[] payload() default { };
2.2.1 使用步骤
1、定义一个空接口,用于指定分组,内部不需要任何实现。
2、指定 注解时,通过 groups 指定分组。用于指定在某个分组条件下,才去执行校验规则。
3、在 Controller 中通过 @Validated 注解指定分组,去指定校验。
注:使用分组校验后,Bean 注解上若不指定分组,则不会执行校验规则。
2.2.2 举例
1、如:创建两个分组接口 AddGroup、UpdateGroup。
AddGroup 用于指定 添加数据 时的校验规则(比如:id、name 均不为 null)。
UpdateGroup 用于指定 修改数据 时的校验规则(比如:name 不允许为 null)。
2、给 Bean 添加注解,并指定分组信息。
@Data
public class Emp {@NotNull(message = "id 不能为 null", groups = {AddGroup.class})private Integer id;@NotNull(message = "name 不能为 null", groups = {AddGroup.class, UpdateGroup.class})private String name;
}
@Validated注解
3、通过 @Validated 注解指定分组,去指定校验
@RestController
public class EmpController {@PostMapping("/emp")public void createEmp(@Validated({AddGroup.class}) @RequestBody Emp emp) {}@PutMapping("/emp")public void UpdateEmp(@Validated({UpdateGroup.class}) @RequestBody Emp emp) {}
}
@Validated和@Valid的区别
-
@Validated:
- Spring 框架特有的注解,是标准 JSR-303 的一个变种,提供了一个分组功能。
- 作用在类上、方法上、方法参数上,不能作用于成员属性上。
-
@Valid:
-
标准 JSR-303 规范的标记型注解。
-
作用在方法、构造函数、方法参数、成员属性上。
-
2.3 自定义校验注解
上面的注解满足不了业务需求时,可以自定义校验注解、然后自定义校验规则。
2.3.1 使用步骤
1、自定义一个校验注解。可以创建一个 ValidationMessages.properties 用于保存默认的 message 信息。
2、自定义一个校验器(即自定义校验规则):实现 ConstraintValidator 接口,并重写相关方法。
-
initialize :初始化,可以获取 自定义的属性的值。
-
isValid :校验,可以获取到实际的值,然后与自定义的属性值进行比较。
3、将校验注解 与 校验器 关联起来。@Constraint(validatedBy = {校验器类.class})
2.3.2 举例
自定义一个校验规则,判断数据长度是否合法。
1、自定义一个校验注解:(比如这里是@TestValid)
@Target({FIELD})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy={JiaoYan.class})
public @interface TestValid {// 提示信息String message() default "{本自定义注解的全类名.message}";class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};/*** 返回一个长度* @return 默认为 5*/int length() default 5;
}
配置文件内容为:
自定义注解的全类名.message=值不能为 Null,且长度不超过 5
2、自定义一个校验器(比如这里是 JiaoYan)
/*** 实现 ConstraintValidator 接口,* 其中 ConstraintValidator 的泛型,一个需要指定自定义的注解,一个需要指定需要获取的值的类型。* 比如:* ConstraintValidator<TestValid, String> 中* TestValid 表示自定义注解* String 表示获取的值的类型* 即定义规则,判断一个 String 的值的长度是否满足条件*/
public class JiaoYan implements ConstraintValidator<TestValid, String> {/*** 用于保存自定义的(默认)长度*/private int length;/*** 初始化方法,获取默认数据* @param test 注解对象*/@Overridepublic void initialize(TestValid test) {length = test.length();}/*** 自定义校验规则,如果 String 为 Null 或者 长度大于 5,则校验失败(返回 false)* @param value 需要校验的值* @param context* @return true 表示校验成功,false 表示校验失败*/@Overridepublic boolean isValid(String value, ConstraintValidatorContext context) {return value == null ? false : length > value.length();}
}
3、使用注解
@Data
public class Emp {@NotNull(message = "id 不能为 null", groups = {AddGroup.class})private Integer id;// 默认@TestValid()@NotNull(message = "name 不能为 null", groups = {AddGroup.class, UpdateGroup.class})private String name;// 自定义@TestValid(length = 10, message = "值不能为 Null 且长度不超过 10", groups = {AddGroup.class})private String email;
}
2.4 相关注解
2.4.1 空检查相关注解
注解 | 注解详情 |
---|---|
@Null | 被指定的注解元素必须为 Null |
@NotNull | 任意类型,不能为 Null,但可以为空,比如:空数组[]、空字符串"" |
@NotBlank | 针对字符串,不能为 Null,且去除前后空格后的字符串长度要大于 0 |
@NotEmpty | 针对字符串、集合、数组,针对字符串时,不能为 Null,且长度要大于 0 |
2.4.2 长度检查
注解 | 注解详情 |
---|---|
@Size | 针对字符串、集合、数组,判断长度是否在给定范围内 |
@Length | 针对字符串,判断长度是否在给定范围内 |
2.4.3 布尔值检查
注解 | 注解详情 |
---|---|
@AssertTrue | 针对布尔值,用来判断布尔值是否为 true |
@AssertFalse | 针对布尔值,用来判断布尔值是否为 false |
2.4.4 日期检查
注解 | 注解详情 |
---|---|
@Past | 针对日期,用来判断当前日期是否为 过去的日期 |
@Future | 针对日期,用来判断当前日期是否为 未来的日期 |
2.4.5 数值检查
注解 | 注解详情 |
---|---|
@Max(value) | 针对字符串、数值,用来判断是否小于等于某个指定值 |
@Min(value) | 针对字符串、数值,用来判断是否大于等于某个指定值 |
2.4.6 其他
注解 | 注解详情 |
---|---|
@Pattern | 验证字符串是否满足正则表达式 |
@Email | 验证字符串是否满足邮件格式 |
@Url | 验证是否满足 url 格式 |
@Digits | 验证数字整数和小数位数,如:@Digits(integer=6, fraction=2) |
文章结束!恭喜你又学会了一个知识点!!!
相关文章:

spring中使用@Validated,什么是JSR 303数据校验,spring boot中怎么使用数据校验
文章目录 一、JSR 303后台数据校验1.1 什么是 JSR303?1.2 为什么使用 JSR 303? 二、Spring Boot 中使用数据校验2.1 基本注解校验2.1.1 使用步骤2.1.2 举例Valid注解全局统一异常处理 2.2 分组校验2.2.1 使用步骤2.2.2 举例Validated注解Validated和Vali…...

实际部署Dify可能遇到的问题:忘记密码、开启HTTPS、知识库文档上传的大小限制和数量限制
背景 前面我们以 docker compose 容器化的方式本地部署了 Dify 社区版,并快速体验了其聊天助手、工作量编排以及智能体(Agent)功能。不过后续实际生产环境使用时遇到了忘记密码、如何开启SSL以支持HTTPS、如何突破知识库文档上传的大小限制和…...
mugen
title: 走进 Mugen:性能测试领域的得力助手 date: ‘2024-12-30’ category: blog tags: Mugen性能测试开源项目系统评估 sig: QA archives: ‘2024-12’ author:way_back summary: Mugen 作为一款优秀的性能测试工具,以其丰富的功能、灵活的配置和精准…...

CannotRetrieveUpdates alert in disconnected OCP 4 cluster解决
环境: Red Hat OpenShift Container Platform (RHOCP) 4 问题: Cluster Version Operator 不断发送警报,表示在受限网络/断开连接的 OCP 4 集群中无法接收更新。 在隔离的 OpenShift 4 集群中看到 CannotRetrieveUpdates 警报: …...

计算机网络 (16)数字链路层的几个共同问题
一、封装成帧 封装成帧是数据链路层的一个基本问题。数据链路层把网络层交下来的数据构成帧发送到链路上,以及把接收到的帧中的数据取出并上交给网络层。封装成帧就是在一段数据的前后分别添加首部和尾部,构成了一个帧。接收端在收到物理层上交的比特流后…...

细说STM32F407单片机通过IIC读写EEPROM 24C02
目录 一、操作说明 二、工程配置 1、时钟、DEBUG、GPIO、USART6、NVIC、Code Generator 2、 IIC2 (1)Master Features组,主设备参数 (2)Slave Features组,从设备参数 三、软件设计 1、KELED 2、E…...

【AimRT】现代机器人通信中间件 AimRT
目录 一、什么是AimRT二、AimRT与ROS22.1 定位与设计2.2 组成与通信方式对比 三、AimRT基本概念3.1 Node、Pkg 和 Module3.2 Protocol、Channel、Rpc 和 Filter3.3 App模式 和 Pkg模式3.4 Executor3.5 Plugin 一、什么是AimRT AimRT 是智元机器人公司自主研发的一款机器人通信…...

Unity 读Excel,读取xlsx文件解决方案
Unity读取表格数据 效果: 思路: Unity可以解析Json,但是读取Excel需要插件的帮助,那就把这个功能分离开,读表插件就只管读表转Json,Unity就只管Json解析,中间需要一个存储空间,使用…...

R基于贝叶斯加法回归树BART、MCMC的DLNM分布滞后非线性模型分析母婴PM2.5暴露与出生体重数据及GAM模型对比、关键窗口识别
全文链接:https://tecdat.cn/?p38667 摘要:在母婴暴露于空气污染对儿童健康影响的研究中,常需对孕期暴露情况与健康结果进行回归分析。分布滞后非线性模型(DLNM)是一种常用于估计暴露 - 时间 - 响应函数的统计方法&am…...
【信息系统项目管理师】高分论文:论信息系统项目的沟通管理(信息管理服务一体化平台)
更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 论文一、事预则立,规划沟通管理二、提升支持,管理沟通三、观察偏差,监督沟通论文 2022年2月,我公司承建某省退役军人信息管理服务一体化平台项目,由于本人具有较丰富的项目管理经验,同时也是一名退伍军人…...

物联网工厂可视化监控平台:为智能制造打造的可视化大屏
01行业背景 随着技术的不断进步,物联网(IoT)已经成为推动数字化转型的核心力量。物联网通过连接各种设备和传感器,实现数据的实时收集、传输和分析,为各行各业带来了革命性的变化。随着5G、云计算、大数据等技术的成熟…...

3、redis的高可用
主从复制 主从复制:这是redis高可用的基础。哨兵模式和集群都是建立在此基础之上。 主从模式和数据库的主从模式是一样的,主负责写入,然后把写入的数据同步到从,从节点只能读不能写。read only。 不能做高可用的切换ÿ…...

数据结构--顺序表(详解)
欢迎大家来到我的博客~欢迎大家对我的博客提出指导,有错误的地方会改进的哦~点击这里了解更多内容 目录 一、线性表二、顺序表 一、线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结…...
Day62 图论part11
Floyd 算法精讲 Floyd 算法代码很简单,但真正理解起原理 还是需要花点功夫,大家在看代码的时候,会发现 Floyd 的代码很简单,甚至看一眼就背下来了,但我为了讲清楚原理,本篇还是花了大篇幅来讲解。 代码随想…...
git clone 超时
git clone 超时 参考 https://blog.csdn.net/qq_45906972/article/details/142214187?utm_mediumdistribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0-142214187-blog-137158358.235v43pc_blog_bottom_relevance_base8&spm1001.2101.3001.…...

WPF编程excel表格操作
WPF编程excel表格操作 摘要NPOI安装封装代码测试代码 摘要 Excel操作几种方式 使用开源库NPOI(常用,操作丰富)使用Microsoft.Office.Interop.Excel COM组件(兼容性问题)使用OpenXml(效率高)使用OleDb(过时) NPOI安装 封装代码 using System; using System.IO; u…...

Day10补代码随想录 理论基础|232.用栈实现队列|225.用队列实现栈|20.有效的括号|1047.删除字符串中的所有相邻重复项
栈和队列理论基础 抽象认识 栈是先进后出(FIFO),队列是先进先出(LIFO) 队首(先进))队尾(后进)栈顶(后进)栈底(先进) 栈(Stack) 只在一端进行进出操作(只在一端进一端出)像个篮球框,取用篮球从一端进出。 /进栈 int a[1000];//足够大的栈空间 int top-1…...

【Devops】什么是Devops?(Development+Operations)和运维的区别?
DevOps(Development Operations)是一种将开发(Development)和运维(Operations)团队结合在一起的文化和实践,目的是通过自动化、协作和持续反馈来加快软件的开发、部署和运维的周期,…...

基于NodeMCU的物联网电灯控制系统设计
最终效果 基于NodeMCU的物联网电灯控制系统设计 小程序关灯 上图展现了小程序关灯过程的数据传输过程:用户下达关灯指令→小程序下发关灯指令→MQTT服务器接收关灯指令→下位机接收与处理关灯指令。 项目介绍 该项目是“物联网实验室监测控制系统设计(…...

Linux驱动开发 IIC I2C驱动 编写APP访问EEPROM AT24C02
在嵌入式开发中,I2C(Inter-Integrated Circuit)是一种常用的串行通信协议,广泛应用于与外设(如 EEPROM、传感器、显示屏等)进行数据交换。AT24C02 是一种常见的 I2C EEPROM 存储器,它提供 2Kbit…...

label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...

【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...

day36-多路IO复用
一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...

群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...
MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释
以Module Federation 插件详为例,Webpack.config.js它可能的配置和含义如下: 前言 Module Federation 的Webpack.config.js核心配置包括: name filename(定义应用标识) remotes(引用远程模块࿰…...