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


person Darshan Patil    schedule 06.01.2012    source источник
comment
По волшебству не работает, нужно настроить валидатор. В каком контексте работает этот код?   -  person skaffman    schedule 06.01.2012
comment
Также обратитесь к этому вопросу и ответу, который позволяет избежать ручной проверки BindingResult на наличие ошибок проверки: stackoverflow.com/questions/61992596/   -  person Manishoaham    schedule 27.05.2020


Ответы (16)


Чтобы проверка bean-компонентов JSR-303 работала в Spring, вам нужно несколько вещей:

  1. Конфигурация пространства имен MVC для аннотаций: <mvc:annotation-driven />
  2. Спецификация JSR-303 JAR: validation-api-1.0.0.GA.jar (похоже, она у вас уже есть)
  3. Реализация спецификации, например Hibernate Validation, которая является наиболее часто используемым примером: hibernate-validator-4.1.0.Final.jar
  4. В bean-компоненте, подлежащем проверке, аннотации проверки, либо из JAR спецификации, либо из JAR реализации (что вы уже сделали)
  5. В обработчике, который вы хотите проверить, аннотируйте объект, который вы хотите проверить, с помощью @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....
    }
}
person atrain    schedule 06.01.2012
comment
Это дает нам конфигурацию валидатора по умолчанию. Теперь я хотел бы настроить валидатор перед его использованием. Где я могу это настроить? Любая перезапись для реализации или установка для вызова? - person Stephane; 08.01.2016
comment
Проблема, с которой я столкнулся, заключалась в том, что я не понимал, что мне нужно добавить @Valid к каждой переменной-члену, которая также была объектом, содержащим ограничения проверки. - person WhiteKnight; 17.03.2016
comment
Я добавил @Valid в свой RequestBody, но ограничение по-прежнему не вызывается. Я проверил зависимости, есть ли конфликт. Решил и это. Не уверен, в чем проблема. Я также проверил, есть ли аннотации к полю. Применяется. - person Tushar Banne; 08.01.2018
comment
Как ни странно, все пункты, упомянутые выше, у меня тоже выполнены. Тем не менее проверка не работает :( - person Andrey M. Stepanov; 09.05.2018

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

Person person = ....;
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
Set<ConstraintViolation<Person>> violations = validator.validate(person);

Затем, повторяя набор нарушений, можно найти нарушения.

person Artem    schedule 06.01.2012
comment
Я думаю, что на этот вопрос можно ответить независимо от используемого фреймворка. спасибо .. но у меня есть одно сомнение, как мы можем проверить параметр, передаваемый какому-либо методу в контексте без какой-либо структуры. например test(@NotNull String str), можем ли мы написать валидатор для того же? - person agpt; 23.04.2014

В моем случае я использовал весеннюю загрузку версии 2.3.0. Когда я изменил свою зависимость от maven для использования 2.1.3, это сработало.

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.3.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
</parent>
<dependencies>
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
    </dependency>
</dependencies>
person yrazlik    schedule 12.05.2020
comment
Начиная с версии 2.3.0.RELEASE Spring Boot Web и стартеры WebFlux больше не зависят от стартера проверки, поэтому вам нужно добавить spring-boot-starter-validation в свой pom.xml. Подробнее см. 2.3.0 Примечания к выпуску - person MartinBG; 16.05.2020

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

Часто используемый метод - выполнить проверку в @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
}
person Nikola Yovchev    schedule 06.01.2012

Вы также можете просто использовать @NonNull с библиотекой lombok, по крайней мере, для @NotNull сценария. Подробнее: https://projectlombok.org/api/lombok/NonNull.html

person Andreas Covidiot    schedule 17.08.2015

Я приехал сюда через несколько лет и смог исправить это благодаря 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){
  ...
}

Спасибо и ура

person xCovelus    schedule 22.10.2018

в моем случае у меня было настраиваемое ограничение на уровне класса, которое не вызывалось.

@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;
}

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

person ChetPrickles    schedule 17.07.2016

Вам нужно добавить @Valid к каждой переменной-члену, которая также была объектом, содержащим ограничения проверки.

person Chad    schedule 25.05.2017

После версии 2.3.0 spring-boot-strarter-test (который включал NotNull / NotBlank / etc) теперь является sprnig boot-strarter-validation

Просто измените его с ....- test на ...- validation, и он должен работать.

Если не понизить версию, которую вы используете до 2.1.3, это также решит.

person Pedro Sousa    schedule 21.08.2020

Таким образом, @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
person Akshay    schedule 18.09.2017

для параметров метода вы можете использовать Objects.requireNonNull () следующим образом: test(String str) { Objects.requireNonNull(str); } Но это проверяется только во время выполнения и выдает NPE, если null. Это похоже на проверку предварительных условий. Но это может быть то, что вы ищете.

person Edward    schedule 10.10.2018

Отличный ответ от 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.

person PavelP    schedule 17.01.2019

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

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

Я использовал спящий режим, требуемые зависимости были:  Снимок зависимостей

* Снимок сделан в классе "Spring & Hibernate для начинающих" @ Udemy

person Junda Yang    schedule 01.10.2019

Если вы используете ломбок, вы можете использовать аннотацию @NonNull. или просто добавьте зависимость javax.validation в файл pom.xml.

person Prasenjit Mahato    schedule 20.06.2020

Для тех, кто не смог выполнить проверку на стороне сервера через зависимость проверки Hibernate. Просто удалите зависимость проверки подлинности Hibernate + javax и добавьте проверку Spring-boot-starter. Он предоставляет Hibernate Validator внутри, и у меня он отлично сработал.

Кредиты: - комментарий с YouTube.

person Shivam Jaiswal    schedule 19.07.2021

В моем случае я удалил эти строки

1-импорт javax.validation.constraints.NotNull;

2-импорт javax.validation.constraints.Size;

3- @NotNull

4- @ Размер (макс. = 3)

person Hermann N'ZI    schedule 14.06.2020