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

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


Ограничения на уровне класса

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

В листинге 3.11 показан класс для оформления заказа. Этот заказ товара следует определенному жизненному циклу бизнес-логики: создается в системе, оплачивается клиентом, а потом доставляется клиенту. Класс отслеживает все эти события, оперируя соответствующими датами: creationDate, paymentDate и deliveryDate. Аннотация @ChronologicalDates действует на уровне класса и проверяет, находятся ли эти даты в правильном хронологическом порядке.


Листинг 3.11. Ограничение, действующее на уровне класса и проверяющее верность хронологической последовательности дат

>@ChronologicalDates

>public class Order {

>··private String orderId;

>··private Double totalAmount;

>··private Date creationDate;

>··private Date paymentDate;

>··private Date deliveryDate;

>··private List orderLines;

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

>}

В листинге 3.12 показана реализация ограничения @ChronologicalDates. Подобно тем ограничениям, что были рассмотрены выше, оно реализует интерфейс ConstraintValidator, обобщенный тип которого — Order. Метод isValid проверяет, находятся ли три даты в правильном хронологическом порядке, и если это так — возвращает true.


Листинг 3.12. Реализация ограничения ChronologicalDates, действующего на уровне класса

>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 может использоваться для описания и валидации соглашения, применяемого с заданным методом или конструктором. Так строится хорошо известный стиль «Программирование по соглашениям»:

• предусловия должны выполняться вызывающей стороной еще до вызова метода или конструктора;

• постусловия гарантированно выполняются для вызывающей стороны после возврата вызова, направленного к методу или конструктору.

В листинге 3.13 показано несколько способов использования ограничений на уровне метода. Сервис CardValidator проверяет кредитную карту в соответствии с конкретным валидационным алгоритмом. Для этого конструктор использует ограничение @NotNull с параметром ValidationAlgorithm. Затем два метода validate возвращают Boolean (валидна кредитная карта или нет?) с ограничением @AssertTrue для возвращаемого типа и ограничениями @NotNull и @Future у параметров методов.


Листинг 3.13. Сервис с конструктором и ограничениями на уровне метода

>public class CardValidator {

>··private ValidationAlgorithm validationAlgorithm;

>··public CardValidator(@NotNull ValidationAlgorithm validationAlgorithm) {

>····this.validationAlgorithm = validationAlgorithm;

>··}

>··@AssertTrue

>··public Boolean validate(@NotNull CreditCard creditCard) {

>····return validationAlgorithm.validate(creditCard.getNumber(), 

>creditCard.getCtrlNumber());

>··}

>··@AssertTrue

>··public Boolean validate(@NotNull String number, @Future Date expiryDate, 

>··Integer controlNumber, String type) {

>····return validationAlgorithm.validate(number, controlNumber);

>··}

>}


Наследование ограничений

Часто в бизнес-модели действует механизм наследования. При использовании валидации компонентов приходится накладывать ограничения на классы, суперклассы или интерфейсы вашей бизнес-модели. Наследование ограничений у свойств работает точно так же, как и обычное наследование в Java: оно является кумулятивным. Таким образом, если один компонент наследует от другого, то ограничения наследуемого компонента также заимствуются и будут валидироваться.

В листинге 3.15 показан класс CD, расширяющий Item (листинг 3.14). Оба класса имеют атрибуты и применяемые с ними ограничения. Если валидируется экземпляр CD, то валидируются не только его ограничения, но и ограничения, налагаемые на родительский класс.


Листинг 3.14. Суперкласс Item, использующий ограничения

>Public class Item {

>··@NotNull

>··protected Long id;

>··@NotNull @Size(min = 4, max = 50)

>··protected String title;

>··protected Float price;

>··protected String description;

>··@NotNull

>··public Float calculateVAT() {

>····return price * 0.196f;

>··}

>··@NotNull

>··public Float calculatePrice(@DecimalMin("1.2") Float rate) {

>····return price * rate;


Рекомендуем почитать
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 так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.