一坨一坨 if/else 参数校验,被 SpringBoot 参数校验组件整干净了
ztj100 2025-05-11 19:46 4 浏览 0 评论
来源:
https://mp.weixin.qq.com/s/ZVOiT-_C3f-g7aj3760Q-g
数据的校验的重要性就不用说了,即使在前端对数据进行校验的情况下,我们还是要对传入后端的数据再进行一遍校验,避免用户绕过浏览器直接通过一些 HTTP 工具直接向后端请求一些违法数据。
最普通的做法就像下面这样。我们通过 if/else 语句对请求的每一个参数一一校验。
这样的代码,小伙伴们在日常开发中一定不少见,很多开源项目都是这样对请求入参做校验的。
但是,不太建议这样来写,这样的代码明显违背了 单一职责原则。大量的非业务代码混杂在业务代码中,非常难以维护,还会导致业务层代码冗杂!
实际上,我们是可以通过一些简单的手段对上面的代码进行改进的!这也是本文主要要介绍的内容!
废话不多说!下面我会结合自己在项目中的实际使用经验,通过实例程序演示如何在 SpringBoot 程序中优雅地的进行参数验证(普通的 Java 程序同样适用)。
不了解的朋友一定要好好看一下,学完马上就可以实践到项目上去。
并且,本文示例项目使用的是目前最新的 Spring Boot 版本 2.4.5!(截止到 2021-04-21)
示例项目源代码地址:https://github.com/CodingDocs/springboot-guide/tree/master/source-code/bean-validation-demo。
添加相关依赖
如果开发普通 Java 程序的的话,你需要可能需要像下面这样依赖:
不过,相信大家都是使用的 Spring Boot 框架来做开发。
基于 Spring Boot 的话,就比较简单了,只需要给项目添加上 spring-boot-starter-web 依赖就够了,它的子依赖包含了我们所需要的东西。另外,我们的示例项目中还使用到了 Lombok。
但是!!!Spring Boot 2.3 1 之后,spring-boot-starter-validation 已经不包括在了 spring-boot-starter-web中,需要我们手动加上!
验证 Controller 的输入
验证请求体
验证请求体即使验证被 @RequestBody 注解标记的方法参数。
PersonController
我们在需要验证的参数上加上了@Valid注解,如果验证失败,它将抛出MethodArgumentNotValidException。默认情况下,Spring 会将此异常转换为 HTTP Status 400(错误请求)。
PersonRequest
我们使用校验注解对请求的参数进行校验!
正则表达式说明:
- ^string : 匹配以 string 开头的字符串
- string$ :匹配以 string 结尾的字符串
- ^string$ :精确匹配 string 字符串
- (^Man$|^Woman$|^UGM$) : 值只能在 Man,Woman,UGM 这三个值中选择
GlobalExceptionHandler
自定义异常处理器可以帮助我们捕获异常,并进行一些简单的处理。如果对于下面的处理异常的代码不太理解的话,可以查看这篇文章 《SpringBoot 处理异常的几种常见姿势》。
通过测试验证
下面我通过 MockMvc 模拟请求 Controller 的方式来验证是否生效。当然了,你也可以通过 Postman 这种工具来验证。
使用 Postman 验证
验证请求参数
验证请求参数(Path Variables 和 Request Parameters)即是验证被 @PathVariable 以及 @RequestParam 标记的方法参数。
PersonController
一定一定不要忘记在类上加上 Validated 注解了,这个参数可以告诉 Spring 去校验方法参数。
ExceptionHandler
通过测试验证
使用 Postman 验证
验证 Service 中的方法
我们还可以验证任何 Spring Bean 的输入,而不仅仅是 Controller 级别的输入。通过使用@Validated和@Valid注释的组合即可实现这一需求!
一般情况下,我们在项目中也更倾向于使用这种方案。
一定一定不要忘记在类上加上 Validated 注解了,这个参数可以告诉 Spring 去校验方法参数。
通过测试验证:
输出结果如下:
name 不能为空
sex 值不在可选范围
Validator 编程方式手动进行参数验证
某些场景下可能会需要我们手动校验并获得校验结果。
我们通过 Validator 工厂类获得的 Validator 示例。另外,如果是在 Spring Bean 中的话,还可以通过@Autowired 直接注入的方式。
@Autowired
Validator validate
具体使用情况如下:
输出结果如下:
sex 值不在可选范围
name 不能为空
自定以 Validator(实用)
如果自带的校验注解无法满足你的需求的话,你还可以自定义实现注解。
案例一:校验特定字段的值是否在可选范围
比如我们现在多了这样一个需求:PersonRequest 类多了一个 Region 字段,Region 字段只能是China、China-Taiwan、China-HongKong这三个中的一个。
第一步,你需要创建一个注解 Region。
第二步,你需要实现 ConstraintValidator接口,并重写isValid 方法。
现在你就可以使用这个注解:
@Region
private String region;
通过测试验证
使用 Postman 验证
案例二:校验电话号码
校验我们的电话号码是否合法,这个可以通过正则表达式来做,相关的正则表达式都可以在网上搜到,你甚至可以搜索到针对特定运营商电话号码段的正则表达式。
PhoneNumber.java
PhoneNumberValidator.java
搞定,我们现在就可以使用这个注解了。
通过测试验证
使用验证组
验证组我们基本是不会用到的,也不太建议在项目中使用,理解起来比较麻烦,写起来也比较麻烦。简单了解即可!
当我们对对象操作的不同方法有不同的验证规则的时候才会用到验证组。
我写一个简单的例子,你们就能看明白了!
1.先创建两个接口,代表不同的验证组
public interface AddPersonGroup {
}
public interface DeletePersonGroup {
}
2.使用验证组
通过测试验证:
验证组使用下来的体验就是有点反模式的感觉,让代码的可维护性变差了!尽量不要使用!
常用校验注解总结
JSR303 定义了 Bean Validation(校验)的标准 validation-api,并没有提供实现。Hibernate Validation是对这个规范/规范的实现 hibernate-validator,并且增加了 @Email、@Length、@Range 等注解。Spring Validation 底层依赖的就是Hibernate Validation。
JSR 提供的校验注解:
- @Null 被注释的元素必须为 null
- @NotNull 被注释的元素必须不为 null
- @AssertTrue 被注释的元素必须为 true
- @AssertFalse 被注释的元素必须为 false
- @Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
- @Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
- @DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
- @DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
- @Size(max=, min=) 被注释的元素的大小必须在指定的范围内
- @Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
- @Past 被注释的元素必须是一个过去的日期
- @Future 被注释的元素必须是一个将来的日期
- @Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
Hibernate Validator 提供的校验注解:
- @NotBlank(message =) 验证字符串非 null,且长度必须大于 0
- @Email 被注释的元素必须是电子邮箱地址
- @Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
- @NotEmpty 被注释的字符串的必须非空
- @Range(min=,max=,message=) 被注释的元素必须在合适的范围内
拓展
经常有小伙伴问到:“@NotNull 和 @Column(nullable = false) 两者有什么区别?”
我这里简单回答一下:
- @NotNull是 JSR 303 Bean 验证批注,它与数据库约束本身无关。
- @Column(nullable = false) : 是 JPA 声明列为非空的方法。
总结来说就是即前者用于验证,而后者则用于指示数据库创建表的时候对表的约束。
- 上一篇:用了这两款插件,同事再也不说我代码写的烂了
- 下一篇:Java中的空指针怎么处理?
相关推荐
-
- SpringBoot如何实现优雅的参数校验
-
平常业务中肯定少不了校验,如果我们把大量的校验代码夹杂到业务中,肯定是不优雅的,对于一些简单的校验,我们可以使用java为我们提供的api进行处理,同时对于一些...
-
2025-05-11 19:46 ztj100
- Java中的空指针怎么处理?
-
#暑期创作大赛#Java程序员工作中遇到最多的错误就是空指针异常,无论你多么细心,一不留神就从代码的某个地方冒出NullPointerException,令人头疼。...
- 一坨一坨 if/else 参数校验,被 SpringBoot 参数校验组件整干净了
-
来源:https://mp.weixin.qq.com/s/ZVOiT-_C3f-g7aj3760Q-g...
- 用了这两款插件,同事再也不说我代码写的烂了
-
同事:你的代码写的不行啊,不够规范啊。我:我写的代码怎么可能不规范,不要胡说。于是同事打开我的IDEA,安装了一个插件,然后执行了一下,规范不规范,看报告吧。这可怎么是好,这玩意竟然给我挑出来这么...
- SpringBoot中6种拦截器使用场景
-
SpringBoot中6种拦截器使用场景,下面是思维导图详细总结一、拦截器基础...
- 用注解进行参数校验,spring validation介绍、使用、实现原理分析
-
springvalidation是什么在平时的需求开发中,经常会有参数校验的需求,比如一个接收用户注册请求的接口,要校验用户传入的用户名不能为空、用户名长度不超过20个字符、传入的手机号是合法的手机...
- 快速上手:SpringBoot自定义请求参数校验
-
作者:UncleChen来源:http://unclechen.github.io/最近在工作中遇到写一些API,这些API的请求参数非常多,嵌套也非常复杂,如果参数的校验代码全部都手动去实现,写起来...
- 分布式微服务架构组件
-
1、服务发现-Nacos服务发现、配置管理、服务治理及管理,同类产品还有ZooKeeper、Eureka、Consulhttps://nacos.io/zh-cn/docs/what-is-nacos...
- 优雅的参数校验,告别冗余if-else
-
一、参数校验简介...
- Spring Boot断言深度指南:用断言机制为代码构筑健壮防线
-
在SpringBoot开发中,断言(Assert)如同代码的"体检医生",能在上线前精准捕捉业务逻辑漏洞。本文将结合企业级实践,解析如何通过断言机制实现代码自检、异常预警与性能优化三...
- 如何在项目中优雅的校验参数
-
本文看点前言验证数据是贯穿所有应用程序层(从表示层到持久层)的常见任务。通常在每一层实现相同的验证逻辑,这既费时又容易出错。为了避免重复这些验证,开发人员经常将验证逻辑直接捆绑到域模型中,将域类与验证...
- SpingBoot项目使用@Validated和@Valid参数校验
-
一、什么是参数校验?我们在后端开发中,经常遇到的一个问题就是入参校验。简单来说就是对一个方法入参的参数进行校验,看是否符合我们的要求。比如入参要求是一个金额,你前端没做限制,用户随便过来一个负数,或者...
- 28个验证注解,通过业务案例让你精通Java数据校验(收藏篇)
-
在现代软件开发中,数据验证是确保应用程序健壮性和可靠性的关键环节。JavaBeanValidation(JSR380)作为一个功能强大的规范,为我们提供了一套全面的注解工具集,这些注解能够帮...
- Springboot @NotBlank参数校验失效汇总
-
有时候明明一个微服务里的@Validated和@NotBlank用的好好的,但就是另一个里不能用,这时候问题是最不好排查的,下面列举了各种失效情况的汇总,供各位参考:1、版本问题springbo...
- 这可能是最全面的Spring面试八股文了
-
Spring是什么?Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- idea eval reset (50)
- vue dispatch (70)
- update canceled (42)
- order by asc (53)
- spring gateway (67)
- 简单代码编程 贪吃蛇 (40)
- transforms.resize (33)
- redisson trylock (35)
- 卸载node (35)
- np.reshape (33)
- torch.arange (34)
- node卸载 (33)
- npm 源 (35)
- vue3 deep (35)
- win10 ssh (35)
- exceptionininitializererror (33)
- vue foreach (34)
- idea设置编码为utf8 (35)
- vue 数组添加元素 (34)
- std find (34)
- tablefield注解用途 (35)
- python str转json (34)
- java websocket客户端 (34)
- tensor.view (34)
- java jackson (34)