Validation - Spring Boot项目中参数检验的利器

什么是Validation

Sping Boot官方原文:

When it comes to validating user input, Spring Boot provides strong support for this common, yet critical, task straight out of the box.

Although Spring Boot supports seamless integration with custom validators, the de-facto standard for performing validation is Hibernate Validator, the Bean Validation framework’s reference implementation.

Validation是Spring Boot官方提供的一个参数检验的工具,通常负责验证用户输入,也就是在从前端获取请求时对请求中包含的信息参数进行检验,避免了进入后端检验这个流程的耗时与逻辑编写

为什么要使用Validation

Validation在Spring Boot架构的分布式项目当中比较常见,其优点我总结为:

  • 与后端逻辑分离,做到了解耦
  • 使用简单,只需要在需要进行参数检验的参数(DTO层)上增加一个注释即可,不需要编写大量接口和实现代码
  • 官方支持,使用稳定

接下来我们将通过前两个角度来看看Validation是怎样简单上手使用的,我将使用我的学习项目作为示例

如何使用Validation

在一种情况下,比如我们设计数据库表的时候,往往会有一些字段包含实际意义,比如邮箱或电话号码,这些字段与分配的随机id不同,在现实中有一定的规范;另一种情况下,比如我们的用户设置初始密码时,我们也通常会要求用户至少输入6位,有时还会要求至少有一位大写字母等,这时我们就需要对用户输入的数据进行检验,检查这些数据是否符合实际规范或者我们的要求,此时就可以用上Validation

比如在我的项目中,作为一个电商平台,有用户表如下:

public class User {private Long id;private String username;private String password;private String phone;private String email;private Date registerTime;private Integer status;private String realName;private String address;
}

电商平台会出现用户注册的场景,于是我们就要定义用户注册时返回的数据的DTO类

public class UserRegisterDTO {@NotBlank(message = "用户名不能为空")private String username;@NotBlank(message = "密码不能为空")@Size(message = "密码长度至少为6", min = 6)private String password;@NotBlank(message = "电话号码不能为空")@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")private String phone;@NotBlank(message = "邮箱不能为空")@Email(message = "邮箱格式不正确")private String email;
}

在注册时,我们就需要规范用户输入的这些信息,所有信息都是必要的不能为空,同时密码有长度限制,电话号码有其固定格式,邮箱同理,我们在这里就可以通过Validation的注释来告诉系统,在把用户返回的这些数据包装成对应的DTO类时,需要进行检查

再具体一点,我们怎么通知系统呢

首先我们需要添加依赖,比如我的项目中:

        <dependency><groupId>jakarta.validation</groupId><artifactId>jakarta.validation-api</artifactId><version>3.1.1</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>

我做的是一个微服务项目,目前上述的代码都位于用户模块,因此这个依赖我也是添加在我用户模块的子pom中,有了这个依赖,我们就可以开始使用Validation

接着我们需要在对应的API中声明,告诉系统我们在处理这个请求之前需要对其参数进行检验,比如我注册的Restful API:

    // 注册用户@PostMapping("/register")public Result<Boolean> register(@Valid @RequestBody UserRegisterDTO dto) {return userService.register(dto) ?Result.ok(true) :Result.fail("Register Failed");}

只有在这里指明了@Valid这个注释,系统才会对其进行Validation相关处理

接着我们就要进一步对参数进行注释,正如我之前给出的代码,在DTO层对应的参数前添加相应的注释即可,一般来说,validation注释有以下几种:

  • @AssertFalse:被注解的元素必须为false
  • @AssertTrue:被注解的元素必须为true
  • @DecimalMax(value):被注解的元素必须是一个数字,其值必须小于等于指定的最大值
  • @DecimalMin(value):被注解的元素必须是一个数字,其值必须大于等于指定的最小值
  • @Digits(integer, fraction):被注解的元素必须是一个数字,其值必须在可接受的范围内
  • @Future:被注解的元素必须是一个将来的日期
  • @Max(value):被注解的元素必须是一个数字,其值必须小于等于指定的最大值
  • @Min(value):被注解的元素必须是一个数字,其值必须大于等于指定的最小值
  • @NotNull:被注解的元素必须不为null
  • @Null:被注解的元素必须为null
  • @Past:被注解的元素必须是一个过去的日期
  • @Pattern(regex, flag):被注解的元素必须符合指定的正则表达式
  • @Size(min, max):被注解的元素的大小必须在指定的范围内
  • @Email:被注解的元素必须是电子邮件地址
  • @NotEmpty:被注解的元素不能为null,并且长度必须大于0
  • @NotBlank:被注解的元素为字符串,并且被trim()以后length要大于0
  • @Range(min, max):被注解的元素必须在合适的范围内
  • @URL:被注解的元素必须是一个有效的URL

在元素之前添加相应的注释,项目启动后,把用户返回的参数包装成DTO类对象时就会进行检查

但是只检查出来了,最多也就会返回400的错误代码,前端只是了解到有错误,但是无法对错误进行定位,于是此时我们就需要进一步处理

自定义Result类,用来统一管理前端请求的处理结果

public class Result<T> {private Integer code;private String msg;private T data;public static <T> Result<T> ok(T data) {Result<T> r = new Result<>();r.setCode(200);r.setMsg("success");r.setData(data);return r;}public static <T> Result<T> fail(String msg) {Result<T> r = new Result<>();r.setCode(500);r.setMsg(msg);return r;}
}

自定义异常处理类,用于对运行时错误进行处理

@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(MethodArgumentNotValidException.class)public Result<?> handleValidationException(MethodArgumentNotValidException ex) {String errorMsg = ex.getBindingResult().getFieldError().getDefaultMessage();return Result.fail(errorMsg);}
}

有了这两段代码,项目启动后就有了自定义的对运行时错误进行定位处理的能力,比如用户注册时输入的初始密码小于6位,通过Validation注释检查出了这一错误,然后汇报给GlobalExceptionHandler类,它就将错误信息包装,并最终包装成Result类,返回给前端,这样前端就能看见具体的错误信息,比如我测试如下:

我在Postman中进行用户注册测试,这是注册的body json部分:

{"username": "testValid6","password": "five","email": "12345678","phone": "12345678"
}

最后返回了结果:

{"timestamp": "2025-07-19T04:59:28.091+00:00","status": 400,"error": "Bad Request","trace": 略"message": "Validation failed for object='userRegisterDTO'. Error count: 3","errors": [{"codes": ["Email.userRegisterDTO.email","Email.email","Email.java.lang.String","Email"],"arguments": [{"codes": ["userRegisterDTO.email","email"],"arguments": null,"defaultMessage": "email","code": "email"},[],{"arguments": null,"defaultMessage": ".*","codes": [".*"]}],"defaultMessage": "邮箱格式不正确","objectName": "userRegisterDTO","field": "email","rejectedValue": "12345678","bindingFailure": false,"code": "Email"},{"codes": ["Pattern.userRegisterDTO.phone","Pattern.phone","Pattern.java.lang.String","Pattern"],"arguments": [{"codes": ["userRegisterDTO.phone","phone"],"arguments": null,"defaultMessage": "phone","code": "phone"},[],{"arguments": null,"defaultMessage": "^1[3-9]\\d{9}$","codes": ["^1[3-9]\\d{9}$"]}],"defaultMessage": "手机号格式不正确","objectName": "userRegisterDTO","field": "phone","rejectedValue": "12345678","bindingFailure": false,"code": "Pattern"},{"codes": ["Size.userRegisterDTO.password","Size.password","Size.java.lang.String","Size"],"arguments": [{"codes": ["userRegisterDTO.password","password"],"arguments": null,"defaultMessage": "password","code": "password"},2147483647,6],"defaultMessage": "密码长度至少为6","objectName": "userRegisterDTO","field": "password","rejectedValue": "five","bindingFailure": false,"code": "Size"}],"path": "/user/register"
}

可以看出,这里按照DTO设计的参数的顺序,通通给出了错误的信息,这样就能够精准地定位错误,前端也就可以对其做相应的处理

总结

整体来说,Validation将原先需要一个API一个API编写的参数检验逻辑简化至如此方便,可以说是Spring Boot项目中官方提供的一个参数检验的利器了,对参数标注只需要注释,错误处理可以统一编写错误处理类,前端也可以清晰地看见具体的错误,能够极大地简化这部分逻辑的开发,省去繁琐的重复性工作

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/90070.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/90070.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/90070.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云服务器VS虚拟主机:如何抉择?

开篇引入在当今数字化浪潮中&#xff0c;无论是个人站长想要搭建独具风格的博客&#xff0c;展示自己的生活感悟与专业见解&#xff1b;还是中小企业期望构建官方网站&#xff0c;拓展线上业务版图&#xff0c;提升品牌知名度&#xff1b;亦或是大型互联网企业筹备高并发的电商…

不同相机CMOS噪点对荧光计算的影响

摘要&#xff1a;荧光成像是生物医学、材料科学等领域的重要研究手段&#xff0c;其成像质量高度依赖传感器噪声特性。本文系统分析CMOS传感器噪声类型及其对荧光信号计算的影响机制&#xff0c;结合实验数据探讨不同CMOS架构的噪声表现差异&#xff0c;提出针对性优化策略。研…

docker 常见命令使用记录

1. swarm 集群 1. 集群创建 # 创建集群管理节点&#xff0c; --advertise-addr 指定节点管理通信地址&#xff0c;--data-path-addr 指定容器通信地址 docker swarm init --advertise-addr 1.14.138.35 --data-path-addr 1.14.138.35# --advertise-addr 指明当前work节点的…

KRaft 角色状态设计模式:从状态理解 Raft

这些状态类是 Raft 协议行为的核心载体。它们包含转移逻辑 和 节点在特定状态下的所有行为和数据。QuorumState它是 KRaft 客户端实现中状态管理的核心&#xff0c;扮演着“状态机上下文&#xff08;Context&#xff09;”和“状态转换协调者”的关键角色。QuorumState 是整个 …

Linux的磁盘存储管理实操——(上)

一、Linux的设备文件分类 Linux的设备文件分类1、在Linux系统中设备文件是用来与外接交互的接口&#xff0c;它将内核中的硬件设备与文件系统关联起来&#xff0c;让用户可以像操作普通文件一样来操作硬件设备&#xff0c;同时也为开发者提供了方便而强大的应用程序接口。 2、L…

内核bpf的实现原理

bpftrace能帮我们干什么&#xff1f;1、统计 tcp连接的生命时长、2、统计mysql执行一条sql语句的时间3、统计redis执行命令的时间、 4、对文件进行一次读或者写的时间。 常用命令&#xff1a; bpftrace -e Begin { printf("hello\n"); } bpftrace -l *enter_accep…

前端npm配置Nexus为基础仓库

步骤&#xff1a; 一、Nexus仓库配置 新增npm仓库,具体详解见 Nexus私有仓库配置&#xff0c;解释 注&#xff1a;Nexus的版本需要至少3.38以上&#xff0c;不然会出现npm install 时npm的审计功能报错&#xff0c;导致install失败。虽然在3.38以后不会报400错误&#xff0c…

数据结构 之 【排序】(直接插入排序、希尔排序)

目录 1.直接插入排序 1.1直接插入排序的思想 1.2直接插入排序的代码逻辑&#xff1a; 1.3 直接插入排序图解 1.4单趟排序代码(单个元素的排序逻辑) 1.5完整排序代码 1.6直接插入排序的时间复杂度与空间复杂度 1.7直接插入排序的优势 2.希尔排序(缩小增量排序) 2.1…

Laravel 后台登录 403 Forbidden 错误深度解决方案-优雅草卓伊凡|泡泡龙

Laravel 后台登录 403 Forbidden 错误深度解决方案-优雅草卓伊凡|泡泡龙一顿操作猛如虎&#xff0c;一看结果250&#xff0c;必须记录&#xff0c;必须记录&#xff0c;&#xff01;今天弄了很久关于我们2023年的产品系统蜻蜓T会议系统专业版&#xff0c;然后终于搞好了密码也重…

Newline全场景方案闪耀2025中国智慧生活大会

7月15日 — 16日&#xff0c;由中国电子视像行业协会等权威机构指导的2025 CIC中国智慧生活大会在京召开。Newline作为视像协会PID分会副会长单位携全场景智慧办公解决方案亮相&#xff0c;首席营销官李宇鹏受邀出席领袖圆桌环节&#xff0c;与腾讯云、京东方、创维、TCL、小猿…

Edge浏览器地址栏默认搜索引擎设置指南

前言 Microsoft Edge 浏览器允许用户自定义地址栏默认搜索引擎&#xff0c;只是设置入口隐藏比较深&#xff0c;以版本 137.0.3296.83 (正式版本) (64 位)为例详细记录设置地址栏默认搜索引擎步骤&#xff1a; Edge 设置默认搜索引擎步骤 通过设置界面修改 打开Edge设置&#x…

Python eval函数详解 - 用法、风险与安全替代方案

Python eval函数详解 - 用法、风险与安全替代方案在Python中&#xff0c;eval() 是一个内置函数&#xff0c;用于解析并执行传入的字符串形式的表达式。它能够将字符串动态地转换为有效的Python代码并运行。虽然 eval() 功能强大&#xff0c;但其使用也伴随着潜在的安全风险。本…

Webpack5 新特性与详细配置指南

一、Webpack5 新特性 内置 Asset Modules&#xff08;资源模块&#xff09; 替代 file-loader、url-loader、raw-loader 等&#xff0c;统一资源处理方式。四种类型&#xff1a;asset/resource&#xff1a;导出文件 URL&#xff08;等同 file-loader&#xff09;。asset/inli…

笼子在寻找一只鸟:解读生活的隐形陷阱

想象一个闪闪发光的笼子&#xff0c;敞开着门&#xff0c;在世界中游荡&#xff0c;寻找一只鸟儿。这画面是不是有点奇怪&#xff1f;这是卡夫卡的格言“一个笼子在寻找一只鸟”带给我们的奇思妙想。通常&#xff0c;鸟儿自由翱翔&#xff0c;笼子静静等待&#xff0c;但卡夫卡…

低空经济展 | 约克科技携小型化测试设备亮相2025深圳eVTOL展

全球低空经济与eVTOL产业盛会——2025深圳eVTOL展&#xff0c;将于2025年9月23日至25日在深圳坪山燕子湖国际会展中心盛大启幕&#xff01; 本届展会以“低空经济eVTOL航空应急救援商载大型无人运输机”为核心&#xff0c;预计汇聚200位发言嘉宾、500家顶尖展商及15,000位专业观…

数学专业转行做大数据容易吗?需要补什么?

高考志愿选择数学专业是一个面向未来的决定。数学作为基础学科&#xff0c;其严谨的逻辑训练和抽象思维能力培养&#xff0c;为后续专业发展提供了广泛的可能性。在数字化时代背景下&#xff0c;数学专业毕业生在数据科学、人工智能等领域的竞争优势明显。大学期间推荐考CDA数据…

物联网系统中-设备管理定义方法

物联网系统中的设备管理是指对联网物理设备进行全生命周期监控、配置、维护和优化的系统性过程。它涵盖了从设备接入到退役的各个环节&#xff0c;是物联网平台的核心能力&#xff0c;确保设备安全、稳定、高效地运行并产生价值。 以下是设备管理的详细定义与核心组成部分&…

java和ptyhon对比

&#x1f4dd; ​1. 语言特性对比​​维度​​Java​​Python​​语法风格​静态类型&#xff0c;需显式声明变量类型&#xff1b;代码冗长&#xff08;需分号、大括号&#xff09;动态类型&#xff0c;变量类型自动推断&#xff1b;简洁&#xff08;缩进代替大括号&#xff0c…

UI测试解决方案TestComplete:助力小团队端到端测试全覆盖

面对软件多平台部署的复杂环境与有限的人力资源&#xff0c;小团队在追求端到端测试覆盖时常常陷入困境&#xff1a;既要确保应用在Windows、macOS、Linux及iOS、Android等碎片化平台上的稳定兼容&#xff0c;又要应对脚本重复编写耗时费力、测试效率低下的挑战&#xff0c;同时…

【Android】事件、绘制坐标系相关

一&#xff0c;事件坐标系即MotionEvent事件下发的坐标系&#xff0c;其坐标轴如下MotionEvent#offsetLocation方法可调整坐标原点&#xff0c;以影响MotionEvent#getX&#xff0c;MotionEvent#getY值&#xff0c;以匹配子View的坐标参考系&#xff0c;进而进行事件处理。注意&…