Изучаем Java EE 7 - [48]
>public class Customer {
>··@NotNull @Size(min = 2)
>··private String firstName;
>··private String lastName;
>··@Email
>··private String email;
>··private String phoneNumber;
>··@Past
>··private Date dateOfBirth;
>··private Address deliveryAddress;
>··// Конструкторы, геттеры, сеттеры
>}
Написание компонента Address
У Customer может быть ноль или один адрес доставки. Address — это компонент, включающий всю информацию, необходимую для доставки товара по указанному адресу: улица, город, штат, ZIP-код и страна. В листинге 3.23 показан компонент Address с ограничением @NotNull, налагаемым на важнейшие атрибуты (street1, city и zipcode), а также с ограничением @ZipCode, проверяющим валидность ZIP-кода (это ограничение будет разработано позже).
>public class Address {
>··@NotNull
>··private String street1;
>··private String street2;
>··@NotNull
>··private String city;
>··private String state;
>··@NotNull @ZipCode
>··private String zipcode;
>··private String country;
>··// Конструкторы, геттеры, сеттеры
>}
Написание ограничения @Email
Ограничение @Email не встроено в систему валидации компонентов, поэтому нам самим придется его разработать. Нам не понадобится класс реализации (@Constraint(validatedBy = {})), так как вполне работоспособным будет обычная ограничивающая аннотация с регулярным выражением (@Pattern) и заданным размером. В листинге 3.24 показана ограничивающая аннотация @Email.
>@Size(min = 7)
>@Pattern(regexp = "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\."
>····+ "[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*"
>····+ "@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?")
>@ReportAsSingleViolation
>@Constraint(validatedBy = {})
>@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
>@Retention(RUNTIME)
>public @interface Email {
>··String message() default " {org.agoncal.book.javaee7.chapter03.Email.message}";
>··Class>[] groups() default {};
>··Class extends Payload>[] payload() default {};
>··@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
>··@Retention(RUNTIME)
>··@interface List {
>····Email[] value();
>··}
>}
Обратите внимание: в листинге 3.24 сообщение об ошибке представляет собой ключ пакета, определяемый в файле META-INF/ValidationMessages.properties.
>org.agoncal.book.javaee7.chapter03.Email.message=invalid email address
Написание ограничения @ZipCode
Ограничение @ZipCode написать сложнее, чем @Email. ZIP-код имеет определенный формат (например, в США он состоит из пяти цифр), который не составляет труда проверить с помощью регулярного выражения. Но чтобы гарантировать, что ZIP-код не только синтаксически верен, но и валиден, необходимо прибегнуть к внешней службе, которая будет проверять, существует ли конкретный ZIP-код в базе данных. Именно поэтому ограничивающая аннотация ZipCode в листинге 3.25 требует класса реализации (ZipCodeValidator).
>@Constraint(validatedBy = ZipCodeValidator.class)
>@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
>@Retention(RUNTIME)
>public @interface ZipCode {
>··String message() default "{org.agoncal.book.javaee7.chapter03.ZipCode.message}";
>··Class>[] groups() default {};
>··Class extends Payload>[] payload() default {};
>··@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
>··@Retention(RUNTIME)
>··@interface List {
>····ZipCode[] value();
>··}
>}
В листинге 3.26 показан класс реализации ограничивающей аннотации: ZipCodeValidator реализует интерфейс javax.validation.ConstraintValidator с обобщенным типом String. Метод isValid реализует алгоритм валидации, в рамках которого выполняется сопоставление с шаблоном регулярного выражения и происходит вызов внешнего сервиса: ZipCodeChecker. Код ZipCodeChecker здесь не показан, так как в данном случае он неважен. Но необходимо отметить, что он внедряется (@Inject) с квалификатором CDI (@USA, показан в листинге 3.27). Итак, здесь мы наблюдаем взаимодействие спецификаций CDI и Bean Validation.
>public class ZipCodeValidator implements ConstraintValidator
>··@Inject @USA
>··private ZipCodeChecker checker;
>··private Pattern zipPattern = Pattern.compile("\\d{5}(-\\d{5})?");
>··public void initialize(ZipCode zipCode) {
>··}
>··public boolean isValid(String value, ConstraintValidatorContext context) {
>····if (value == null)
>······return true;
>····Matcher m = zipPattern.matcher(value);
>····if (!m.matches())
>····return false;
>····return checker.isZipCodeValid(value);
>··}
>}
>@Qualifier
>@Retention(RUNTIME)
>@Target({FIELD, TYPE, METHOD})
>public @interface USA {
>}
В следующих главах будет показано, как интегрировать валидацию компонентов с другими спецификациями, в частности JPA (можно добавлять ограничения к вашим сущностям) или JSF (можно ограничивать базовые компоненты).
Написание интеграционных тестов CustomerIT и AddressIT
Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.
Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.