02. spring-mvc 使用validation来检验枚举字段值

一、通点?

比如订单状态、性别、用户类型等枚举参数,在作值有效性校验时,我们可不可以使用 validator 统一在controller层进行处理呢?

二、实现方案

1. 定义枚举值数组获取接口

public interface IntArrayValuable {
    int[] array();
}

2. 定义用户枚举类型,并实现IntArrayValuable 接口

public enum UserTypeEnum implements IntArrayValuable {

    USER(1, "用户"),
    ADMIN(2, "管理员");

    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(UserTypeEnum::getValue).toArray();

    /** 类型 */
    private final Integer value;
    /**  类型名 */
    private final String name;

    UserTypeEnum(Integer value, String name) {
        this.value = value;
        this.name = name;
    }

    public Integer getValue() {
        return value;
    }

    public String getName() {
        return name;
    }

    @Override
    public int[] array() {
        return ARRAYS;
    }
}

3. 定义 UserVo

public class UserVo {

    @NotEmpty(message = "用户名不能为空")
    @Length(min = 4, max = 16, message = "用户名不能为空 4-16 位")
    @Pattern(regexp = "^[0-9]+$", message = "用户名全部为数字")
    private String name;

    @Mobile()
    private String mobile;

    /**  用户类型 */
    @NotNull(message = "用户类型不能为空")
    @InEnum(value = UserTypeEnum.class, message = "用户类型必须是 {value}")
    private Integer userType;
    //.....省略set get 方法
}

4. 定义InEnum注解

@Target({
        ElementType.METHOD,
        ElementType.FIELD,
        ElementType.ANNOTATION_TYPE,
        ElementType.CONSTRUCTOR,
        ElementType.PARAMETER,
        ElementType.TYPE_USE
})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
        validatedBy = InEnumValidator.class
)
public @interface InEnum {

    /**
     * @return 实现 EnumValuable 接口的
     */
    Class<? extends IntArrayValuable> value();

    String message() default "必须在指定范围 {value}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

}

5. 定义 InEnumValidator 验证器

public class InEnumValidator implements ConstraintValidator<InEnum, Integer> {

    private List<Integer> values;

    @Override
    public void initialize(InEnum annotation) {
        IntArrayValuable[] values = annotation.value().getEnumConstants();
        if (values.length == 0) {
            this.values = Collections.emptyList();
        } else {
            this.values = Arrays.stream(values[0].array()).boxed().collect(Collectors.toList());
        }
    }

    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
        // 为空时,默认不校验,即认为通过
        if (value == null) {
            return true;
        }
        // 校验通过
        if (values.contains(value)) {
            return true;
        }
        // 校验不通过,自定义提示语句(因为,注解上的 value 是枚举类,无法获得枚举类的实际值)
        context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值
        context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()
                .replaceAll("\\{value}", values.toString())).addConstraintViolation(); // 重新添加错误提示语句
        return false;
    }
}

validator 使用参考:
01.spring-mvc 结合 Java Validation Api 提升web开发效能

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容