··String message() default "{javax.validation.constraints.Pattern.message}";
··Class >[] groups() default {};
··Class extends Payload>[] payload() default {};
··// Определяет несколько аннотаций @Pattern, применяемых к одному элементу
··@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
··@Retention(RUNTIME)
··@interface List {
····Pattern[] value();
··}
}
При разработке собственной ограничивающей аннотации следует добавить соответствующую ей аннотацию с множеством значений. Спецификация Bean Validation не требует этого строго, но настоятельно рекомендует определять внутренний интерфейс под названием List.
Выше мы рассмотрели различные способы разработки ограничения, которое применялось бы к атрибуту (или геттеру). Но вы также можете создать ограничение для целого класса. Идея заключается в том, чтобы выразить ограничение на основе нескольких свойств, которыми обладает заданный класс.
В листинге 3.11 показан класс для оформления заказа. Этот заказ товара следует определенному жизненному циклу бизнес-логики: создается в системе, оплачивается клиентом, а потом доставляется клиенту. Класс отслеживает все эти события, оперируя соответствующими датами: creationDate, paymentDate и deliveryDate. Аннотация @ChronologicalDates действует на уровне класса и проверяет, находятся ли эти даты в правильном хронологическом порядке.
@ChronologicalDates
public class Order {
··private String orderId;
··private Double totalAmount;
··private Date creationDate;
··private Date paymentDate;
··private Date deliveryDate;
··private List
··// Конструкторы, геттеры, сеттеры
}
В листинге 3.12 показана реализация ограничения @ChronologicalDates. Подобно тем ограничениям, что были рассмотрены выше, оно реализует интерфейс ConstraintValidator, обобщенный тип которого — Order. Метод isValid проверяет, находятся ли три даты в правильном хронологическом порядке, и если это так — возвращает true.
public class ChronologicalDatesValidator implements
ConstraintValidator
··@Override
··public void initialize(ChronologicalDates constraintAnnotation) {
··}
··@Override
··public boolean isValid(Order order, ConstraintValidatorContext context) {
····return order.getCreationDate(). getTime() <
···········order.getPaymentDate(). getTime() &&
···········order.getPaymentDate(). getTime() <··
···········order.getDeliveryDate(). getTime();
··}
}
Ограничения, действующие на уровне методов, появились в спецификации Bean Validation 1.1. Существуют ограничения, объявляемые для методов, а также для конструкторов (геттеры не считаются ограниченными методами). Эти ограничения могут быть добавлены к параметрам метода (это будут «ограничения параметров») или к самому методу («ограничения возвращаемых значений»). Таким образом, спецификация Bean Validation может использоваться для описания и валидации соглашения, применяемого с заданным методом или конструктором. Так строится хорошо известный стиль «Программирование по соглашениям»:
• предусловия должны выполняться вызывающей стороной еще до вызова метода или конструктора;
• постусловия гарантированно выполняются для вызывающей стороны после возврата вызова, направленного к методу или конструктору.