1. Обзор
В этом кратком руководстве мы рассмотрим основы проверки Java-бина с помощью стандартной среды — JSR 380, также известной как Bean Validation 2.0
.
Проверка ввода пользователя является очень распространенным требованием в большинстве приложений. А среда Java Bean Validation стала стандартом де-факто для обработки такого рода логики.
2. JSR 380
JSR 380 — это спецификация API Java для проверки компонентов, входящая в состав Jakarta EE и JavaSE. Это гарантирует, что свойства bean-компонента соответствуют определенным критериям, используя такие аннотации, как @NotNull
, @Min
и @Max
.
Эта версия требует Java 8 или более поздней версии и использует преимущества новых функций, добавленных в Java 8, таких как аннотации типов и поддержка новых типов, таких как Optional
и LocalDate
.
Для получения полной информации о спецификациях прочитайте JSR 380 .
3. Зависимости
Мы собираемся использовать пример Maven, чтобы показать необходимые зависимости. Но, конечно, эти баночки можно добавлять по-разному.
3.1. API проверки
Согласно спецификации JSR 380, зависимость validation-api
содержит стандартные API проверки:
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
3.2. Справочная реализация API проверки
Hibernate Validator — эталонная реализация API проверки.
Чтобы использовать его, нам нужно добавить следующую зависимость:
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.13.Final</version>
</dependency>
Небольшое примечание: hibernate-validator
полностью отделен от аспектов персистентности Hibernate. Таким образом, добавляя его как зависимость, мы не добавляем эти аспекты постоянства в проект. ``
3.3. Зависимости языка выражений
JSR 380 поддерживает интерполяцию переменных, позволяя использовать выражения внутри сообщений о нарушениях.
Чтобы проанализировать эти выражения, мы добавим зависимость javax.el
от GlassFish, которая содержит реализацию спецификации языка выражений:
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.0</version>
</dependency>
4. Использование аннотаций проверки
Здесь мы возьмем компонент 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
проверяет, что значение аннотированного свойства не равноnull
.@AssertTrue
подтверждает, что аннотированное значение свойстваистинно.
@Size
проверяет, что аннотированное значение свойства имеет размер между атрибутамиmin
иmax
; может применяться кString
,Collection
,Map
и свойствам массива.@Min
проверяет, что аннотированное свойство имеет значение не меньше атрибутаvalue .
@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
и проверит его.
5. Программная проверка
В некоторых фреймворках, таких как Spring, есть простые способы инициировать процесс проверки, просто используя аннотации. В основном это сделано для того, чтобы нам не приходилось взаимодействовать с API программной проверки.
Теперь давайте пойдем по ручному маршруту и настроим все программно:
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Чтобы проверить bean-компонент, нам сначала нужен объект Validator
, который создается с использованием ValidatorFactory
.
5.1. Определение компонента
Теперь мы собираемся настроить этого недопустимого пользователя — с нулевым значением имени
:
User user = new User();
user.setWorking(true);
user.setAboutMe("Its all about me!");
user.setAge(50);
5.2. Проверка компонента
Теперь, когда у нас есть Validator
, мы можем проверить наш компонент, передав его методу проверки .
Любые нарушения ограничений, определенных в объекте User
, будут возвращены как Set
:
Set<ConstraintViolation<User>> violations = validator.validate(user);
Перебирая нарушения, мы можем получить все сообщения о нарушениях, используя метод getMessage
:
for (ConstraintViolation<User> violation : violations) {
log.error(violation.getMessage());
}
В нашем примере ( ifNameIsNull_nameValidationFails
) набор будет содержать один ConstraintViolation
с сообщением «Имя не может быть нулевым».
6. Заключение
В этой статье основное внимание уделялось простому проходу через стандартный Java Validation API. Мы показали основы проверки компонентов с использованием аннотаций javax.validation
и API.
Как обычно, реализацию концепций из этой статьи и все фрагменты кода можно найти на GitHub .