tags: [参数校验,@GroupSequenceProvider,hibernate validator,Bean Validation]
categories: [springboot,参数校验]


场景描述

在使用进行数据校验时,经常会遇到需要多个字段组合式的校验。
例如

  • 某个嘉年华俱乐部门票对不同人群存在不同的定价:
  1. 年龄必须大于 12 岁;
  2. 12 ~ 18 岁半价;
  3. 18 岁以上全价;
  4. coser 则可以免费;

换句话来说,任何年龄大于 12 岁的人都可以购买全价,对于半价票需要校验年龄是否满足未成年,对于免费票需要校验是否是 coser。

实现方案

入场时,需要根据门票类型动态的切换校验分组,定义如下的 Person 类。

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
@Getter
@Setter
@GroupSequenceProvider(Person.FareTypeGroupSequenceProvider.class)
public class Person {

/**
* 年龄
*/
@Min(value = 12, message = "年龄最小不低于 12 岁")
@Max(value = 18, message = "年龄大于 18 岁需要购买全价门票", groups=WhenIsHalf.class)
private Integer age;

/**
* 票价[0=免费,1=半价,2=全价]
*/
@NotNull(message = "票价类型不能为空")
private Integer fareType;

/**
* 是否是 coser
*/
@AssertTrue(message = "只有 coser 才可以免费进去", groups = WhenIsFree.class)
private Boolean coser;

public interface WhenIsFree {}

public interface WhenIsHalf {}

/**
* 校验分组处理器
*/
public static class FareTypeGroupSequenceProvider implements DefaultGroupSequenceProvider<Person> {


@Override
public List<Class<?>> getValidationGroups(Person person) {
ArrayList<Class<?>> list = Lists.newArrayList();
list.add(Person.class);
// 判空
if (Objects.nonNull(person)) {
// 当 fareType = 0 时
if (Objects.equals(person.getFareType(), 0)) {
list.add(WhenIsFree.class);
} else (Objects.equals(person.getFareType(), 1)) {
list.add(WhenIsHalf.class);
}
}
return list;
}
}
}

注意事项

  1. DefaultGroupSequenceProvider 类型是泛型类,必须指定为需要参数校验的 Bean 类型;
  2. DefaultGroupSequenceProvider.getValidationGroups 方法返回的 list 中必须包含 Bean 类型;
  3. DefaultGroupSequenceProvider 只能增强 Default.class 分组;

评论