最早在传统 Spring MVC 项目里,因为前端对接数据都是后端程序员自己对接的,入参很明确,后端的参数校验自然可有可无,主要看项目的安全要求和工期要求。因此后端参数校验虽然很早就用,但是断断续续,不甚了了。
这几年,项目基本都是前后端分离模式,后端必要的参数校验自然不可少。每次使用,总是要在网上查找相应注解;同时有些不常用用法或奇怪 BUG 在做完后没及时总结,再一次遇到才后悔莫及。
因此,开一篇专门的笔记,来记录常用的注解和用法以供工作中查阅,希望能坚持逐渐完善吧。
一、常用注解
| 注解 | 作用 |
|---|---|
| @Null | 验证对象是否为 null |
| @NotNull | 验证对象是否不为 null, 无法查检长度为 0 的字符串 |
| @NotBlank | 字符串不为 null,并且字符串 trim()以后 length 要大于 0 |
| @NotEmpty | 集合或字符串不为空 |
| @AssertTrue | Boolean 对象是否为 true |
| @AssertFalse | Boolean 对象是否为 false |
| @Size(min=, max=) | 验证对象(Array, Collection , Map, String)长度是否在给定的范围之内 |
| @Length(min=, max=) | 验证字符串长度介于 min 和 max 之间 |
| @Past | 验证 Date 和 Calendar 对象是否在当前时间之前,验证成立的话被注释的元素一定是一个过去的日期 |
| @PastOrPresent | 过去或者现在 |
| @Future | 验证 Date 和 Calendar 对象是否在当前时间之后 ,验证成立的话被注释的元素一定是一个将来的日期 |
| @FutureOrPresent | 将来或者现在 |
| @Min | 验证 Number 和 String 对象是否大等于指定的值 |
| @Max | 验证 Number 和 String 对象是否小等于指定的值 |
| @DecimalMax | 被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过 BigDecimal 定义的最大值的字符串表示 . 小数 存在精度 |
| @DecimalMin | 被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过 BigDecimal 定义的最小值的字符串表示 . 小数 存在精度 |
| @Digits(integer=,fraction=) | 数字格式检查。integer 指定整数部分的最大长度,fraction 指定小数部分的最大长度 |
| @Positive | 数字,正数 |
| @PositiveOrZero | 数字,正数或 0 |
| @Negative | 数字,负数 |
| @NegativeOrZero | 数字,负数或 0 |
| @Range(min=, max=) | 被指定的元素必须在合适的范围内 |
| @Pattern(regex=) | 字符串必须匹配正则表达式 |
| @Valid | 嵌套验证、级联验证,如对象属性 |
二、校验方式
- 在 Controller 方法参数前加 @Valid 注解
a) 此处,@Valid 可以换成 @Validated;这两个有一些细节差别,待后期使用中完善吧;
b) @Valid 位置也可以放置在方法上或类上,产生的验证范围会发生变化,习惯放于参数前,更灵活;
c) 在验证参数后面加 BindingResult bindingResult,bindingResult 会自动接收错误信息。 - 手动校验
a) 如果我们的数据不是来自接口传值,没有通过 Controller 层,但是又希望验证 Bean 的参数有效性,那么可以通过手动调用 ValidatorFactory 来进行校验;
b) 示例如下:1
2
3
4
5
6
7
8
9// Bean 验证器
ValidatorFactory vf = Validation.buildDefaultValidatorFactory();
Validator validator = vf.getValidator();
// 校验的业务对象:demo,Bean 类型:Demo
Set<ConstraintViolation<Demo>> checkSet = validator.validate(demo);
if (CollectionUtils.isNotEmpty(checkSet)) {
// Bean 验证不通过
throw new ServiceException(checkSet.stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(",")));
}
三、问题记录
级联验证
a) 在 Bean 中存在对象属性或集合属性,需要级联验证对象中的属性时,需在属性上加“@Valid”注解,之前犯过傻,记录一下;
b) 示例如下:1
2
3
4
5public class DemoDto {
private List<Detail> list;List 集合参数验证
a) 可能遇到如下情况,保存一组数据,所以入参是对象集合,示例如下:
b) 这种情况,想要验证集合非空及对象的属性有效性,常规方式是无效的;
c) 参照网上的解决方式(未验证),既然集合在对象里可以级联验证,那么我们自定义一个集合类,实现 List接口,示例如下: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33// 定义校验集合类
public class ValidatorList<E> implements List<E> {
private List<E> list;
/**
* 关键
* @return
*/
public List<E> getList() {
return list;
}
/**
* 关键
* @return
*/
public void setList(List<E> list) {
this.list = list;
}
public ValidatorList() {
this.list = new ArrayList<E>();
}
public ValidatorList(List<E> list) {
this.list = list;
}
}
// 使用新集合类接收参数
// 控制器
public int save( ValidList<SaveDto> list, BindingResult bindingResult) {
// 省略业务代码
}
原文链接: https://xinghuipeng.pages.dev/2022/06/14/work/java/SpringValidation使用笔记/
版权声明: 转载请注明出处.