SpringBoot优雅的参数校验-validation
前言
在后端开发过程中,我们避免不了对前端传过来的参数进行检验。有的人会说,前端检验不就行了吗,为啥还要后端检验一遍?我们前端经常对我说的一句话:”后端不要信任前端,你怎么知道接口不会被拦截,前端就一定不会传错。“。因此,参数校验是非常重要的一个环节,严格参数校验会减少很多出bug的概率,增加接口的安全性,增强程序的健壮性。
当我们在做参数检验的时候,可能会出现这种情况:参数太多,我们要写很多条件判断语句,这样就会显得代码不够整洁,阅读体验也不是很好。
因此我们需要一种优雅的方式来处理上面的问题,进行SpringBoot统一参数校验。那就是今天我们的主角validation啦。
使用方式
通过@Validated这一注解配合一些参数校验注解(PS:@NotNull,@NotEmpty)。然后对抛出的异常进行全局统一捕获然后返回错误信息。
引入依赖
1 | <!-- Validation --> |
PostParams
1 | package com.example.spring_boot_validation.entity.params; |
TestController
1 |
|
ControllerAdvice
参数检验异常统一拦截处理
1 |
|
在使用参数检验的过程中,主要会抛出以上三种异常BindException、MethodArgumentNotValidException、ConstraintViolationException。原因主要是因为跟请求发起的数据格式(content-type)有关系,对于不同的传输数据的格式spring采用不同的HttpMessageConverter(http参数转换器)来进行处理。
请求体(@RequestBody)绑定到java bean上失败时抛出MethodArgumentNotValidException;普通参数(@RequestParam)(非 java bean)校验出错时抛出ConstraintViolationException;请求参数绑定到java bean上失败时抛出BindException;
测试
请求POST: http://localhost:8080/post-test ,结果如下

常用的一些注解解析
@Validated 和 @Valid 的异同
| 注解 | 范围 | 嵌套 | 校验组 |
|---|---|---|---|
| @Validated | 可以标记类、方法、方法参数,不能用在成员属性(字段)上 | 不支持 | 支持 |
| @Valid | 可以标记方法、构造函数、方法参数和成员属性(字段)上 | 支持 | 不支持 |
通常在使用过程中,我们把@Validated标记在类上,然后@Valid标记在实体中的属性上。在Controller中使用,把@Validated标记在类上。然后针对java bean的参数就用@Valid注解。如下所示:

校验注解一览表
| 注解 | 作用 |
|---|---|
| @Valid | 被注释的元素是一个对象,需要检查此对象的所有字段值 |
| @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(value) | 被注释的元素必须符合指定的正则表达式 |
| 被注释的元素必须是电子邮箱地址 | |
| @Length(min=, max=) | 被注释的字符串的大小必须在指定的范围内 |
| @NotEmpty | 被注释的字符串的必须非空 |
| @Range(min=, max=) | 被注释的元素必须在合适的范围内 |
| @NotBlank | 被注释的字符串的必须非空 |
| @URL(protocol=,host=, port=,regexp=, flags=) | 被注释的字符串必须是一个有效的url |
嵌套验证
我们很多时候会存在这样的业务场景,前端会给后端传递一个list,我们不仅要限制每次请求list内的个数,同时还要对list内基本元素的属性值进行校验。这个时候就需要进行嵌套验证了,实现的方式很简单。在list上添加@Vaild就可以实现了。
