Сигнатура класса определяет тип данных, с которым ассоциируется ограничение. В листинге 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();

Перейти на страницу:

Похожие книги