Springbootカスタム列挙検証器による列挙検証の実現


インタフェースパラメータは多くの場合列挙タイプであり、検証範囲は列挙クラスのいくつかの値に限定される.
カスタム列挙チェッカを実装することによって、注釈はDTOの対応するフィールドに宣言され、列挙タイプを検証できます.
 
1.     EnumValidator.java
package com.pld.product.center.common.utils;

import com.pld.product.center.common.enums.ProductResultCodeEnum;
import com.pld.product.center.common.exceptions.PldException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.*;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author tlj
 * @date 2019/7/9
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
@Constraint(validatedBy = EnumValidator.EnumValidatorHandle.class)
public @interface EnumValidator {
    Class> value();

    String message() default "          ";
    String method() default "getCode";
    Class>[] groups() default {};

    Class extends Payload>[] payload() default {};
    /**
     * @author tlj
     * @date 2019/7/9
     */
    @Slf4j
    class EnumValidatorHandle implements ConstraintValidator, Annotation {
        private List values = new ArrayList<>();

        @Override
        public void initialize(EnumValidator enumValidator) {
            Class> clz = enumValidator.value();
            Object[] objects = clz.getEnumConstants();
            try {
                Method method = clz.getMethod(enumValidator.method());
                if (Objects.isNull(method)) {

                    throw new PldException(ProductResultCodeEnum.PRODUCT_PARAM_ERROR,String.format("    %s    %s   ",clz.getName(),enumValidator.method()));
                }
                Object value;
                for (Object obj : objects) {
                    value = method.invoke(obj);
                    values.add(value);
                }
            } catch (Exception e) {
                log.error("        :{}", e);
            }
        }


        @Override
        public Class extends Annotation> annotationType() {
            return null;
        }

        @Override
        public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
            if (value instanceof String) {
                String valueStr = (String)value;
                return StringUtils.isEmpty(valueStr)|| values.contains(value);
            }
            return Objects.isNull(value) || values.contains(value);
        }
    }

}

2.列挙クラス:
/**
 * @author tlj
 * @date 2019/7/9
 */
@Getter
public enum SxWhetherIntEnum {
    YES(1, " "),
    NO(2, " ");

    private Integer code;
    private String msg;

    SxWhetherIntEnum(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

}

3.使用する場合、注記はDTOフィールドに適用されます.
/**
     *      ,1- ,2- 
     */
    @ApiModelProperty(value = "     ,1- ,2- (  )")
    @EnumValidator(value = SxWhetherIntEnum.class,message = "        :1 2 ")
    private Integer payable;