参数校验
参数校验
客户端校验和服务端校验
客户端校验
客户端校验:提示用户正确输入,密码的输入等准确性来加强用户体验。
服务端校验
服务端校验即接口校验:更多的是为了接口安全,数据库安全,防止非法用户。
java规范:JSR-303
为什么对接口参数校验
数据库汇中字段对应的数据,应该遵循业务要求和数据库设计
防止(减小)范围外的输入的数据入库后影响业务正常运行的风险
数据来源是接口,从入口处(接口)进行校验。
如何进行接口参数校验实现
使用@Valid
spring基于规范的实现:@Valid,对@Valid的扩展:@Validated
注解 springboot中@Validated @Valid,通过注解的方法,在实体上加注解。
非实体校验
形参校验注解(@NotBlank、@NotNull等)
1
public Result delete(@RequestParam @NotBlank(message = "主键不能为空") String id){}
实体校验
@Validated + 属性校验注解(@NotBlank、@NotNull等)
1
public Result update(@RequestBody @Validated UserUpdateVO data) {}
1
2
3
4
5
6
7
8
9
10
11
12@Data
public class UserUpdateVO {
@NotBlank(message = "id不能为空")
private String id;
@NotNull(message = "小数位数不能为空")
@Max(value = 2,message = "小数位数格式错误")
@Min(value = 0, message = "小数位数格式错误")
private Integer decimalDigits;
}List
校验 @Valid + ValidList
@Valid 起嵌套校验的作用
原Controller方法:
1
public Result add(@RequestBody List<实体> data) {}
List是jdk的接口。@Valid,@Validated 无法校验非实体Bean.
校验List<实体>的方法。 定义ValidList 实现List接口。List<实体> → ValidList<实体>
1
public Result add( @RequestBody @Valid ValidList<实体> data) {}
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136public class ValidList<E> implements List<E> {
@Valid
private List<E> list;
public ValidList() {
this.list = new ArrayList<>();
}
public ValidList(List<E> list) {
this.list = list;
}
public List<E> getList() {
return list;
}
public void setList(List<E> list) {
this.list = list;
}
@Override
public int size() {
return list.size();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public boolean contains(Object o) {
return list.contains(o);
}
@Override
public Iterator<E> iterator() {
return list.iterator();
}
@Override
public Object[] toArray() {
return list.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return list.toArray(a);
}
@Override
public boolean add(E e) {
return list.add(e);
}
@Override
public boolean remove(Object o) {
return list.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return list.containsAll(c);
}
@Override
public boolean addAll(Collection<? extends E> c) {
return list.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends E> c) {
return list.addAll(index, c);
}
@Override
public boolean removeAll(Collection<?> c) {
return list.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return list.retainAll(c);
}
@Override
public void clear() {
list.clear();
}
@Override
public E get(int index) {
return list.get(index);
}
@Override
public E set(int index, E element) {
return list.set(index, element);
}
@Override
public void add(int index, E element) {
list.add(index, element);
}
@Override
public E remove(int index) {
return list.remove(index);
}
@Override
public int indexOf(Object o) {
return list.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return list.lastIndexOf(o);
}
@Override
public ListIterator<E> listIterator() {
return list.listIterator();
}
@Override
public ListIterator<E> listIterator(int index) {
return list.listIterator(index);
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
return list.subList(fromIndex, toIndex);
}
}实体内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
29public Result update(@RequestBody @Validated UserUpdateVO data) {}
@Data
public class UserUpdateVO {
@NotBlank(message = "id不能为空")
private String id;
@NotNull(message = "小数位数不能为空")
@Max(value = 2,message = "小数位数格式错误")
@Min(value = 0, message = "小数位数格式错误")
private Integer decimalDigits;
@Size(min = 1,message = "角色不能为空")
@Valid
// @Valid 开启递归校验Role
private List<Role> roles;
}
@Data
public class Role{
@NotBlank(message = "角色不能为空")
private String roleId;
}
通过工具类
RegexUtils.java
将常用的校验方法放在一个类中,然后哪个参数需要校验,就调用工具类中的方法。
校验失败处理
使用全局异常捕获。 使用 @ControllerAdvice 分别定义方法,捕获并处理MethodArgumentNotValidException、BindException、ConstraintViolationException
实现
1 | import lombok.extern.slf4j.Slf4j; |
常用校验注解
| 空校验 | 针对类型 | 说明 |
|---|---|---|
| @Null | 任何类型 | 校验对象必须为空 |
| @NotNull | 任何类型 | 校验对象不为空,不能校验字符串长度为0的对象 |
| @NotBlank | 字符串 | 只对字符串有效,校验字符串去掉前后空格后长度不为0 |
| @NotEmpty | 字符串、集合、数组 | 校验对象不能为空 (字符串长度不为0、集合大小不为0) |
| boolean校验 | 针对类型 | 说明 |
|---|---|---|
| @AssertTrue | 布尔 | 校验boolean类型必须为true |
| @AssertFalse | 布尔 | 校验boolean类型必须为false |
| 日期校验 | 针对类型 | 说明 |
|---|---|---|
| @Past | 日期类型 | 校验必须是一个过去的日期 |
| @Future | 日期类型 | 校验必须是一个将来的日期 |
| 数值校验 | 针对类型 | 说明 |
|---|---|---|
| @Min | 数字类型 | 校验必须是一个数字,其值必须大于或等于指定的最小值 |
| @Max | 数字类型 | 校验必须是一个数字,其值必须小于或等于指定的最大值 |
| @DecimalMin | 数字类型 | 校验必须是一个数字,其值必须大于或等于指定的最小值 |
| @DecimalMax | 数字类型 | 校验必须是一个数字,其值必须小于或等于指定的最大值 |
| @Digits(integer=,fraction=) | 数字类型 | 校验必须是一个数字,interger指定整数精度,fraction指定小数精度 |
| @Range(min =,max = ) | 数字类型、字符串 | 校验对象的值在min和max区间内 |
| @Length(min =,max = ) | 字符串 | 校验对象的值的长度在min和max区间内 |
| @Size(min =,max = ) | 字符串、集合、数组 | 校验对象的值在min和max区间内,如字符长度、集合大小 |
| 其他校验 | 针对类型 | 说明 |
|---|---|---|
| 字符串 | 校验对象的值必须是Email类型,也可以通过regexp和flag指定自定义的email格式 | |
| @Pattern | 字符串 | 校验对象的值必须符合指定的正则表达式 |
| @CreditCardNumber | 数字类型、字符串 | 校验对象的值必须是信用卡类型 |
| @URL | 字符串 | 校验对象的值必须是URL地址 |
进阶用法
- 自己写注解类。
- 约束规则“分组”(group)
- 校验方法的返回值
- 约束规则支持正则表达式
- 支持跨参数校验 ?
参考
https://blog.csdn.net/sj13074480550/article/details/103399503