Oleg Atamanenko
JSR-303 предоставляет удобный API для проверки валидности объектов, а также входных параметров. Очевидно, что стандартных валидаторов в какой-то момент может быть недостаточно, поэтому необходимо писать собственный.
Хочу показать на примере валидации запроса к MongoDB, как легко это делается.
@Target({FIELD, PARAMETER})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {MongoQueryValidator.class})
public @interface MongoQuery {
String message() default "Invalid mongo query";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Обратите внимание на аннотацию @Constraint - она описывает, какой класс будет проводить реальную валидацию. Атрибуты groups()
и payload()
являются обязательными.
public class MongoQueryValidator implements ConstraintValidator<MongoQuery, CharSequence> {
@Override
public void initialize(MongoQuery constraintAnnotation) {
}
@Override
public boolean isValid(CharSequence value, ConstraintValidatorContext context) {
// ignore null and empty strings.
if (null == value || value.length() == 0) {
return true;
}
try {
Query query = new BasicQuery(value.toString());
return true;
} catch (Exception e) {
return false;
}
}
}
В данном случае, валидатор у нас простой - мы пытаемся создать Mongo Query из переданной строки, если это не удаётся, то считаем, что строка не является корректным запросом к Mongo и возвращаем false
.
Если есть желание возвращать динамическое сообщение об ошибке, то это можно сделать следующим образом:
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("<Custom error message>").addConstraintViolation();
На этом всё, теперь нам остаётся только добавить валидацию на нашу модель или входной параметр.
public class Model {
@MongoQuery
private String queryCriteria;
}