简介
在Web开发过程中,接口传参往往需要进行参数校验。最普通的方式是手动编码,对接口传参一个一个地进行手动校验,代码臃肿编写费时费力。
Javax.validation包则对参数校验规定了一批通用的API,通过接入实现以及编写一套代码及规定参数的格式范围取值等,就能够摆脱编写臃肿的代码,解放生产力。
本文接下去的内容则介绍一种简单的参数校验工具封装。
使用
引入依赖
新建maven工程,引入必要依赖项,如下:1
2
3
4
5
6
7
8
9
10<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.17.Final</version>
</dependency>
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.el</artifactId>
    <version>3.0.1-b09</version>
</dependency>
这里引入的是 javax.validation 的 hibernate-validator 实现。
核心代码
获取 Validator1
javax.validation.Validator validator = javax.validation.Validation.byProvider(org.hibernate.validator.HibernateValidator.class).configure().failFast(false).buildValidatorFactory().getValidator();
进行参数校验1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23public static <T> ValidateResult<T> validate(T source) {
    if (validator == null) {
        logger.warn("No validator available!");
        return null;
    }
    Set<ConstraintViolation<Object>> errors = validator.validate(source);
    ValidateResult<T> validateResult = new ValidateResult<>();
    validateResult.source(source);
    if (errors != null && !errors.isEmpty()) {
        List<PropertyError> propertyErrors = new ArrayList<>();
        for (ConstraintViolation<Object> error : errors) {
            propertyErrors.add(new PropertyError()
                    .property(error.getPropertyPath().toString())
                    .message(error.getMessage())
                    .invalidValue(error.getInvalidValue()));
        }
        validateResult.success(false);
        validateResult.propertyErrors(propertyErrors);
    } else {
        validateResult.success(true);
    }
    return validateResult;
}
其中,ValidateResult 定义如下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
41public class ValidateResult<T> {
    /**
     * The source object tobe validated.
     */
    private T source;
    /**
     * Validate result, true: success, false: failed.
     */
    private Boolean success;
    /**
     * Detail information if validate failed.
     */
    private List<PropertyError> propertyErrors;
    public T getSource() {
        return source;
    }
    public ValidateResult source(T source) {
        this.source = source;
        return this;
    }
    public Boolean getSuccess() {
        return success;
    }
    public ValidateResult success(Boolean success) {
        this.success = success;
        return this;
    }
    public List<PropertyError> getPropertyErrors() {
        return propertyErrors;
    }
    public ValidateResult propertyErrors(List<PropertyError> propertyErrors) {
        this.propertyErrors = propertyErrors;
        return this;
    }
}
其中,PropertyError 定义如下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
41public class PropertyError {
    /**
     * Property where validate failed.
     */
    private String property;
    /**
     * Error message.
     */
    private String message;
    /**
     * Invalid value for this property.
     */
    private Object invalidValue;
    public String getProperty() {
        return property;
    }
    public PropertyError property(String property) {
        this.property = property;
        return this;
    }
    public String getMessage() {
        return message;
    }
    public PropertyError message(String message) {
        this.message = message;
        return this;
    }
    public Object getInvalidValue() {
        return invalidValue;
    }
    public PropertyError invalidValue(Object invalidValue) {
        this.invalidValue = invalidValue;
        return this;
    }
}
测试结果
编写测试代码,定义参数类型TestModel并规定参数约束条件,如下: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
52import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@Valid
public class TestModel {
    @NotNull(message = "ID is null!")
    private String id;
    @NotNull(message = "name is null!")
    @NotEmpty(message = "name is empty!")
    private String name;
    @Size(max = 1000, message = "max length is 1000!")
    private String description;
    @Size(max = 10)
    private String color;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
}
其中,@NotNull,@NotEmpty,@Size 等注解为 javax.validation 定义的参数约束条件。
编写测试代码,创建参数实例并进行校验,打印结果,如下: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@Test
public void test() {
    List<TestModel> testModels = new ArrayList<>();
    int type = 0;
    for (int i = 0; i < 9; i++) {
        TestModel model = new TestModel();
        switch (type) {
            case 0:
                model.setId(UUID.randomUUID().toString().replaceAll("-", ""));
                model.setName("name_" + i);
                model.setDescription("desc_" + i);
                model.setColor("RED");
                break;
            case 1:
                model.setId(UUID.randomUUID().toString().replaceAll("-", ""));
                model.setName("");
                model.setDescription("desc_" + i);
                model.setColor("RED");
                break;
            case 2:
                model.setId(null);
                model.setName("name_" + i);
                model.setDescription("");
                model.setColor("ABCDEFGHIJKLMN");
                break;
            default:
                model.setId(UUID.randomUUID().toString().replaceAll("-", ""));
                model.setName("name_" + i);
                model.setDescription("desc_" + i);
                break;
        }
        testModels.add(model);
        type++;
        if (type == 3) {
            type = 0;
        }
    }
    List<ValidateResult<TestModel>> results = new ArrayList<>();
    testModels.forEach(testModel -> results.add(ValidateUtils.validate(testModel)));
    results.forEach(System.out::println);
}
运行结果:1
2
3
4
5
6
7
8
9
10
11十月 28, 2019 10:23:41 上午 org.hibernate.validator.internal.util.Version <clinit>
INFO: HV000001: Hibernate Validator 6.0.17.Final
ValidateResult{source=TestModel{id='6ced48a15c9e42e7971b9e9cc65d86db', name='name_0', description='desc_0', color='RED'}, success=true, propertyErrors=null}
ValidateResult{source=TestModel{id='8321e78e3de44916bc8997f17aada9a4', name='', description='desc_1', color='RED'}, success=false, propertyErrors=[PropertyError{property='name', message='name is empty!', invalidValue=}]}
ValidateResult{source=TestModel{id='null', name='name_2', description='', color='ABCDEFGHIJKLMN'}, success=false, propertyErrors=[PropertyError{property='color', message='个数必须在0和10之间', invalidValue=ABCDEFGHIJKLMN}, PropertyError{property='id', message='ID is null!', invalidValue=null}]}
ValidateResult{source=TestModel{id='39088ecb7d8e40ca855121a87fce0dd5', name='name_3', description='desc_3', color='RED'}, success=true, propertyErrors=null}
ValidateResult{source=TestModel{id='c4d0829a30f3481f856dd483eac91448', name='', description='desc_4', color='RED'}, success=false, propertyErrors=[PropertyError{property='name', message='name is empty!', invalidValue=}]}
ValidateResult{source=TestModel{id='null', name='name_5', description='', color='ABCDEFGHIJKLMN'}, success=false, propertyErrors=[PropertyError{property='color', message='个数必须在0和10之间', invalidValue=ABCDEFGHIJKLMN}, PropertyError{property='id', message='ID is null!', invalidValue=null}]}
ValidateResult{source=TestModel{id='b13601c5a4d24905b1b73527217a8852', name='name_6', description='desc_6', color='RED'}, success=true, propertyErrors=null}
ValidateResult{source=TestModel{id='9df4ecd18dcf421a957d956d18f3c28b', name='', description='desc_7', color='RED'}, success=false, propertyErrors=[PropertyError{property='name', message='name is empty!', invalidValue=}]}
ValidateResult{source=TestModel{id='null', name='name_8', description='', color='ABCDEFGHIJKLMN'}, success=false, propertyErrors=[PropertyError{property='color', message='个数必须在0和10之间', invalidValue=ABCDEFGHIJKLMN}, PropertyError{property='id', message='ID is null!', invalidValue=null}]}
