你们好,我是金金金。
场景
先看如下一张图,这是一个控制器里面的一个方法,第一眼是不是就感觉代码量非常多?而且随着参数越来越多 你则需要写
n
个if else
来完成校验,属实是麻烦而且不够优雅
JSR303
校验
仔细认真看,更容易理解吸收,想想什么层面需要做校验呢?
- 前端请求后端接口传输参数,是在
controller
中校验还是在Service
中校验?
都需要校验,只是分工不同。
-
Contoller
中校验请求参数的合法性,包括:必填项校验,数据格式校验,比如:是否是符合一定的日期格式,等。 -
Service
中要校验的是业务规则相关的内容,比如:课程已经审核通过所以提交失败。 -
Service
中根据业务规则去校验不方便写成通用代码,Controller
中则可以将校验的代码写成通用代码。
-
在
Service
层,校验是和业务逻辑紧密相关的。因为不同的业务场景下,校验规则可能不同,很难将这些规则抽象成通用的代码。 比如,在处理订单的Service
层中,校验的逻辑可能会涉及多个业务条件和数据库查询,这些条件可能只在特定的业务场景下适用,难以通用化。- 所以一般
service
层都是手动if
校验
- 所以一般
-
在
Controller
层,校验通常是对请求参数的基本合法性进行验证 例如字段是否为空、长度是否在允许范围内、值是否在有效范围内等。由于这些校验规则通常是标准化的,不依赖于复杂的业务逻辑,因此很容易抽象成通用代码。 例如,可以使用注解、AOP
等方式实现通用的参数校验逻辑,这样在不同的Controller
中都可以复用这些校验逻辑。-
所以
controller
层一般可以使用注解做校验早在
JavaEE6
规范中就定义了参数校验的规范,它就是JSR-303
,它定义了Bean Validation
,即对bean
属性进行校验。
-
SpringBoot
提供了JSR-303
的支持,它就是spring-boot-starter-validation
,它的底层使用Hibernate Validator
,Hibernate Validator
是Bean Validation
的参考实现。
所以,在
Controller
层使用spring-boot-starter-validation
完成对请求参数的基本合法性进行校验。
使用
- 如何在
controller
层面完成优雅的参数校验呢?接着往下看~
引入需要的坐标依赖
参数校验(
Spring Boot 2.3.1
之后,spring-boot-starter-validation
已经不包括在了spring-boot-starter-web
中,需要手动加上)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
规则对应参考如下:
实体类
-
控制器层方法接收的参数是一个DTO实体类
-
定义校验规则:首先找到这个
DTO
,在对应的属性上面添加对应的校验注解 -
开启校验:在
Controller
方法接收参数前面加上注解@Validated
-
自定义全局校验拦截
MethodArgumentNotValidException
异常(参数验证失败会抛出这个异常,所以也就是为什么拦截这个异常的原因),返回自定义响应实体给到前端 -
测试
- 我已经测试过了,是可以的,我就不贴图片了(懒一下~)
单个、多个参数校验
-
控制器层方法接收的参数不是一个实体类,而是直接写明了参数个数的情况(一般参数个数低于三个可以这么写,超过3个还是建议用一个
DTO
接收比较好~)
-
方法所在的控制器类上加注解
@Validated
-
参数前面加入相对应的校验注解
这里有个坑需要注意~先接着往下看
-
测试,前端不传递
roomNumber
参数-
前端并未收到房间号不能为空的信息
-
后端也并未打印出房间号为空的字样
这里需要注意,是因为加了
@RequestParam
导致没传递参数被此注解给拦截了,并未走到@NotBlank
所以既然加了
@NotBlank
校验,可以把@RequestParam("roomNumber")
给去掉 -
-
再次测试
-
后端:成功被全局异常所拦截,成功打印信息
-
前端:接收到了后端返回的信息,弹出对应的报错信息,相当完美!
-
-
传入一个三位数字的字符串,如预期一样提示出来了
总结
DTO参数
- 对应属性上加入校验规则注解
- 开启校验,在对应的方法参数前面加
@Validated
普通参数
- 控制器类上加入
@Validated
- 方法参数前面加入对应的校验规则注解(注意:
@RequestParam
注解)
- 编写有误还请大佬指正,万分感谢。