java spring validation - 指定自定义验证注释的字段类型

时间:2016-06-06 10:48:35

标签: java validation spring-mvc

我正在开发一个java spring mvc应用程序。我已经实现了一个自定义验证注释来验证一些字符串(例如)。这是我的注释机构:

@Documented
@Constraint(validatedBy = PhoneValidator.class)
@Target( { ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Phone {

String message() default "{validation.phone}";

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

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

}

这是我的PhoneValidator课程:

public class PhoneValidator implements ConstraintValidator<Phone, String>  {

    @Override
    public void initialize(Phone a) {

    }

    @Override
    public boolean isValid(String phone, ConstraintValidatorContext cvc) {
        //my logic for validating the phone

    }

}

这是有效的,我可以将@Phone放在模型上任何字段的顶部。但我的问题是开发人员可以将此注释放在“任何”模型字段之上,我不希望这个任何!实际上,我希望开发人员可以将此注释放在 String 字段上。无论如何这样做?

2 个答案:

答案 0 :(得分:0)

目前,@Target的数据类型没有编译时检查机制。但是,如果@Phone注释放在除String以外的数据类型之上,它将在运行时抛出异常(可能为ClassCastException),因为遵循ConstraintValidator.isValid方法严格要求一个String电话。

@Override
public boolean isValid(String phone, ConstraintValidatorContext cvc) {
    //my logic for validating the phone

}

答案 1 :(得分:0)

我已经制作了几个自定义验证器注释,希望它可以帮助你。

    @Documented
    @Constraint(validatedBy = EnumStringValidator.class)
    @Target({ElementType.METHOD, ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface EnumString {

        String message() default "{com.raycloud.supply.platform.validate.spec.EnumString.message}";

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

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

        Class<? extends  Enum> enumClass();
    }



    public class EnumStringValidator implements ConstraintValidator<EnumString, CharSequence> {

        private Class<? extends Enum> enumClass;

        @Override
        public void initialize(EnumString annotation) {
            enumClass = annotation.enumClass();
        }

        @Override
        public boolean isValid(CharSequence field, ConstraintValidatorContext ctx) {
            if (field == null) {
                return true;
            }
            int len = field.length();

            if (len == 0) {
                return false;
            }

            try {
                Enum.valueOf(enumClass, field.toString());
            } catch (RuntimeException re) {
                return false;
            }

            return true;
        }

-------------------------

@Documented
@Constraint(validatedBy = {
        TrimmedValidatorForCharSequence.class,
        TrimmedValidatorForIterable.class})
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Trimmed {

    String message() default "{com.raycloud.supply.platform.validate.spec.Trimmed.message}";

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

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

}

public class TrimmedValidatorForCharSequence implements ConstraintValidator<Trimmed, CharSequence> {

    @Override
    public void initialize(Trimmed annotation) {
    }

    @Override
    public boolean isValid(CharSequence field, ConstraintValidatorContext ctx) {
        if (field == null) {
            return true;
        }
        int len = field.length();

        if (len == 0) {
            return false;
        }

        if (Util.isWhiteSpace(field.charAt(0)) || Util.isWhiteSpace(field.charAt(len - 1))) {
            return false;
        }

        return true;
    }

public class EnumStringValidator implements ConstraintValidator<EnumString, CharSequence> {

    private Class<? extends Enum> enumClass;

    @Override
    public void initialize(EnumString annotation) {
        enumClass = annotation.enumClass();
    }

    @Override
    public boolean isValid(CharSequence field, ConstraintValidatorContext ctx) {
        if (field == null) {
            return true;
        }
        int len = field.length();

        if (len == 0) {
            return false;
        }

        try {
            Enum.valueOf(enumClass, field.toString());
        } catch (RuntimeException re) {
            return false;
        }

        return true;
    }


-------------------------

@Target({TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = MethodVerifyValidator.class)
@Documented
public @interface MethodVerify {

    /**
     * validator class
     */
    Class<?> verifyClass();

    /**
     * validator method name
     */
    String methodName() default "verify";

    /**
     * method parameter types
     */
    Class[] parameterTypes() default {};

    String message() default "{com.raycloud.amazon.validate.MethodVerify.message}";

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

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

    @Target({TYPE, ANNOTATION_TYPE})
    @Retention(RUNTIME)
    @Documented
    @interface methods {
        MethodVerify[] value();
    }

}

public class MethodVerifyValidator
        implements ConstraintValidator<MethodVerify, Object> {

    private Method method;

    @Override
    public void initialize(final MethodVerify annotation) {
        String name = annotation.methodName();
        Class[] types = annotation.parameterTypes();

        method = Util.findMethod(annotation.verifyClass(), name, types);
        if (method == null) {
            throw new IllegalStateException("none method found!");
        }

        Util.makeAccessible(method);
    }

    @Override
    public boolean isValid(final Object value, final ConstraintValidatorContext ctx) {
        //if(value == null)//value != null
        try {
            method.invoke(value);
        } catch (Exception re) {
            return false;
        }

        return true;
    }

}