技术分享
🛡️Spring Boot如何校验参数?
00 分钟
2024-7-28
2024-7-28
type
status
date
Jul 28, 2024 01:32 PM
slug
summary
category
tags
password
icon

背景

在日常的接口开发中,为了防止非法参数对业务造成影响,经常需要对接口的参数做校验,例如登录的时候需要校验用户名密码是否为空,创建用户的时候需要校验邮件、手机号码格式是否准确。靠代码对接口参数一个个校验的话就太繁琐了,代码可读性极差。
Hibernate Validator框架就是为了解决开发人员在开发的时候少写代码,提升开发效率;Hibernate Validator专门用来进行接口参数校验,例如常见的必填校验,email格式校验,用户名必须位于6到12之间 等等…
Hibernate Validator校验框架遵循了JSR-303验证规范(参数校验规范),JSR是Java Specification Requests的缩写。
如果参数校验不通过,会抛出 ConstraintViolationException 异常,被全局的
⚠️
统一异常处理
捕获,返回“请求参数不正确”的响应。示例如下:

SpringBoot中集成参数校验

引入Mave依赖

定义要参数校验的实体类

常用的参数校验注解:

参数校验使用

  • 在需要参数校验的类上,添加 @Validated注解,例如说 Controller、Service 类。代码如下:
Controller 做了参数校验后,Service 是否需要做参数校验?
需要。Service 可能会被别的 Service 进行调用,也会存在参数不正确的情况,所以必须进行参数校验。

自定义注解

如果 Validator 内置的参数校验注解不满足需求时,我们也可以自定义参数校验的注解。例如,手机号码的校验

手机号码

@Mobile

MobileValidator 校验器

使用@Mobile注解

校验密码和确认密码是否相同

方式一:注解

方式二:直接校验

分组校验

一个VO对象在新增的时候某些字段为必填,在更新的时候又非必填。例如,新增的时候id不是必填项,更新的时候id是必填项,面对这种场景你会怎么处理呢?
在实际开发中大多数都是建立两个VO对象,UserCreateVOUserUpdateVO来处理这种场景,这样确实也能实现效果,但是会造成类膨胀。
其实Validator校验框架已经考虑到了这种场景并且提供了解决方案,就是分组校验。要使用分组校验,只需要三个步骤:

定义分组接口

定义一个分组接口 UserValidGroup 让其继承javax.validation.groups.Default,再在分组接口中定义出多个不同的操作类型,Create,Update,Query,Delete。

在模型中给参数分配分组

给需要参数校验的方法指定分组

当然如果你的UserValidGroup没有继承Default分组,那在代码属性上就需要加上@Validated(value = {UserValidGroup.Crud.Create.class, Default.class}才能让email字段的校验生效。

@Valid 和 @Validated

不知道你发现了没有,使用了分组校验之后,Controller中的校验的时候使用了@Validated而不是@Valid,原因主要有以下几点:
  1. @Valid 注解,是 Bean Validation 所定义,可以添加在普通方法、构造方法、方法参数、方法返回、成员变量上,表示它们需要进行约束校验。@Validated 注解,是 Spring Validation 锁定义,可以添加在类、方法参数、普通方法上,表示它们需要进行约束校验。
  1. @Validated 有 value 属性,支持分组校验。属性如下:
    1. @Valid 注解,因为没有分组校验的属性,所以无法提供分组校验。
  1. 嵌套校验:相比来说,@Valid 注解的地方,多了【成员变量】。这就导致,如果有嵌套对象的时候,只能使用 @Valid 注解。例如说:
    1. 如果不在 User.profile 属性上,添加 @Valid 注解,就会导致 UserProfile.nickname 属性,不会进行校验。
  1. @Valid 注解的地方,也多了【构造方法】和【方法返回】,所以在有这方面的诉求的时候,也只能使用 @Valid 注解。
💡
总结:
总的来说,绝大多数场景下,我们使用 @Validated 注解即可。
而在有嵌套校验的场景,我们使用 @Valid 注解添加到成员属性上。
 

评论
Loading...