文章

自定义注解实现参数校验,并实现多参数联动校验

自定义注解实现参数校验,并实现多参数联动校验

Spring Boot中自定义注解实现参数校验

在日常开发中, 我们经常需要用到参数校验,而如果在Controller层中对每个参数都手动代码去校验,无疑是非常繁琐且不易于维护的。而javax正好提供了很多常用的校验,如:@NotNull、@NotBlank、@NotEmpty等常用的参数校验注解,我们只需要在对用的参数上添加该注解就可以完成校验。但是还有很多情况是javax中没有提供的,这时就需要我们自己定义注解来实现响应的参数校验

新建一个注解 @Blank

1
2
3
4
5
6
7
8
9
@Documented
@Constraint(validatedBy = {BlankValidator.class})
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
public @interface Blank {
    String message() default "{javax.validation.constraints.Blank.message}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

校验一个字段必须为Blank,即:null、空串、trim后为空串

创建对应的 validator

创建 BlankValidator 并实现 ConstraintValidator 的 isValid 方法

1
2
3
4
5
6
7
8
public class BlankValidator implements ConstraintValidator<Blank, String> {
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return StrUtil.isBlank(value);
    }
}


使用

在接收参数对象中,使用该注解

1
2
@Blank(message = 'name must be blank')
private String name;

多字段联动校验

在参数校验时,很多情况下,需要对多个字段联动判断,如:我们需要传入级别 level 和对应的 code 来做查询,但限制 level 和 code 必须同时存在或者同时不存在,此时可以通过指定 group 来进行分组判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 指定对应的Provider
@GroupSequenceProvider(LevelAndCodeProvider.class)
public class TestReq {
    @ApiModelProperty(value = "等级")
    private String level;

    @Blank(message = "等级为空时,code 应同时为空", groups = {WhenLevelIsBlank.class})
    @NotBlank(message = "等级不空时,code 不应为空", groups = {WhenLevelNotBlank.class})
    @ApiModelProperty(value = "节点id")
    private String code;

    /* 分组校验 */
    public @interface WhenLevelIsBlank {}
    /* 分组校验 */
    public @interface WhenLevelNotBlank {}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class LevelAndCodeProvider implements DefaultGroupSequenceProvider<TestReqVO> {
    @Override
    public List<Class<?>> getValidationGroups(TestReqVO object) {
        List<Class<?>> defaultGroupSequence = new ArrayList<>();
        // 这一步不能省,否则 Default 分组都不会执行了,会抛错的
        defaultGroupSequence.add(TestReqVO.class);
        if (object != null) { // 这块判空请务必要做
        String level = object.getLevel();
        if (StrUtil.isBlank(level)) {
            defaultGroupSequence.add(TestReqVO.WhenLevelIsBlank.class);
        } else {
            defaultGroupSequence.add(TestReqVO.WhenLevelNotBlank.class);
        }
    }
    return defaultGroupSequence;
}
}

通过分组校验实现,当 level 为空时,code必须为空,当 level 不空时,code 也必须不空

本文由作者按照 CC BY 4.0 进行授权