Jakarta Bean Validation — это спецификация, описывающая API для валидации объектов в рамках Jakarta EE. Вы можете использовать данную спецификацию для валидации в проектах вне зависимости от используемого фреймворка или сервера приложений. Более того, вы можете использовать Jakarta Bean Validation в полностью самостоятельных проектах, не основанных на Jakarta EE или каком-либо фреймворке.
Идейным предшественником Jakarta Bean Validation 3.0 является Bean Validation 2.0 из Java EE, однако все изменения в спецификации заключаются в переименованиях, связанных с миграцией проекта из Java EE в Jakarta EE.
В рамках этой статьи будет рассмотрен минимальный набор зависимостей, необходимый для использования Jakarta Bean Validation, описаны основные интерфейсы и ограничения или правила валидации.
Цикл статей о Jakarta Bean Validation
Данная статья является частью цикла статей о Jakarta Bean Validation:
- Знакомство с Jakarta Bean Validation 3.0 (Вы сейчас её читаете)
- Валидация объектов
- Валидация методов
- Группы валидации (В процессе написания)
- Создание ограничения и валидатора (В процессе написания)
- Интерполяция сообщений (В процессе написания)
- Конфигурация валидатора (В процессе написания)
Зависимости
Основной зависимостью является библиотека jakarta.validation:jakarta.validation-api
, актуальная версия которой на момент написания статьи — 3.0.2
. Добавлять данную библиотеку в зависимости проекта, как правило, не нужно — если ваш проект использует Jakarta EE API, то Bean Validation уже включён в зависимости. В остальных случаях данная библиотека будет являться транзитивной зависимостью библиотек, реализующих Bean Validation (например, org.hibernate.validator:hibernate-validator
), либо библиотек зависящих от реализаций (например, org.springframework.boot:spring-boot-starter-validation
).
Для примеров кода в рамках данной статьи я буду использовать Hibernate Validator 8.0.1.Final:
Основные типы Jakarta Bean Validation
Основные интерфейсы, с которыми вам предстоит взаимодействовать при использовании Jakarta Bean Validation: Validator
, ExecutableValidator
, ConstraintViolation
и ConstraintValidator
.
Validator
Интерфейс Validator
используется для валидации объектов. Этот интерфейс объявляет следующие методы:
validate
— для валидации объектовvalidateProperty
— для валидации отдельного свойства объектаvalidateValue
— для валидации значения относительно ограничений какого-либо свойства классаgetConstraintsForClass
— для получения ограничений классаunwrap
— для получения экземпляра класса, специфичного для конкретной реализации Jakarta Bean ValidationforExecutables
— для получения экземпляраExecutableValidator
, валидатора для методов
Создать валидатор можно одним из трёх способов:
ExecutableValidator
ExecutableValidator
используется для валидации аргументов и возвращаемых значений методов и конструкторов. Он объявляет четыре метода:
validateParameters
— для валидации аргументов методаvalidateConstructorParameters
— для валидации аргументов конструктораvalidateReturnValue
— для валидации значения, возвращённого методомvalidateConstructorReturnValue
— для валидации значения, возвращённого конструктором
Получить экземпляр ExecutableValidator
можно при помощи метода Validator.forExecutables()
:
ConstraintViolation
Все методы валидации возвращают множество экземпляров ConstraintViolation
. Этот интерфейс описывает ошибку валидации и объявляет следующие методы:
getMessage()
— для получения интерполированного сообщенияgetMessageTemplate()
— для получения исходного шаблона сообщенияgetRootBean()
— для получения валидируемого объектаgetRootBeanClass()
— для получения класса валидируемого объектаgetLeafBean()
— для получения объекта, в котором возникла ошибка валидацииgetExecutableParameters()
— для получения аргументов валидируемого методаgetExecutableReturnValue()
— для получения возвращаемого значения валидируемого методаgetPropertyPath()
— для получения пути валидируемого свойстваgetInvalidValue()
— для получения значения, не прошедшего валидациюgetConstraintDescriptor()
— для получения дескриптора ограничения, которое было нарушеноunwrap()
— для получения более конкретной реализацииConstraintViolation
, специфичной для провайдера
Пример получения отчёта об ошибках валидации:
ConstraintValidator
Интерфейс ConstraintValidator
используется для реализации логики конкретных правил валидации и объявляет два метода:
initialize
— для инициализации, в ходе которой можно получить доступ аннотации ограниченияisValid
— непосредственно для реализации логики валидации.
Пример реализации ConstraintValidator
для ограничения jakarta.validation.constraints.NotNull
:
Ограничения или правила валидации
Ограничение (constraint) — это правило валидации, описываемое специфичной для Jakarta Bean Validation аннотацией. Ограничение может применяться использованием аннотаций в коде, либо при помощи XML.
Типичная аннотация ограничения имеет следующий вид:
Аннотация @Target
задаёт список элементов, к которым аннотация ограничения может быть применена. Данный список может отличаться от продемонстрированного.
@Retention
задаёт вариант доступности аннотации при компиляции исходного кода, значение RUNTIME
указывает на доступность аннотации во время исполнения.
Если аннотация ограничения должна иметь возможность применения несколько раз к элементу кода, то в значении аннотации @Repeatable
необходимо указать имя класса-аннотации, описывающего множественное применение. При этом описывающая множественное применение аннотация должна иметь @Target
и @Retention
идентичные у описываемой аннотации.
Аннотация @Documented
указывает на то, что описываемая аннотация будучи применённой к элементам кода будет являться частью публичного контракта.
При помощи аннотации @Constraint
можно задать список классов, валидирующих элементы кода, отмеченные описываемой аннотацией.
Аннотация ограничения должна иметь как минимум три стандартных свойства:
String message
, содержащее шаблон сообщения, который будет использован в случае нарушения ограниченияClass<?>[] groups
, содержащее список типов для группировки ограничений при валидацииClass<? extends Payload>[] payload
, содержащее список типов полезной нагрузки. Данное свойство может использоваться для передачи каких-то дополнительных данных в класс-валидатор.
Кроме этих свойств класс-аннотация ограничения может содержать свойство ConstraintTarget validationAppliesTo()
со значением по умолчанию ConstraintTarget.IMPLICIT
, данное свойство используется для ограничений, применимых к методам и конструкторам во избежание неоднозначности объекта валидации.
Стандартные ограничения
Jakarta Bean Validation предоставляет набор стандартных ограничений, который вы можете использовать в своих проектах.
@AssertFalse
Применяется к свойствам типов java.lang.Boolean
и boolean
, ограничивает валидируемое значение значением false
.
@AssertTrue
Аннотация, аналогичная предыдущей, применяется также к свойствам типов java.lang.Boolean
и boolean
, но ограничивает валидируемое значение значением true
.
@DecimalMax(value=, inclusive=)
Аннотация, применяемая к свойствам типов, представляющих целые числа:
BigDecimal
BigInteger
CharSequence
byte
,short
,int
,long
и их классы-обёртки
Обратите внимание на то, что float
и double
, а так же их классы-обёртки не поддерживаются ввиду особенностей округления.
Свойством value
задаётся максимальное значение валидируемого свойства, а inclusive
— включается ли максимально значение в диапазон допустимых значений.
@DecimalMin(value=, inclusive=)
Аналогичная предыдущей аннотация, также применяемая к свойствам типов, представляющих целые числа:
BigDecimal
BigInteger
CharSequence
byte
,short
,int
,long
и их классы-обёртки
double
и float
не поддерживаются.
Свойством value
задаётся минимальное значение валидируемого свойства, а inclusive
— включается ли минимальное значение в диапазон допустимых значений.
@Digits(integer=, fraction=)
Аннотация, при помощи которой можно ограничить максимальное количество знаков в целой и дробной части числа.
Как и предыдущие два ограничения поддерживает типы:
BigDecimal
BigInteger
CharSequence
byte
,short
,int
,long
и их классы-обёртки
Типы double
и float
не поддерживаются.
Свойство integer
задаёт максимальное количество знаков целой части числа, fraction
— дробной.
@Email
Аннотация, применяемая к свойствам типа CharSequence
и его наследников (String
), требующая, чтобы валидируемая строка была валидным адресом электронной почты.
@Future
Аннотация, ограничивающая значение свойства будущим временем.
Поддерживаемые типы валидируемых свойств:
java.util.Date
java.util.Calendar
java.time.Instant
java.time.LocalDate
java.time.LocalDateTime
java.time.LocalTime
java.time.MonthDay
java.time.OffsetDateTime
java.time.OffsetTime
java.time.Year
java.time.YearMonth
java.time.ZonedDateTime
java.time.chrono.HijrahDate
java.time.chrono.JapaneseDate
java.time.chrono.MinguoDate
java.time.chrono.ThaiBuddhistDate
@FutureOrPresent
Аннотация, ограничивающая значение свойства будущим или настоящим временем.
Список поддерживаемых типов идентичен таковому у @Future
.
@Max(value=)
Аннотация, позволяющая указать максимальное значение свойства числового типа.
Поддерживаемые типы:
BigDecimal
BigInteger
CharSequence
byte
,short
,int
,long
и их классы-обёртки
double
и float
не поддерживаются.
@Min(value=)
Аннотация, позволяющая указать минимальное значение свойства числового типа.
Список поддерживаемых типов идентичен таковому у @Max
.
@NotBlank
Аннотация, требующая, чтобы валидиуемое строковое значение не было пустой строкой или не состояло исключительно из пробельных символов.
Применяется к CharSequence
и наследникам.
@NotEmpty
Аннотация, требующая, чтобы валидируемое свойство было непустым объектом.
Поддерживаемые типы:
CharSequence
и наследники (length()
)Collection
и наследники (size()
)Map
и наследники (size()
)- Массивы (
length
)
@NotNull
Аннотация, требующая, чтобы валидируемое значение было отлично от null
.
@Negative
Аннотация, требующая, чтобы валидируемое значение было отрицательным числом.
Поддерживаемые типы:
BigDecimal
BigInteger
CharSequence
byte
,short
,int
,long
,float
,double
и их классы-обёртки
Значение null
считается валидным.
@NegativeOrZero
Аннотация, требующая, чтобы валидируемое значение было отрицательным числом, либо нулём.
Поддерживаемые типы:
BigDecimal
BigInteger
CharSequence
byte
,short
,int
,long
,float
,double
и их классы-обёртки
Значение null
считается валидным.
@Null
Аннотация, требующая, чтобы валидируемое значение было null
.
@Past
Аннотация, ограничивающая значение свойства прошедшим временем.
Список поддерживаемых типов идентичен таковому у @Future
.
@PastOrPresent
Аннотация, ограничивающая значение свойства прошедшим или настоящим временем.
Список поддерживаемых типов идентичен таковому у @Future
.
@Pattern(regex=, flags=)
Аннотация, требующая, чтобы валидируемое значение типа CharSequence
соответствовало регулярному выражению.
В свойстве regex
указывается регулярное выражение, а в flags
— массив флагов.
@Positive
Аннотация, требующая, чтобы валидируемое значение было положительным числом.
Поддерживаемые типы:
BigDecimal
BigInteger
CharSequence
byte
,short
,int
,long
,float
,double
и их классы-обёртки
Значение null
считается валидным.
@PositiveOrZero
Аннотация, требующая, чтобы валидируемое значение было положительным числом, либо нулём.
Поддерживаемые типы:
BigDecimal
BigInteger
CharSequence
byte
,short
,int
,long
,float
,double
и их классы-обёртки
Значение null
считается валидным.
@Size(min=, max=)
Аннотация, ограничивающая размеры значения валидируемого свойства.
Поддерживаемые типы:
CharSequence
и наследники (length()
)Collection
и наследники (size()
)Map
и наследники (size()
)- Массивы (
length
)
Свойством min
задаётся минимальный размер (включительно), свойством max
— максимальный (включительно).
В следующих статьях будет продемонстрировано применение ограничений для валидаций объектов и методов.