Проверка строки Java с использованием значений перечисления и аннотации - PullRequest
23 голосов
/ 09 июня 2011

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

@ValidateString(enumClass=com.co.enum)
String dataType;

int maxValue;
int minValue;
int precision;

или

@ValidateString(values={"String","Boolean", "Integer"})
String dataType;

int maxValue;
int minValue;
int precision;

Я также хочу провести некоторую проверку других переменных в зависимости от значения, установленного в dataType,

, если(dataType = "String") maxValue, minValue, precision все должны быть нулевыми или нулевыми.

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

Кто-нибудь, пожалуйста, помогите мне

Ответы [ 6 ]

26 голосов
/ 12 января 2014

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

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.ReportAsSingleViolation;
import javax.validation.constraints.NotNull;

@Documented
@Constraint(validatedBy = EnumValidatorImpl.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@NotNull(message = "Value cannot be null")
@ReportAsSingleViolation
public @interface EnumValidator {

  Class<? extends Enum<?>> enumClazz();

  String message() default "Value is not valid";

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

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

}

Реализация вышеприведенного класса:

import java.util.ArrayList;
import java.util.List;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class EnumValidatorImpl implements ConstraintValidator<EnumValidator, String> {

  List<String> valueList = null;

  @Override
  public boolean isValid(String value, ConstraintValidatorContext context) {
    if(!valueList.contains(value.toUpperCase())) {
      return false;
    }
    return true;
  }

  @Override
  public void initialize(EnumValidator constraintAnnotation) {
    valueList = new ArrayList<String>();
    Class<? extends Enum<?>> enumClass = constraintAnnotation.enumClazz();

    @SuppressWarnings("rawtypes")
    Enum[] enumValArr = enumClass.getEnumConstants();

    for(@SuppressWarnings("rawtypes")
    Enum enumVal : enumValArr) {
      valueList.add(enumVal.toString().toUpperCase());
    }

  }

}

ИСПОЛЬЗОВАНИЕ ВЫШЕГО АННОТАЦИИ ОЧЕНЬ ПРОСТО

 @JsonProperty("lead_id")
  @EnumValidator( enumClazz=DefaultEnum.class,message="This error is coming from the enum class", groups = {Group1.class })
  private String leadId;
21 голосов
/ 15 июня 2011

Это то, что я сделал.

Аннотация

public @interface ValidateString {

    String[] acceptedValues();

    String message() default "{uk.dds.ideskos.validator.ValidateString.message}";

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

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

Класс проверки

public class StringValidator implements ConstraintValidator<ValidateString, String>{

    private List<String> valueList;

    @Override
    public void initialize(ValidateString constraintAnnotation) {
        valueList = new ArrayList<String>();
        for(String val : constraintAnnotation.acceptedValues()) {
            valueList.add(val.toUpperCase());
        }
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if(!valueList.contains(value.toUpperCase())) {
            return false;
        }
        return true;
    }

}

И я использовал его как

@ValidateString(acceptedValues={"Integer", "String"}, message="Invalid dataType")
String dataType;

Long maxValue;
Long minValue;

Теперь мне нужно выяснить, как реализовать условную проверку т.е.если String, то maxValue и minValue должны быть равны нулю или нулю.

Есть идеи?

8 голосов
/ 09 июня 2011

Откажитесь от представления String и создайте реальное перечисление.

public enum DataType {
   STRING,
   BOOLEAN,
   INTEGER;
}

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

Этостоит усилий, чтобы изменить свой код для использования перечислений.Однако, предполагая, что вы не можете, вы можете, по крайней мере, изменить аннотацию на использование перечислений.

@ValidateString(DataType.STRING) String dataType;

, и таким образом ваша аннотация ValidateString получит выгоду от перечислений, даже если остальныекод не работает.

Теперь при крайне редкой вероятности того, что вы вообще не можете использовать перечисление, вы можете установить статические открытые целые числа, которые отображают каждое принятое значение.

public class DataType {
  public static final int STRING = 1;
  public static final int BOOLEAN = 2;
  ...
}

Однако, если вы используете String для параметра аннотации, у нас нет системы проверки типов, которая распространяется на тип, чтобы указать, что разрешены только определенные значения.Другими словами, Java не имеет возможности сделать что-то вроде этого:

public int<values=[1,3,5,7..9]> oddInt; 

, что приведет к ошибке, если вы попытаетесь назначить

 oddInt = 4;

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

0 голосов
/ 26 сентября 2018

Вот подробный пример с функцией динамического сообщения об ошибке документация Hibernate

https://docs.jboss.org/hibernate/validator/4.1/reference/en-US/html/validator-customconstraints.html#validator-customconstraints-simple

0 голосов
/ 11 сентября 2018

Я принимаю ответ Раджива Синглы https://stackoverflow.com/a/21070806/8923905, только для того, чтобы оптимизировать код и позволить параметру String быть нулевым, если в вашем приложении это не является обязательным и может быть пустым:

1 - Удалить аннотацию @NotNull на интерфейсе

2 - См. Модифицированный код ниже для реализации.

public class EnumValidatorImpl implements ConstraintValidator <EnumValidator,String> {

    private List<String> valueList = null;

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return null == value || valueList.contains(value.toUpperCase());
    }

    @Override
    public void initialize(EnumValidator constraintAnnotation) {
        valueList = new ArrayList<>();
        Class<? extends Enum<?>> enumClass = constraintAnnotation.enumClass();

        Enum[] enumValArr = enumClass.getEnumConstants();

        for(Enum enumVal : enumValArr) {
            valueList.add(enumVal.toString().toUpperCase());
        }

    }
}
0 голосов
/ 31 января 2012

Вы можете использовать @NotNull аннотацию вместе с вашей.Для этого необходимо добавить аннотацию @Target( { ANNOTATION_TYPE }) в ValidateString.

http://docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-customconstraints.html

...