Обзор дела
В этой статье мы рассмотрим основы проверки Java-бинов с использованием стандартной среды — JSR 380, также известной как Bean Validation 2.0.
Конечно, проверка пользовательского ввода является чрезвычайно распространенным требованием в большинстве приложений, и среда Java Bean Validation стала стандартом де-факто для обработки этой логики.
JSR 380
JSR 380 — это спецификация API Java для проверки компонентов, часть JavaEE и JavaSE, которая использует такие аннотации, как @NotNull, @Min и @Max, чтобы гарантировать, что свойства компонента соответствуют определенным критериям.
Эта версия требует Java 8 или более поздней версии и использует новые функции, добавленные в Java 8 (например, аннотацию типа), и поддерживает новые типы, такие как Optional и LocalDate.
Полную информацию о спецификации см.JSR 380.
зависимость
Мы будем использовать пример Maven, чтобы показать необходимые зависимости, но, конечно, эти банки могут быть добавлены различными способами.
Аутентифицировать API
Согласно спецификации JSR 380, зависимость validation-api содержит стандартный API проверки:
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.0.Final</version>
</dependency>
Эталонная реализация API проверки
Hibernate Validator — эталонная реализация API проверки.
Чтобы использовать его, мы должны добавить следующие зависимости:
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.2.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>6.0.2.Final</version>
</dependency>
Небольшое замечание: hibernate-validator полностью независим от аспектов персистентности Hibernate, и, добавляя его в качестве зависимости, мы не добавляем эти аспекты персистентности в проект.
Зависимости языка выражений
JSR 380 обеспечивает поддержку интерполяции переменных, позволяя использовать выражения в сообщениях о нарушениях.
Чтобы проанализировать эти выражения, мы должны добавить зависимости от API языка выражений и реализации этого API. GlassFish предоставляет эталонную реализацию:
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.6</version>
</dependency>
Если эти JAR-файлы не добавлены, вы получите сообщение об ошибке во время выполнения, подобное этому:
HV000183: Не удалось загрузить «javax.el.ExpressionFactory». Проверьте, есть ли у вас зависимости EL от вашего пути к классам, или используйте ParameterMessageInterpolator.
Используйте аннотации проверки
Мы будем использовать компонент User в качестве основного примера и добавим к нему простую проверку:
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.validation.constraints.Email;
public class User {
@NotNull(message = "Name cannot be null")
private String name;
@AssertTrue
private boolean working;
@Size(min = 10, max = 200, message
= "About Me must be between 10 and 200 characters")
private String aboutMe;
@Min(value = 18, message = "Age should not be less than 18")
@Max(value = 150, message = "Age should not be greater than 150")
private int age;
@Email(message = "Email should be valid")
private String email;
// standard setters and getters
}
Все аннотации, используемые в примерах, являются стандартными аннотациями JSR:
- @NotNull — проверяет, что аннотированное значение свойства не равно нулю.
- @AssertTrue — проверяет, что значение аннотированного свойства истинно.
- @Size — проверяет, что значение аннотированного свойства имеет размер между свойствами min и max; может применяться к свойствам String, Collection, Map и массива.
- @Min — Проверяет, что значение аннотированного свойства меньше значения свойства.
- @Max — проверяет, что значение аннотированного свойства больше, чем значение свойства.
- @Email — проверяет, что аннотированное свойство является действительным адресом электронной почты.
Некоторые аннотации принимают другие атрибуты, но атрибут сообщения является общим для всех атрибутов. Это сообщение обычно отображается, когда значение соответствующего свойства не проходит проверку.
Некоторые другие аннотации, которые можно найти в JSR:
- @NotEmpty — Проверяет, что свойство не является нулевым или пустым; может применяться к значениям String, Collection, Map или Array.
- @NotBlank — может применяться только к текстовым значениям и проверяет, что свойство не является нулевым или пробельным.
- @Positive и @PositiveOrZero — применяются к числовым значениям и проверяются, являются ли они строго положительными или положительными, включая 0
- @Negative и @NegativeOrZero — применяются к числовым значениям и проверяются, являются ли они строго отрицательными или отрицательными, включая 0
- @Past и @PastOrPresent — Проверяет, что значение даты находится в прошлом, включая настоящее; может применяться к типам дат, в том числе добавленным в Java 8.
- @Future и @FutureOrPresent — убедитесь, что значения дат относятся к будущему, включая настоящее
Аннотации проверки также могут применяться к элементам коллекции:
List<@NotBlank String> preferences;
В этом случае добавьте проверку к любому значению в списке параметров.
Спецификация также поддерживает новый необязательный тип в Java 8:
private LocalDate dateOfBirth;
public Optional<@Past LocalDate> getDateOfBirth() {
return Optional.of(dateOfBirth);
}
Здесь платформа проверки автоматически распаковывает значение LocalDate и проверяет его.
Верификация программы
Некоторые фреймворки, такие как Spring, могут запускать процесс проверки простым способом, просто используя аннотации. В основном это сделано для того, чтобы нам не приходилось взаимодействовать с API проверки программы.
Теперь пойдем по ручному маршруту и установим его программно:
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Чтобы проверить bean-компонент, мы должны сначала иметь объект Validator, который создается с использованием ValidatorFactory.
определить бобы
Теперь мы собираемся установить недопустимого пользователя — используйте пустое значение имени:
User user = new User();
user.setWorking(true);
user.setAboutMe("Its all about me!");
user.setAge(50);
Проверить бины
Теперь, когда у нас есть валидатор, мы можем проверить наш компонент, передав его методу проверки. Все, что нарушает ограничения, определенные в объекте User, будет возвращено как Set.
Set<ConstraintViolation<User>> violations = validator.validate(user);
Перебирая нарушения, мы можем получить все сообщения о нарушениях, используя метод getMessage.
for (ConstraintViolation<User> violation : violations) {
log.error(violation.getMessage());
}
В нашем примере (ifNameIsNull_nameValidationFails) коллекция будет содержать ConstraintViolation с сообщением «Name not not null».
Заключение дела
В этой статье основное внимание уделяется простой передаче стандартного Java Validation API и иллюстрируются основы проверки bean-компонентов с использованием аннотации и API javax.validation.