0 added
0 removed
Original
2026-01-01
Modified
2026-03-10
1
<p>Теги: java, pom.xml, java enterprise, java ee, hibernate, bean validation 2.0 (jsr 380), @null, @notnull, @size, @past, @future, @min, @max, javax.validation.constraints, cdi, validateproperty, validatevalue</p>
1
<p>Теги: java, pom.xml, java enterprise, java ee, hibernate, bean validation 2.0 (jsr 380), @null, @notnull, @size, @past, @future, @min, @max, javax.validation.constraints, cdi, validateproperty, validatevalue</p>
2
<p>Ни для кого не секрет, что ни одна повседневная задача разработчика не обходится без потребности валидировать поступающие "извне" потоки данных: с пользовательских HTML-форм, внешних систем и т.д. На первый взгляд, ничего нет плохого в том, что каждый программист пытается по-своему решить эту задачу (фактически написав "очередной велосипед", используя множество проверок, состоящих из if-else блоков).</p>
2
<p>Ни для кого не секрет, что ни одна повседневная задача разработчика не обходится без потребности валидировать поступающие "извне" потоки данных: с пользовательских HTML-форм, внешних систем и т.д. На первый взгляд, ничего нет плохого в том, что каждый программист пытается по-своему решить эту задачу (фактически написав "очередной велосипед", используя множество проверок, состоящих из if-else блоков).</p>
3
<p>Но при таком подходе высока вероятность, что в будущем поддержка такого "спагетти"-кода станет крайне затруднительной из-за постоянной потребности в модификации атрибутов класса или в случае переиспользования проверок в различных участках системы, например, на клиенте и на сервере. Чтобы избежать подобных проблем, в стеке JavaEE предусмотрели спецификацию<strong>Bean Validation 2.0 (JSR 380)</strong>.</p>
3
<p>Но при таком подходе высока вероятность, что в будущем поддержка такого "спагетти"-кода станет крайне затруднительной из-за постоянной потребности в модификации атрибутов класса или в случае переиспользования проверок в различных участках системы, например, на клиенте и на сервере. Чтобы избежать подобных проблем, в стеке JavaEE предусмотрели спецификацию<strong>Bean Validation 2.0 (JSR 380)</strong>.</p>
4
<h2>Итак, что же это за зверь?</h2>
4
<h2>Итак, что же это за зверь?</h2>
5
<p>Основная идея данной спецификации заключается в использовании таких аннотаций, как<strong>@Null /@NotNull, @Size, @Past /@Future, @Min /@Max</strong>и т. д., размещаемых над полями класса для проверки заранее ожидаемых значений, вхождения в границы диапазона, соответствия регулярным выражениям и т. д.</p>
5
<p>Основная идея данной спецификации заключается в использовании таких аннотаций, как<strong>@Null /@NotNull, @Size, @Past /@Future, @Min /@Max</strong>и т. д., размещаемых над полями класса для проверки заранее ожидаемых значений, вхождения в границы диапазона, соответствия регулярным выражениям и т. д.</p>
6
<p>Более того, эту функциональность без каких-либо проблем можно использовать и в JavaSE-приложениях, для чего лишь потребуется в<strong>pom.xml</strong>подключить следующие зависимости:</p>
6
<p>Более того, эту функциональность без каких-либо проблем можно использовать и в JavaSE-приложениях, для чего лишь потребуется в<strong>pom.xml</strong>подключить следующие зависимости:</p>
7
<dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>${validation.version}</version> </dependency> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>${validator.version}</version> </dependency> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator-annotation-processor</artifactId> <version>${validator.version}</version> </dependency><p>Валидатор<strong>Hibernate</strong>(на момент написания заметки самая актуальная версия validator.version - 6.0.11.Final, validation.version - 2.0.1.Final) является референсной имплементацией спецификации<strong>Bean Validation</strong>.</p>
7
<dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>${validation.version}</version> </dependency> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>${validator.version}</version> </dependency> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator-annotation-processor</artifactId> <version>${validator.version}</version> </dependency><p>Валидатор<strong>Hibernate</strong>(на момент написания заметки самая актуальная версия validator.version - 6.0.11.Final, validation.version - 2.0.1.Final) является референсной имплементацией спецификации<strong>Bean Validation</strong>.</p>
8
<p><em>Обращаю внимание, что добавление этой библиотеки в проект не добавит поддержки аспектов персистентности одноимённой библиотеки.</em></p>
8
<p><em>Обращаю внимание, что добавление этой библиотеки в проект не добавит поддержки аспектов персистентности одноимённой библиотеки.</em></p>
9
<h2>Немного практики</h2>
9
<h2>Немного практики</h2>
10
<p>Теперь посмотрим, как же использовать всю мощь спецификации в прикладном коде. Представим, что определён класс<strong>User</strong>с некоторым набором характеристик:</p>
10
<p>Теперь посмотрим, как же использовать всю мощь спецификации в прикладном коде. Представим, что определён класс<strong>User</strong>с некоторым набором характеристик:</p>
11
import javax.validation.constraints.*; public class User { @NotBlank(message = "Name cannot be null") private String name; @AssertTrue private boolean hasWork; @Size(min = 10, max = 500, message = "Description should be in range of 10 and 500 symbols") private String description; @Min(value = 18, message = "Age should be greater than 18") @Max(value = 100, message = "Age should be less than 100") private int age; @NotNull @Email(message = "Email must be valid") private String email; // setters and getters }<p>Уже только взглянув на сами аннотации, интуитивно догадываемся, что свойства: -<strong>name</strong>должно быть отличным от<strong>null</strong>и пустой строки “”; -<strong>hasWork</strong>иметь значение истинно; -<strong>description</strong>- строка, количество символов которой не должно превышать 500 и быть меньше 10 символов; -<strong>age</strong>лежит в диапазоне 18..100, включительно; -<strong>email</strong>должно удовлетворять формату электронных писем.</p>
11
import javax.validation.constraints.*; public class User { @NotBlank(message = "Name cannot be null") private String name; @AssertTrue private boolean hasWork; @Size(min = 10, max = 500, message = "Description should be in range of 10 and 500 symbols") private String description; @Min(value = 18, message = "Age should be greater than 18") @Max(value = 100, message = "Age should be less than 100") private int age; @NotNull @Email(message = "Email must be valid") private String email; // setters and getters }<p>Уже только взглянув на сами аннотации, интуитивно догадываемся, что свойства: -<strong>name</strong>должно быть отличным от<strong>null</strong>и пустой строки “”; -<strong>hasWork</strong>иметь значение истинно; -<strong>description</strong>- строка, количество символов которой не должно превышать 500 и быть меньше 10 символов; -<strong>age</strong>лежит в диапазоне 18..100, включительно; -<strong>email</strong>должно удовлетворять формату электронных писем.</p>
12
<p>В примере представлены далеко не все возможные аннотации, определяющие ограничения значений полей бинов. С полным списком можно познакомиться в пакете<strong>javax.validation.constraints</strong>.</p>
12
<p>В примере представлены далеко не все возможные аннотации, определяющие ограничения значений полей бинов. С полным списком можно познакомиться в пакете<strong>javax.validation.constraints</strong>.</p>
13
<p><em>Также акцентирую внимание на том, что допустимо комбинирование разных ограничений, не противоречащих здравой логике (в приведенном примере - одновременно использовать<strong>@Min @Max</strong>и<strong>@NotNull @Email</strong>).</em></p>
13
<p><em>Также акцентирую внимание на том, что допустимо комбинирование разных ограничений, не противоречащих здравой логике (в приведенном примере - одновременно использовать<strong>@Min @Max</strong>и<strong>@NotNull @Email</strong>).</em></p>
14
<p>Не менее интересной является возможность использования данных аннотаций для элементов коллекций в следующем виде:</p>
14
<p>Не менее интересной является возможность использования данных аннотаций для элементов коллекций в следующем виде:</p>
15
Set<@NotBlank String> hobbies; Далее, мы попробуем создать заранее инвалидный объект класса User, не определив ряд обязательных полей: User user = new User(); user.setHasWork(true); user.setDescription("Simple description about author!"); user.setAge(30);<p>Осталось научиться проверять бины и получать информацию о потенциальных проблемах валидации такого рода объектов. Для этого важно получить ссылку на объект класса<strong>Validator</strong>. В JavaEE-контейнере можно просто заинжектить данный объект, используя спецификацию<strong>CDI</strong>:</p>
15
Set<@NotBlank String> hobbies; Далее, мы попробуем создать заранее инвалидный объект класса User, не определив ряд обязательных полей: User user = new User(); user.setHasWork(true); user.setDescription("Simple description about author!"); user.setAge(30);<p>Осталось научиться проверять бины и получать информацию о потенциальных проблемах валидации такого рода объектов. Для этого важно получить ссылку на объект класса<strong>Validator</strong>. В JavaEE-контейнере можно просто заинжектить данный объект, используя спецификацию<strong>CDI</strong>:</p>
16
@Inject Validator validator;<p>Для JavaSE-приложений можно инициализировать данный объект явно:</p>
16
@Inject Validator validator;<p>Для JavaSE-приложений можно инициализировать данный объект явно:</p>
17
ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator();<p>У объекта<strong>validator</strong>есть несколько полезных методов<strong>validate</strong>, проверяющих все свойства бина -<strong>validateProperty</strong>и<strong>validateValue</strong>, испытывающие конкретное свойство объекта.</p>
17
ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator();<p>У объекта<strong>validator</strong>есть несколько полезных методов<strong>validate</strong>, проверяющих все свойства бина -<strong>validateProperty</strong>и<strong>validateValue</strong>, испытывающие конкретное свойство объекта.</p>
18
Set<ConstraintViolation<User>> violations = validator.validate(user); for (ConstraintViolation<User> violation : violations) { log.error(violation.getMessage()); }<p>В текущем примере поля<strong>name</strong>и<strong>email</strong>не проинициализированы и об этом будет сообщено в логе. Для получения невалидного значения достаточно вызвать:</p>
18
Set<ConstraintViolation<User>> violations = validator.validate(user); for (ConstraintViolation<User> violation : violations) { log.error(violation.getMessage()); }<p>В текущем примере поля<strong>name</strong>и<strong>email</strong>не проинициализированы и об этом будет сообщено в логе. Для получения невалидного значения достаточно вызвать:</p>
19
violation.getInvalidValue()<h2>Вот и познакомились с базовыми возможностями спецификации<strong>Bean Validation</strong>!</h2>
19
violation.getInvalidValue()<h2>Вот и познакомились с базовыми возможностями спецификации<strong>Bean Validation</strong>!</h2>
20
<p>Если у вас появилось желание узнать подробности и узнать, например, как создавать свои кастомные валидаторы, каким образом объединять проверки в группы, как использовать эти возможности с другими спецификациями (JAX-RS, JPA), а также делать сообщения интернациональными - приходите к нам на курс "Разработчик Java Enterprise"!</p>
20
<p>Если у вас появилось желание узнать подробности и узнать, например, как создавать свои кастомные валидаторы, каким образом объединять проверки в группы, как использовать эти возможности с другими спецификациями (JAX-RS, JPA), а также делать сообщения интернациональными - приходите к нам на курс "Разработчик Java Enterprise"!</p>
21
<p><em>Есть вопрос? Напишите в комментариях!</em></p>
21
<p><em>Есть вопрос? Напишите в комментариях!</em></p>
22
22