Аннотации из javax.validation.constraints не работают
Какая конфигурация необходима для использования аннотаций от javax.validation.constraints
, таких как @Size
, @NotNull
и т.д.? Здесь мой код:
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
public class Person {
@NotNull
private String id;
@Size(max = 3)
private String name;
private int age;
public Person(String id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
}
Когда я пытаюсь использовать его в другом классе, проверка не работает (т.е. объект создается без ошибок):
Person P = new Person(null, "Richard3", 8229));
Почему это не относится к ограничениям для id
и name
? Что еще мне нужно сделать?
Ответы
Ответ 1
Для проверки JSR-303 bean для работы в Spring вам нужно несколько вещей:
- Конфигурация пространства имен MVC для аннотаций:
<mvc:annotation-driven />
- JAR-303 spec JAR:
validation-api-1.0.0.GA.jar
(похоже, что у вас уже есть)
- Реализация спецификации, такая как Hibernate Validation, которая, как представляется, является наиболее часто используемым примером:
hibernate-validator-4.1.0.Final.jar
- В bean для проверки, аннотации проверки, либо из спецификации JAR, либо из JAR реализации (который вы уже сделали)
- В обработчике, который вы хотите проверить, аннотируйте объект, который вы хотите проверить, с помощью
@Valid
, а затем включите BindingResult
в сигнатуру метода для захвата ошибок.
Пример:
@RequestMapping("handler.do")
public String myHandler(@Valid @ModelAttribute("form") SomeFormBean myForm, BindingResult result, Model model) {
if(result.hasErrors()) {
...your error handling...
} else {
...your non-error handling....
}
}
Ответ 2
Вы должны использовать Validator, чтобы проверить, действительно ли ваш класс.
Person person = ....;
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
Set<ConstraintViolation<Person>> violations = validator.validate(person);
Затем, при повторных нарушениях, вы можете обнаружить нарушения.
Ответ 3
Вам нужно будет вызвать Validator в Entity, если вы хотите его проверить. Затем вы получите набор ConstraintViolationException, который в основном показывает, для какого поля /s вашего объекта существует нарушение ограничения и что именно было. Возможно, вы также можете поделиться некоторыми из кода, который вы ожидаете проверить свою сущность.
Часто используемым методом является проверка в транзакции @PrePersist и отката при использовании нескольких модификаций данных во время транзакции или других действий при получении исключения проверки.
Ваш код должен выглядеть следующим образом:
@PrePersist
public void prePersist(SomeEntity someEntity){
Validator validator = Validation.buildDefaultValidatorFactory.getValidator();
Set<ConstraintViolation<SomeEntity>> = validator.validate(someEntity);
//do stuff with them, like notify client what was the wrong field, log them, or, if empty, be happy
}
Ответ 4
Вы также можете просто использовать @NonNull
с помощью библиотеки lombok library, по крайней мере для сценария @NotNull
. Подробнее: https://projectlombok.org/api/lombok/NonNull.html
Ответ 5
в моем случае у меня было пользовательское ограничение уровня класса, которое не вызывалось.
@CustomValidation // not called
public class MyClass {
@Lob
@Column(nullable = false)
private String name;
}
как только я добавил ограничение на уровне поля для моего класса, как пользовательского, так и стандартного, сработало ограничение уровня класса.
@CustomValidation // now it works. super.
public class MyClass {
@Lob
@Column(nullable = false)
@NotBlank // adding this made @CustomValidation start working
private String name;
}
мне кажется, что мне плохо, но достаточно легко обойти, я думаю,
Ответ 6
Я пришел сюда несколько лет после того, как, и я мог бы исправить это благодаря atrain комментарий выше. В моем случае мне не хватало @Valid
в API, который получает объект (POJO в моем случае), который был аннотирован @Size
. Это решило проблему.
Мне не нужно было добавлять какие-либо дополнительные аннотации, такие как @Valid
или @NotBlank
к переменной, аннотированной @Size
, только это ограничение в переменной и то, что я упомянул в API...
Класс Pojo:
...
@Size(min = MIN_LENGTH, max = MAX_LENGTH);
private String exampleVar;
...
Класс API:
...
public void exampleApiCall(@RequestBody @Valid PojoObject pojoObject){
...
}
Спасибо и ура
Ответ 7
Вам нужно добавить @Valid в каждую переменную-член, которая также была объектом, содержащим ограничения проверки.
Ответ 8
Итак, @Valid в интерфейсе службы будет работать только для этого объекта. Если у вас есть еще какие-либо проверки в иерархии объекта ServiceRequest, вы можете явно активировать проверки. Так вот как я это сделал:
public class ServiceRequestValidator {
private static Validator validator;
@PostConstruct
public void init(){
validator = Validation.buildDefaultValidatorFactory().getValidator();
}
public static <T> void validate(T t){
Set<ConstraintViolation<T>> errors = validator.validate(t);
if(CollectionUtils.isNotEmpty(errors)){
throw new ConstraintViolationException(errors);
}
}
}
Если вы хотите вызвать проверку для этого объекта, вам необходимо иметь следующие аннотации на уровне объекта.
@Valid
@NotNull
Ответ 9
для параметров метода вы можете использовать Objects.requireNonNull() следующим образом: test(String str) { Objects.requireNonNull(str); }
test(String str) { Objects.requireNonNull(str); }
Но это проверяется только во время выполнения и выдает NPE, если ноль. Это как проверка предварительных условий. Но это может быть то, что вы ищете.
Ответ 10
Ну, я пропустил аннотацию @Valid в моем контроллере. это сработало после этого.
Ответ 11
Отличный ответ от atrain,
но, возможно, лучшее решение для обнаружения исключений - использовать собственный HandlerExceptionResolver
и поймать
@Override
public ModelAndView resolveException(
HttpServletRequest aReq,
HttpServletResponse aRes,
Object aHandler,
Exception anExc
){
// ....
if(anExc instanceof MethodArgumentNotValidException) // do your handle error here
}
Тогда вы сможете содержать ваш обработчик как можно более чистым.
Вам больше не нужны BindingResult, Model и SomeFormBean в myHandlerMethod.
Ответ 12
Я новичок в Spring, поэтому, пожалуйста, возьмите мой ответ с солью. Я также не мог заставить @NotNull работать, когда использовал его. У меня был экран с полями ввода в нем, я не заполнил его и переместил мой экран вперед (для возможного сохранения в какой-то БД).
Я ломал голову только, чтобы наткнуться на @NotBlank. Это был мой ответ. Поле, о котором идет речь, было пустым, я полагаю, что это было "" или пустая строка, не имеющая нулевого значения для каждого слова. Таким образом, проверка на @NotBlank была поймана.
Не уверен, что это поможет вам, но не может помешать расследовать эту возможность, если вы также боретесь с тем, что некоторые @NotNulls являются неотобравшимися.
Ответ 13
Недавно я столкнулся с этой проблемой в очень похожей ситуации:
Удовлетворил все требования в списке ответов с наивысшим рейтингом, но все же получил неправильный результат.
Поэтому я посмотрел на свои зависимости и обнаружил, что скучаю по некоторым из них. Я исправил это, добавив недостающие зависимости.
Я использовал Hibernate, необходимые зависимости были:
![Dependencies Snapshot]()
* Снимок, сделанный в классе "Spring & Hibernate для начинающих" @Udemy