SpringBoot参数校验详解
前言
在web开发时,对于请求参数,一般上都需要进行参数合法性校验的,原先的写法时一个个字段一个个去判断,这种方式太不通用了,Hibernate Validator 是 Bean Validation 规范的参考实现,用于在 Java 应用中进行对象的校验。以下是如何在 Spring Boot 项目中安装和使用 Hibernate Validator 的详细步骤。
一、Hibernate Validator参数校验依赖的安装
SpringBoot 2.3以前版本
<!-- Spring Boot Starter Web 包含了 Spring MVC 和 Bean Validation 等常用依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
Springboot从2.3以后,spring-boot-starter-web中不再引入hibernate-validator,需要手动引入。
<!-- Spring Boot Starter Web 包含了 Spring MVC 和 Bean Validation 等常用依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Hibernate Validator 是 Bean Validation 的默认实现 --><dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId></dependency>
二、SpringBoot参数校验异常返回结果类封装
在使用 Spring Boot 进行参数校验时,如果参数不符合要求,会抛出校验异常。为了更好地处理这些异常并返回统一的错误格式,可以通过以下方式进行封装:
1. 使用 @ControllerAdvice 全局异常处理
创建一个全局异常处理类,捕获 MethodArgumentNotValidException 和 ConstraintViolationException,并将其转换为统一的响应格式。
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;@ControllerAdvice
public class GlobalExceptionHandler {// 处理 @Valid 校验异常@ExceptionHandler(MethodArgumentNotValidException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)@ResponseBodypublic Map<String, Object> handleValidationException(MethodArgumentNotValidException ex) {Map<String, Object> errors = new HashMap<>();errors.put("status", HttpStatus.BAD_REQUEST.value());errors.put("message", "Validation failed");Map<String, String> fieldErrors = new HashMap<>();for (FieldError error : ex.getBindingResult().getFieldErrors()) {fieldErrors.put(error.getField(), error.getDefaultMessage());}errors.put("errors", fieldErrors);return errors;}// 处理 @Validated 校验异常@ExceptionHandler(ConstraintViolationException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)@ResponseBodypublic Map<String, Object> handleConstraintViolationException(ConstraintViolationException ex) {Map<String, Object> errors = new HashMap<>();errors.put("status", HttpStatus.BAD_REQUEST.value());errors.put("message", "Validation failed");Map<String, String> fieldErrors = new HashMap<>();Set<ConstraintViolation<?>> violations = ex.getConstraintViolations();for (ConstraintViolation<?> violation : violations) {fieldErrors.put(violation.getPropertyPath().toString(), violation.getMessage());}errors.put("errors", fieldErrors);return errors;}
}
2. 自定义返回结果格式
在返回结果中包含自定义的状态码、错误信息和字段错误列表。
例如:
{"status": 400,"message": "Validation failed","errors": {"fieldName1": "Error message 1","fieldName2": "Error message 2"}
}
3. 参数校验示例
控制器中可以使用 @Valid 或 @Validated 注解进行参数校验:
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import javax.validation.Valid;@RestController
public class UserController {@PostMapping("/users")public ResponseEntity<String> createUser(@Valid @RequestBody UserRequest userRequest) {// 业务逻辑return ResponseEntity.ok("User created successfully");}
}
4. 校验注解
在请求对象中使用 JSR-303/JSR-380 提供的校验注解,例如 @NotNull, @Size, @Email 等。
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;public class UserRequest {@NotBlank(message = "Username is mandatory")@Size(min = 3, max = 20, message = "Username must be between 3 and 20 characters")private String username;@NotBlank(message = "Email is mandatory")@Email(message = "Email should be valid")private String email;// getters and setters
}
通过以上方法,可以将参数校验异常统一封装成一个标准格式的响应结果,便于前端处理。
三、@Valid 和 @Validated之间的区别
@Valid 和 @Validated 是 Spring 框架中用于进行参数验证的两个注解,尽管它们的作用相似,但在使用场景和功能上有一些区别:
1. @Valid
- 作用:
@Valid是 JSR-303/JSR-380 标准中的注解,用于在 Bean Validation 中对对象进行校验。它可以用在方法参数、返回值、或者类字段上。 - 适用范围:
- 对单个对象进行校验。
- 当用在集合类(如
List、Set)或者数组时,它会对集合中的每个元素进行校验。
- 典型用法:
@PostMapping("/user") public ResponseEntity<String> createUser(@Valid @RequestBody User user) {// 如果 user 对象不符合校验规则,会抛出 MethodArgumentNotValidExceptionreturn ResponseEntity.ok("User created"); }
2. @Validated
- 作用:
@Validated是 Spring 提供的一个注解,扩展了@Valid的功能。除了能够进行标准的 Bean Validation 校验外,它还支持分组校验(Group Validation)。 - 适用范围:
- 可以用来对不同的校验场景使用不同的校验规则(通过分组)。
- 主要在 Spring 的
@Service、@Controller等类中用于方法级别的校验。
- 典型用法:
@PostMapping("/user") public ResponseEntity<String> createUser(@Validated(OnCreate.class) @RequestBody User user) {// 如果 user 对象不符合 OnCreate 分组的校验规则,会抛出 MethodArgumentNotValidExceptionreturn ResponseEntity.ok("User created"); }
主要区别:
-
标准 vs. 扩展:
@Valid是标准的 Java Bean Validation 注解。@Validated是 Spring 提供的扩展注解,支持更多功能。
-
分组校验:
@Valid不支持分组校验,只能进行默认的校验。@Validated支持分组校验,允许根据不同的操作或场景应用不同的校验逻辑。
-
使用场景:
- 如果只需要基本的校验,使用
@Valid即可。 - 如果需要在不同的场景下应用不同的校验逻辑,使用
@Validated并结合分组校验。
- 如果只需要基本的校验,使用
希望这些信息能帮你更好地理解这两个注解的区别。
四、常用的校验参数详解
结合 Hibernate Validator 实现。通过在实体类字段或方法参数上使用各种注解,可以轻松进行参数校验。
以下是 Spring Boot 中常用的参数校验注解及其用法详解:
1. 基本校验注解
-
@NotNull:字段不能为
null,但可以为空字符串。@NotNull(message = "Name cannot be null") private String name; -
@NotEmpty:字段不能为
null,也不能为空字符串或空集合。@NotEmpty(message = "List cannot be empty") private List<String> items; -
@NotBlank:字段不能为
null,且去掉首尾空格后,必须至少有一个字符。常用于校验字符串。@NotBlank(message = "Email cannot be blank") private String email; -
@Size:校验字符串、集合、数组的大小或长度。
@Size(min = 2, max = 30, message = "Name must be between 2 and 30 characters") private String name; -
@Min 和 @Max:校验数值型字段的最小值和最大值。
@Min(value = 18, message = "Age must be at least 18") @Max(value = 60, message = "Age must be less than 60") private int age; -
@Email:校验是否为合法的电子邮件格式。
@Email(message = "Email should be valid") private String email; -
@Pattern:使用正则表达式校验字符串的格式。
@Pattern(regexp = "^\\d{10}$", message = "Phone number must be 10 digits") private String phoneNumber; -
@Past 和 @Future:校验日期字段是否在过去或未来。
@Past(message = "Birthday must be in the past") private LocalDate birthday;@Future(message = "Appointment date must be in the future") private LocalDate appointmentDate; -
@AssertTrue 和 @AssertFalse:校验布尔类型字段是否为
true或false。@AssertTrue(message = "Must agree to terms") private boolean agreedToTerms;
2. 组合注解
可以组合多个注解来实现复杂的校验规则。例如,校验一个字段既不为空,又必须符合特定格式:
@NotBlank(message = "Username cannot be blank")
@Pattern(regexp = "^[a-zA-Z0-9]{3,}$", message = "Username must be alphanumeric and at least 3 characters long")
private String username;
3. 分组校验(@Validated)
分组校验可以根据不同场景应用不同的校验规则。需要结合 @Validated 注解来实现。
-
定义分组接口:
public interface CreateGroup {} public interface UpdateGroup {} -
在实体类中应用分组:
@NotNull(groups = UpdateGroup.class, message = "Id cannot be null when updating") private Long id;@NotBlank(groups = CreateGroup.class, message = "Name cannot be blank when creating") private String name; -
在 Controller 方法中指定分组:
@PostMapping("/create") public ResponseEntity<String> createUser(@Validated(CreateGroup.class) @RequestBody User user) {// 校验仅针对 CreateGroup 分组return ResponseEntity.ok("User created"); }@PutMapping("/update") public ResponseEntity<String> updateUser(@Validated(UpdateGroup.class) @RequestBody User user) {// 校验仅针对 UpdateGroup 分组return ResponseEntity.ok("User updated"); }
4. 自定义校验注解
如果内置的校验注解不能满足需求,可以创建自定义校验注解。
-
创建注解:
@Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = MyCustomValidator.class) public @interface MyCustomValidation {String message() default "Invalid value";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {}; } -
实现校验逻辑:
public class MyCustomValidator implements ConstraintValidator<MyCustomValidation, String> {@Overridepublic boolean isValid(String value, ConstraintValidatorContext context) {// 校验逻辑,例如:字符串必须包含 "valid"return value != null && value.contains("valid");} } -
使用自定义注解:
@MyCustomValidation(message = "The value must contain 'valid'") private String customField;
通过这些校验注解和机制,可以在 Spring Boot 中高效地处理参数校验逻辑,确保应用的输入数据符合预期。
通过以上就可以正常使用注解在SpringBoot中完成参数校验功能了!感谢大家的收看 如果感觉有帮助请留下小星星
相关文章:
SpringBoot参数校验详解
前言 在web开发时,对于请求参数,一般上都需要进行参数合法性校验的,原先的写法时一个个字段一个个去判断,这种方式太不通用了,Hibernate Validator 是 Bean Validation 规范的参考实现,用于在 Java 应用中…...
安全基础学习-SHA-1(Secure Hash Algorithm 1)算法
SHA-1(Secure Hash Algorithm 1)是一种密码学哈希函数,用于将任意长度的输入数据(消息)转换成一个固定长度的输出(哈希值或摘要),长度为160位(20字节)。SHA-1的主要用途包括数据完整性验证、数字签名、密码存储等。 1、SHA-1 的特性 定长输出:无论输入数据长度是多…...
leetcode350. 两个数组的交集 II,哈希表
leetcode350. 两个数组的交集 II 给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可…...
基于YOLOv8的缺陷检测任务模型训练
文章目录 一、引言二、环境说明三、缺陷检测任务模型训练详解3.1 PCB数据集3.1.1 数据集简介3.1.2 数据集下载3.1.3 构建yolo格式的数据集 3.2 基于ultralytics训练YOLOv83.2.1 安装依赖包3.2.2 ultralytics的训练规范说明3.2.3 创建训练配置文件3.2.4 下载预训练模型3.2.5 训练…...
【upload]-ini-[SUCTF 2019]CheckIn-笔记
上传图片木马文件后看到,检查的文件内容,包含<? 一句话木马提示 检查的文件格式 用如下图片木马,加上GIF89a绕过图片和<?检查 GIF89a <script languagephp>eval($_POST[cmd])</script> .user.ini实际上就是一个可以由用…...
uniapp条件编译使用教学(#ifdef、#ifndef)
#ifdef //仅在xxx平台使用#ifndef //除了在xxx平台使用#endif // 结束 标识平台APP-PLUSAPPMP微信小程序/支付宝小程序/百度小程序/头条小程序/QQ小程序MP-WEIXIN微信小程序MP-ALIPAY支付宝小程序MP-BAIDU百度小程序MP-TOUTIAO头条小程序MP-QQQQ小程序H5H5APP-PLUS-NVUEApp nv…...
NXP i.MX8系列平台开发讲解 - 4.1.2 GNSS 篇(二) - 卫星导航定位原理
专栏文章目录传送门:返回专栏目录 Hi, 我是你们的老朋友,主要专注于嵌入式软件开发,有兴趣不要忘记点击关注【码思途远】 文章目录 关注星号公众号,不容错过精彩 作者:HywelStar Hi, 我是你们的老朋友HywelStar, 根…...
怎样在 SQL 中对一个包含销售数据的表按照销售额进行降序排序?
在当今数字化商业的浪潮中,数据就是企业的宝贵资产。对于销售数据的有效管理和分析,能够为企业的决策提供关键的支持。而在 SQL 中,对销售数据按照销售额进行降序排序,是一项基础但极其重要的操作。 想象一下,您面前有…...
DIAdem 与 LabVIEW
DIAdem 和 LabVIEW 都是 NI (National Instruments) 公司开发的产品,尽管它们有不同的核心功能和用途,但它们在工程、测试和测量领域中常常一起使用,以形成一个完整的数据采集、分析、处理和报告生成的解决方案。 1. 功能和用途 LabVIEW (Lab…...
UE虚幻引擎可以云渲染吗?应用趋势与挑战了解
虚幻云渲染技术是基于虚幻引擎的云端渲染技术,将虚幻引擎的渲染计算任务通过云计算的方式进行处理和渲染、并将渲染结果传输到终端设备上进行展示。虚幻引擎云渲染技术在近年来得到了迅猛的发展,并在各个领域得到了广泛的应用,包括游戏、电影…...
实战分享:DefenderUI在企业环境中的部署与应用
前言 想象一下,你的电脑就像一座坚固的城堡,但城门却时常被一些不速之客窥探甚至企图入侵;Defender,作为城堡自带的守护者,实力自然不容小觑;但你是否觉得它有时候太过低调,有些隐藏技能还没完…...
中英双语介绍金融经济中的鹰派 (Hawkish)和鸽派 (Dovish)
中文版 在金融和经济政策中,“鹰派”和“鸽派”是两种对货币政策和经济管理有不同立场的群体。 鹰派 (Hawkish) 鹰派倾向于担心通货膨胀的风险,通常支持较高的利率和更紧的货币政策,以防止经济过热和控制物价上涨。具体特征包括࿱…...
Android 开发中常用的布局类型及其选择指南
在 Android 开发过程中,选择正确的布局类型对于构建高效、美观且响应式的用户界面至关重要。本文将介绍 Android 中几种最常用的布局类型,并对比它们的特点和适用场景,帮助开发者们做出明智的选择。 1. LinearLayout - 线性布局 特点: LinearLayout 是最基本的布局类型之一…...
短视频SDK解决方案,降低行业开发门槛
美摄科技匠心打造了一款集前沿技术与极致体验于一体的短视频SDK解决方案,它不仅重新定义了短视频创作的边界,更以行业标杆级的短视频特效,让每一帧画面都闪耀不凡光芒。 【技术赋能,创意无限】 美摄科技的短视频SDK,…...
【C++】String常见函数用法
一、string类对象的常见构造 我们可采取以下的方式进行构造,以下是常用的接口: //生成空字符串 string; //拷贝构造函数 string(const string& str); //用C-string来构造string类对象 string(const char* s); //string类对象中包含n个字符c strin…...
LeetCode49.字母异位词分组
题目大意 给你一个字符串数组,请你将字母异位词组合在一起。可以按任意顺序返回结果列表。 字母异位词是由重新排列源单词的所有字母得到的一个新单词。 思路分析 示例 1: 输入: strs ["eat", "tea", "tan", "ate", &…...
Nginx日志按天分割
需求、日志按照天的单位进行分割存储。 如果你直接百度,可能会搜到很多教你用各种脚本或是三方插件来按天分割的,这边我用nginx服务本身来分割日志。 方法一 通过使用 $time_iso8601 变量和 map 指令,实现了日志文件按天分割的功能。以下是…...
文本摘要简介
文本摘要是从一段长文本中提取出最重要的信息,并生成一个简短而有意义的摘要。这个过程可以分为两种主要方法: 抽取式摘要(Extractive Summarization):从原文中直接提取出关键句子或段落,组成摘要…...
3.MySQL面试题之Redis 和 Mysql 如何保证数据一致性?
Redis 和 MySQL 数据一致性是分布式系统中的一个常见挑战。保证数据一致性通常涉及几种策略,我会详细解释这些策略并提供相应的代码示例。 先更新数据库,再更新缓存 这种方法先更新 MySQL,然后更新或删除 Redis 缓存。 Transactional publ…...
浅谈TCP协议、UDP协议
一、介绍说明 TCP(传输控制协议) 面向连接:TCP在数据传输之前必须建立连接。这通过一个称为三次握手的过程来完成,确保连接的两端都准备好进行数据传输。 可靠性:TCP提供可靠的数据传输,确保数据包正确无…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
