点击上方蓝色字体关注我吧

一起学习,一起进步,做积极的人!

场景描述:

你还在业务代码或是控制层中校验接口传入参数的有效性和合法性吗?还是只做了前端参数校验,后端接口直接放行?这样的话,程序运行的正确性和健壮性如何保证?还有就是接口参数校验太繁琐了,而且代码编写量大。

今天我们就来讲讲Spring Boot Validate 是如何实现参数校验的......

[ 题外话:Validator框架就是为了解决开发人员在开发时少编码,提升开发效率的,它是专门用来做接口参数校验的。]

Spring Boot 快速入门系列:

Spring Boot 快速入门系列(先导篇) —— 从 Hello World 开始

Spring Boot 快速入门系列(I) —— 属性配置篇

Spring Boot 快速入门系列(II)—— 数据操作篇之 Spring Data JPA

Spring Boot 快速入门系列(III)—— 数据操作篇之 JdbcTemplate Spring Boot 快速入门系列(IV)—— 数据操作篇之 MyBatis

Spring Boot 快速入门系列(V)—— 事务管理篇之 @Transactional

Spring Boot 快速入门系列(VI)—— 接口规范篇

Spring Boot Validate

Spring Boot 支持 JSR 303 / JSR 349 验证框架,可直接通过注解驱动的方式进行数据校验,并将校验结果封装成 BindingResult 对象。

[ 注:JSR 303是 java 为 bean 数据合法性校验提供的标准框架,它已经包含在 JavaEE 6.0 中。JSR 303 通过在 Bean 属性上标注类似于 @NotNull、@Null、@Min、@Max 等标准的注解指定校验规则,并通过这些标准的验证接口对 Bean 进行验证。这些注解在 javax.validation.constraints 包下。 ]

SpringMVC / SpringBoot 本身并没有提供 JSR 303 的实现,所以必须将 JSR 303 的实现者 jar 包放在 classpath 类路径下。

如果是 Maven 项目,在 pom. 配置文件中加入 Hibernate Validator 的依赖包。如下所示:

<!-- 参数校验, SpringBoot项目只需引入spring-boot-starter-web--><dependency>    <groupId>org.hibernate</groupId>    <artifactId>hibernate-validator</artifactId>    <version>6.0.17.Final</version></dependency><!-- lombok插件 --><dependency>    <groupId>org.projectlombok</groupId>    <artifactId>lombok</artifactId>    <version>1.18.8</version>    <scope>provided</scope></dependency>

[ 注:Hibernate Validator是JSR 303的一个参考实现,除支持所有的标准校验注解外,它还支持一些的扩展注解。]

常用注解

以下表格列出常用校验注解及主要校验规则。以下的注解必须配合 @Valid 或 @Validated 使用,通过这两个注解开启校验。

下面的表格列出常用校验类及主要功能。这些注解必须配合@Valid或@Validated使用,通过这两个注解开启校验。

校验类别

注解名称

解释

校验类型

非空校验

@Null

校验bean属性为null

任意类型

@NotNull

校验bean属性不为null

任意类型

@NotEmpty

校验bean属性不为null且不为空,字符串长度不为0,集合大小不能为0

CharSequence子类型、Collection、Map、数组

@NotBlank

校验字符串不为null、且最少有一个非空格字符,不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的首位空格

CharSequence子类型

boolean校验

@AssertTrue

校验Boolean对象是否为true

Boolean,boolean

@AssertFalse

校验Boolean对象是否为false

与@AssertTrue一样

长度校验

@Size(min=下限, max=上限)

校验bean属性的在min和max(包含)指定区间之内,如字符长度、集合大小

字符串、Collection、Map、数组等

@Length(min=下限, max=上限)

校验字符串长度在min和max区间内

CharSequence子类型

时间校验

@Past

校验bean属性(日期类型)比当前时间早

java.util.Date,java.util.Calendar;Joda Time类库的日期类型

@Future

校验bean属性(日期类型)比当前时间晚

与@Past要求一样

数值校验

@Min(value=值)

校验数字 >= value

BigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存储的是数字)子类型

@Max(value=值)

校验数字 <= value

和@Min要求一样

@Digits(integer=整数位数, fraction=小数位数)

校验字符串是否是符合指定格式的数字,即整数位数和小数位数上限,interger指定整数精度,fraction指定小数精度。

和@Min要求一样

@Range(min=最小值,max=最大值)

校验数字是否符合[min,max]范围

BigDecimal,BigInteger,CharSequence, byte, short, int, long等原子类型和包装类型

正则校验

@Pattern(regexp)

校验字符串是否符合正则表达式

String,任何CharSequence的子类型

@Email(regexp)

校验是否邮箱格式

CharSequence子类型(如String)

下面是 @Valid 和 @Validated 两个注解的区别。

@Valid

@Validated

分组校验

不支持

支持

使用范围

方法、属性、构造方法、参数

类、方法、参数

嵌套验证

支持

不支持

[ 注 :嵌套验证。JavaBean AClass中某个属性类型是JavaBean BClass,对AClass进行验证的同时验证BClass。]

参数校验体验

看初级程序员参数校验如何实现

1)新建 TestVo 对象,代码清单如下:

2)Controller 层代码清单如下:

3)先启动 MySQL 服务(在之前Spring Boot 入门系列的工程基础上测试的,所以依赖数据库,与本篇无关)

4)再启动 Spring Boot 项目

5)服务启动成功后,使用 Postman 请求接口测试结果如下:

在没有加入全局异常处理之前(参考:Spring Boot 快速入门系列(VII)—— 全局异常处理篇),返回结果如下所示:

看中级程序员处理接口参数校验实现

1)在 TestVo 实体对象属性上添加相关参数校验注解,代码清单如下:

2)新建 TestMidController 进行测试,代码清单如下:

[ 题外话:n 个 api 就有 n 个 BindingResult, 这样还是太麻烦 !!!太麻烦 !!!太麻烦 !!]

3)使用 Postman 请求接口,测试结果如下:

[ 题外话:细心的小伙伴会发现上面的错误提示信息没有按照参数传入的顺序显示,这对于前端不够友好,小伙伴们试试吧,下期再向大家介绍如何控制参数顺序,敬请期待!]

看高级程序员处理接口参数校验实现

1)在全局异常处理类中(参考示例:Spring Boot 快速入门系列(VII)—— 全局异常处理篇),体验处理参数校验,代码清单如下:

2)新建 TestHighController 进行测试,代码清单如下:

[ 题外话:参数统一在全局异常处理类中校验返回,controller层的代码是不是清晰简洁很多,是不是很爽啊!]

3)使用 Postman 请求接口,测试结果如下:

自定义注解校验

在日常开发接口时,上面的常用注解是不够用的,这时需要自定义参数校验注解,下面对性别 sex 字段进行自定义注解演示:

1)新建 SexValid 校验类实现 ConstraintValidator 接口,代码清单如下:

2)自定义参数校验注解 Sex,可以参考 javax.validation.constraints 包下注解:

代码清单如下:

[ 题外话:注解定义请参考:Java注解 ]

3)使用 Postman 请求接口,测试结果如下:

参数分组校验

日常开发接口时,经常使用同一个对象作为接口入参,比如上面使用的 TestVo 类,其中新增接口,id 为空,更新接口参数 id 非空。这时分组校验对象属性显得尤为重要,演示如下:

1)修改 TestVo 类,代码清单如下:

2)修改 TestHighController 类,结合 @Validated 注解实现分组校验,代码清单如下:

3)使用 Postman 请求接口,测试结果如下:

小结

通过以上接口参数校验代码演示,相信大家以后不会在为接口复杂繁多的参数校验而烦恼。本文总结了基本的参数校验方法、全局异常类、自定义校验类、分组校验等,也用代码演示了初、中、高级程序员对于接口参数校验的编码实现,这种不同水平的对比能使得我们更好的学习和了解如何实现高效简介的参数校验,提高代码可读性,提高生产力。

请问大家目前参与的项目的接口参数校验属于哪个级别的呢,欢迎大家一起讨论!

收藏 打印