簡體   English   中英

@Notnull具有多個字段的Spring自定義注釋驗證

[英]@Notnull Spring Custom Annotation Validation with multiple field

如何編寫(類型級別注解)自定義注解以進行選擇驗證(許多屬性之一必須不為null)?

即使這個“問題”涉及面很廣,我也會給出一個答案,因為這里有我需要的代碼:

@Target(ElementType.TYPE)
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = ChoiceValidator.class)
public @interface Choice {
    String[] value();

    boolean multiple() default false;

    String message() default "{com.stackoverflow.validation.Choice.message}";

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

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

使用bean屬性訪問這里驗證:

public class ChoiceValidator implements ConstraintValidator<Choice, Object> {
    private String[] properties;
    private boolean allowMultiple;

    @Override
    public void initialize(Choice constraintAnnotation) {
        if (constraintAnnotation.value().length < 2) {
            throw new IllegalArgumentException("at least two properties needed to make a choice");
        }
        properties = constraintAnnotation.value();
        allowMultiple = constraintAnnotation.multiple();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        try {
            BeanInfo info = getBeanInfo(value.getClass());
            long notNull = Stream.of(properties)
                    .map(property -> Stream.of(info.getPropertyDescriptors())
                            .filter(desr -> desr.getName().equals(property))
                            .findAny()
                            .orElse(null)
                    )
                    .map(prop -> getProperty(prop, value))
                    .filter(Objects::nonNull)
                    .count();
            return allowMultiple ? notNull != 0 : notNull == 1;
        } catch (IntrospectionException noBean) {
            return false;
        }
    }

    private Object getProperty(PropertyDescriptor prop, Object bean) {
        try {
            return prop.getReadMethod() == null ? null : prop.getReadMethod().invoke(bean);
        } catch (ReflectiveOperationException noAccess) {
            return null;
        }
    }
}

典型用法如下所示( lombok注釋可生成getter和setter):

@Data
@Choice({"one", "two"})
class OneOf {
    private String one;
    private String two;
    private String whatever;
}

@Data
@Choice(value = {"one", "two"}, multiple = true)
class AnyOf {
    private String one;
    private String two;
}

但需要澄清的是:Stackoverflow是供開發人員交流知識的QA社區。 這是不是要問的地方“可以請你的代碼這對我來說免費的嗎?”。 所有有價值的貢獻者至少都首先嘗試解決問題,然后再提出詳細問題。 人們回答問題會花費他們的業余時間,而他們卻沒有得到報酬。 請提出具體問題並表示自己的努力,以表示尊重。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM