Изучаем Java EE 7 - [40]

Шрифт
Интервал

>····return false;

>··}

>··return true;

>··}

>}

Метод isValid реализует алгоритм валидации URL, показанный в листинге 3.8. Параметр value содержит значение объекта, который требуется валидировать (например, file://www.cdbookstore.com/item/123). Параметр context инкапсулирует информацию о контексте, в котором осуществляется валидация (подробнее об этом ниже). Возвращаемое значение является логическим и указывает, успешно ли прошла валидация.

Основная задача валидационного алгоритма в листинге 3.8 — привести переданное значение к java.net.URL и проверить, правильно ли оформлен URL. После этого алгоритм также проверяет валидность атрибутов protocol, host и port. Если хотя бы один из них окажется невалидным, то метод вернет false. Как будет показано далее в разделе «Валидация ограничений», поставщик валидации компонентов задействует это логическое значение при создании списка ConstraintViolation.

Обратите внимание: метод isValid расценивает нуль как валидное значение (if (value == null… return true)). Спецификация Bean Validation считает такую практику рекомендуемой. Так удается не дублировать код ограничения @NotNull. Пришлось бы одновременно использовать ограничения @URL и @NotNull, чтобы указать, что вы хотите представить валидный ненулевой URL (такой как атрибут itemURL в листинге 3.6).

Сигнатура класса определяет тип данных, с которым ассоциируется ограничение. В листинге 3.8 URLValidator реализован для типа String (ConstraintValidator). Это означает, что если вы примените ограничение @URL к другому типу (например, к атрибуту lastConnectionDate), то получите при валидации исключение javax.validation.UnexpectedTypeException, так как не будет найден подходящий валидатор для типа java.util.Date. Если вам требуется ограничение, которое будет применяться сразу к нескольким типам данных, то необходимо либо использовать суперклассы, когда это возможно (скажем, можно было бы определить URLValidator для CharSequence, а не для строки, выразив его так: ConstraintValidator), либо применить несколько классов реализации (по одному для String, CharBuffer, StringBuffer, StringBuilder) в случае иного валидационного алгоритма.


Примечание

Реализация ограничения считается управляемым компонентом. Это означает, что с ней вы можете использовать все сервисы, доступные для обработки управляемых компонентов — в частности, внедрение любого вспомогательного класса, EJB или даже EntityManager (подробнее об этом — в следующих главах). Вы также можете перехватывать или декорировать методы initialize и isValid и даже задействовать управление жизненным циклом (@PostConstruct и @PreDestroy).


Множественные ограничения для одной целевой сущности

Иногда полезно применять одинаковое ограничение к одной и той же цели, используя при этом разные свойства или группы (подробнее об этом ниже). Распространенный пример такого рода — ограничение @Pattern, проверяющее соответствие целевой сущности определенному регулярному выражению. В листинге 3.9 показано, как применить два регулярных выражения к одному и тому же атрибуту. Множественные ограничения используют оператор AND. Это означает, что для валидности атрибута orderId необходимо, чтобы он удовлетворял двум регулярным выражениям.


Листинг 3.9. Объект POJO, в котором несколько шаблонных ограничений применяются к одному и тому же атрибуту

>public class Order {

>··@Pattern.List({

>······@Pattern(regexp = "[C,D,M][A-Z][0–9]*"),

>······@Pattern(regexp = ".[A-Z].*?")

>··})

>··private String orderId;

>··private Date creationDate;

>··private Double totalAmount;

>··private Date paymentDate;

>··private Date deliveryDate;

>··private List orderLines;

>··// Конструкторы, геттеры, сеттеры

>}

Чтобы иметь возможность несколько раз применить одно и то же ограничение к данной цели, ограничивающая аннотация должна определить массив на основе самой себя. При валидации компонентов такие массивы ограничений обрабатываются по-особому: каждый элемент массива интерпретируется как обычное ограничение. В листинге 3.10 показана ограничивающая аннотация @Pattern, определяющая внутренний интерфейс (произвольно названный List) с элементом Pattern[]. Внутренний интерфейс должен иметь правило хранения RUNTIME и использовать в качестве исходного ограничения один и тот же набор целей (в данном случае METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER).


Листинг 3.10. Шаблонное ограничение, определяющее список шаблонов

>@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})

>@Retention(RUNTIME)

>@Constraint(validatedBy = PatternValidator.class)

>public @interface Pattern {

>··String regexp();

>··String message() default "{javax.validation.constraints.Pattern.message}";

>··Class[] groups() default {};

>··Class[] payload() default {};

>··// Определяет несколько аннотаций @Pattern, применяемых к одному элементу

>··@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})

>··@Retention(RUNTIME)

>··@interface List {

>····Pattern[] value();

>··}

>}


Примечание

При разработке собственной ограничивающей аннотации следует добавить соответствующую ей аннотацию с множеством значений. Спецификация Bean Validation не требует этого строго, но настоятельно рекомендует определять внутренний интерфейс под названием List.


Рекомендуем почитать
Pro Git

Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.


Java 7

Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.


MFC и OpenGL

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


Симуляция частичной специализации

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


Обработка событий в С++

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


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.