Bean Validator之自定义入参枚举校验

Bean Validator之自定义入参枚举校验

前一篇文章Bean Validator详解中详细介绍了Bean Validator的相关用法。
此时,会发现如果想要校验入参是否在我们定义的某个枚举范围内,Bean Validator好像并没有对应的注解可以使用。
现在,让我们来讲讲如何实现一个基于枚举的自定义入参校验。

一、自定义注解


import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.*;
import java.lang.reflect.Field;

/**
 1. @author qudian
 2. 枚举值校验
 */
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {EnumValueValidator.class})
public @interface EnumValue {

    String message() default "入参不在枚举范围内";

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

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

    /**
     * 目标枚举类
     */
    Class<? extends Enum<?>> enumClass();

    /**
     * 目标枚举属性
     */
    String enumField();
}
  1. enumClass:指定校验的入参属于哪个枚举类
  2. enumField:指定校验的入参属于枚举类中哪个field
  3. @Constraint:指明具体的校验类

二、实现枚举属性校验

public class EnumValueValidator implements ConstraintValidator<EnumValue, Object> {
        private Class<? extends Enum<?>> enumClass;
        private String enumField;

        @Override
        public void initialize(EnumValue enumValue) {
            enumClass = enumValue.enumClass();
            enumField = enumValue.enumField();
        }

        /**
         * 枚举值校验
         * @param value
         * @param constraintValidatorContext
         * @return 匹配返回true,不匹配返回false
         */
        @Override
        public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
            if (null == value || null == enumClass || null == enumField || "".equals(enumField)) {
                return false;
            }
            try {
                Field field = enumClass.getDeclaredField(enumField);
                Object[] objects = enumClass.getEnumConstants();
                if (null != objects){
                    field.setAccessible(true);
                    for (Object object : objects) {
                        if (value.equals(field.get(object))){
                            return true;
                        }
                    }
                }
                return false;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

    }
  1. isValid(Object value, ConstraintValidatorContext constraintValidatorContext)中的value代表入参值
  2. 校验逻辑中我们先通过反射拿到具体的field,如果枚举中不存在该field,则会报NoSuchFieldException
  3. 第二步再通过enumClass.getEnumConstants()拿到该枚举中所有已定义好的常量数组
  4. 第三步,需要设置field的访问权限为true,否则会报异常:can not access a member of class xx with modifiers “private”
  5. 最后一步,遍历EnumConstants,通过反射拿到具体值,并进行入参对比

三、注解使用

  1. 定义枚举
public enum StatusEnum {
    DEFAULT(0),
    ACTIVE(1),
    INACTIVE(2);
    private Integer status;

    public Integer getStatus() {
        return status;
    }

    StatusEnum(Integer status) {
        this.status = status;
    }
}
  1. 定义入参实体vo
public class DemoVo {
    @EnumValue(enumClass = StatusEnum.class, enumField = "status")
    private Integer status;

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public DemoVo(Integer status) {
        this.status = status;
    }
}
  1. 请求校验
@RestController
@RequestMapping("/demo")
public class DemoController {

    @GetMapping("/validate")
    public void validate(@Valid @RequestBody DemoVo demoVo){
        System.out.println("demoVo = " + demoVo.getStatus());
    }
}

现在,可以就可以根据枚举中的field,任意校验入参了。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值