2016-11-01 4 views
3

Немного жадный вопрос здесь, надеюсь, что это можно было бы также помочь друга, кто хочет узнать больше о проверке аннотацийSpring аннотаций Проверка с несколькими поля

Я в настоящее время изучает весна, и сейчас я планирую попробовать настроить аннотированную проверку.

Я искал много, и теперь я знаю, что есть в основном два вида проверки, один используется для контроллера, а другой один метод аннотаций с использованием @Valid

Так вот мой сценарий: предположим, что я два или более полей, которые могут быть пустыми, когда они ВСЕ NULL. Но только если одно из этих полей содержит любое значение, кроме пустой строки, эти поля должны иметь вход. И у меня было две идеи, но я не мог правильно их реализовать.

Вот пример класса:

public class Subscriber { 
    private String name; 
    private String email; 
    private Integer age; 
    private String phone; 
    private Gender gender; 
    private Date birthday; 
    private Date confirmBirthday; 
    private String birthdayMessage; 
    private Boolean receiveNewsletter; 

    //Getter and Setter 
} 

Предположим, я хочу, чтобы день рождения и поле confirmBirthday должны быть как нулевой или противиться, возможно, я хочу, чтобы комментировать их, используя одну аннотацию для каждого из них и выглядит это:

public class Subscriber { 
    private String name; 
    private String email; 
    private Integer age; 
    private String phone; 
    private Gender gender; 

    @NotNullIf(fieldName="confirmBirthday") 
    private Date birthday; 

    @NotNullIf(fieldName="birthday") 
    private Date confirmBirthday; 

    private String birthdayMessage; 
    private Boolean receiveNewsletter; 

    //Getter and Setter 
} 

Так что я действительно необходимо создать аннотацию проверки, как это:

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

    String fieldName(); 

    String message() default "{NotNullIf.message}"; 
    Class<?>[] group() default {}; 
    Class<? extends Payload>[] payload() default {}; 
} 

И после этого мне нужно будет создать саму валидатора:

public class NotNullIfConstraintValidator implements ConstraintValidator<NotNullIf, String>{ 

    private String fieldName; 

    public void initialize(NotNullIf constraintAnnotation) { 
     fieldName = constraintAnnotation.fieldName(); 
    } 

    public boolean isValid(String value, ConstraintValidatorContext context) { 
     if(value == null) { 
      return true; 
     }; 
     //TODO Validation 
     return false; 
    } 

} 

Так как это может быть достижимо?

Для другой идеи, использующей тот же класс, что и пример, в котором говорилось, что я хочу день рождения, confirmBirthday и birthdayMessdage могут быть только нулевыми или противостоять одновременно. Возможно, мне понадобится использовать аннотированную проверку класса на этот раз для проверки поперечного поля.

Вот как я полагаю, аннотировать класс: @NotNullIf (FIELDNAME = { "день рождения", "birthdayMessage" "confirmBirthday"}) класс Subscriber общественности { // Те же поля, как один из приведенных выше }

Поэтому, когда одно из этих полей не является нулевым, остальные их также необходимо ввести на размер клиента. Возможно ли это?

Я прочитал эту статью: How to access a field which is described in annotation property

Но я до сих пор запутанным о том, как проверка аннотаций работает из тех элементов, которые я перечислил выше. Возможно, мне понадобится подробное объяснение этого кода или, что еще хуже, мне может понадобиться какой-то базовый концептуальный осмотр.

Пожалуйста, помогите!

ответ

2

Для этого вы можете использовать type level annotation только потому, что аннотации на уровне поля не имеют доступа к другим полям!

Я сделал что-то похожее, чтобы разрешить выбор (в точности одно из нескольких свойств должно быть не равным нулю).В вашем случае @AllOrNone аннотацию (или любое имя вы предпочитаете) должны были бы массив имен полей и вы получите весь объект аннотированный типа к считывающему:

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

    String message() default "{AllOrNone.message}"; 
    Class<?>[] groups() default {}; 
    Class<? extends Payload>[] payload() default {}; 
} 

public class AllOrNoneValidator implements ConstraintValidator<AllOrNone, Object> { 
    private static final SpelExpressionParser PARSER = new SpelExpressionParser(); 
    private String[] fields; 

    @Override 
    public void initialize(AllOrNone constraintAnnotation) { 
     fields = constraintAnnotation.value(); 
    } 

    @Override 
    public boolean isValid(Object value, ConstraintValidatorContext context) { 
     long notNull = Stream.of(fields) 
       .map(field -> PARSER.parseExpression(field).getValue(value)) 
       .filter(Objects::nonNull) 
       .count(); 
     return notNull == 0 || notNull == fields.length; 
    } 
} 

(Как вы сказали, что вы используете Spring I б SPEL, чтобы даже вложенные поля доступа)

Теперь вы можете аннотировать Subscriber тип:

@AllOrNone({"birthday", "confirmBirthday"}) 
public class Subscriber { 
    private String name; 
    private String email; 
    private Integer age; 
    private String phone; 
    private Gender gender; 
    private Date birthday; 
    private Date confirmBirthday; 
    private String birthdayMessage; 
    private Boolean receiveNewsletter; 
} 
+0

есть ли что-нибудь еще, кроме этого, что нам нужно сделать для того, чтобы начать использовать пользовательские аннотации? –

+0

@TusharBanne, если у вас есть работающий механизм проверки, например, валидатор спящего режима на месте, нет –

+0

Привет, я не использую никаких фреймворков проверки. –

Смежные вопросы