Подтвердить что ты не робот

Аннотации из 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? Что еще мне нужно сделать?

4b9b3361

Ответ 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