• Validator под java: comp/Validator.
Затем вы можете искать эти JNDI-имена и получать экземпляры Validator. Но вместо поиска экземпляров через JNDI вы можете запросить, чтобы они были внедрены с помощью аннотации @Resource:
@Resource ValidatorFactory validatorFactory;
@Resource Validator validator;
Если ваш контейнер использует CDI (а это происходит в Java EE 7 по умолчанию), то он должен допускать внедрение с помощью @Inject:
@Inject ValidatorFactory;
@Inject Validator;
В любом случае (как с @Resource, так и с @Inject) контейнер следит за жизненным циклом фабрики. Поэтому вам не придется вручную создавать или закрывать ValidatorFactory.
Валидация компонентов
Как только вы получите Validator программно или путем внедрения, можете использовать его методы как для валидации целого компонента, так и для работы с отдельно взятым свойством. В листинге 3.21 показан класс CD, в котором действуют ограничения, связанные со свойствами, параметрами методов и возвращаемым значением.
public class CD {
··@NotNull @Size(min = 4, max = 50)
··private String title;
··@NotNull
··private Float price;
··@NotNull(groups = PrintingCatalog.class)
··@Size(min = 100, max = 5000, groups = PrintingCatalog.class)
··private String description;
··@Pattern(regexp = "[A-Z][a-z]{1,}")
··private String musicCompany;
··@Max(value = 5)
··private Integer numberOfCDs;
··private Float totalDuration;
··@NotNull @DecimalMin("5.8")
··public Float calculatePrice(@DecimalMin("1.4") Float rate) {
····return price * rate;
··}
··@DecimalMin("9.99")
··public Float calculateVAT() {
····return price * 0.196f;
··}
}
Чтобы валидировать свойства целого компонента, мы просто должны создать экземпляр CD и вызвать метод Validator.validate(). Если экземпляр валиден, то возвращается пустое множество ConstraintViolation. В следующем коде показан валидный экземпляр CD (с заголовком и ценой), который и проверяется. После этого код удостоверяет, что множество ограничений действительно является пустым.
CD cd = new CD("Kind of Blue", 12.5f);
Set<ConstraintViolation<CD>> violations = validator.validate(cd);
assertEquals(0, violations.size());
С другой стороны, следующий код вернет два объекта ConstraintViolation — один будет соответствовать заголовку, а другой — цене (оба они нарушают @NotNull):
CD cd = new CD();
Set<ConstraintViolation<CD>> violations = validator.validate(cd);
assertEquals(2, violations.size());
Валидация свойств
В предыдущих примерах валидируются свойства целого компонента. Но существует метод Validator.validateProperty(), позволяющий проверять конкретное именованное свойство заданного объекта.
В показанном ниже коде создается CD — объект, имеющий нулевой заголовок и нулевую цену; соответственно, такой компонент невалиден. Но, поскольку мы проверяем только свойство numberOfCDs, валидация проходит успешно и мы получаем пустое множество нарушений ограничений:
CD cd = new CD();
cd.setNumberOfCDs(2);
Set<ConstraintViolation<CD>> violations = validator.validateProperty(cd, "numberOfCDs");
assertEquals(0, violations.size());
С другой стороны, в следующем коде возникает нарушение ограничения, так как максимальное количество объектов CD должно равняться пяти, а не семи. Обратите внимание: мы используем API ConstraintViolation для проверки количества нарушений, интерполированного сообщения, возвращенного при нарушении, невалидного значения и шаблона сообщения:
CD cd = new CD();
cd.setNumberOfCDs(7);
Set<ConstraintViolation<CD>> violations = validator.validateProperty(cd, "numberOfCDs");
assertEquals(1, violations.size());
assertEquals("must be less than or equal to 5", violations.iterator(). next(). getMessage());
assertEquals(7, violations.iterator(). next(). getInvalidValue());
assertEquals("{javax.validation.constraints.Max.message}",
·············violations.iterator(). next(). getMessageTemplate());
Валидация значений
Пользуясь методом Validator.validateValue(), можно проверять, удастся ли успешно валидировать конкретное свойство указанного класса при наличии у свойства заданного значения. Этот метод удобен при опережающей валидации, так как не требует даже создавать экземпляр компонента, заполнять или обновлять его значения.
Следующий код не создает объект CD, а просто ссылается на атрибут numberOfCDs класса CD. Он передает значение и проверяет, является ли свойство валидным (количество CD не должно превышать пяти):
Set<ConstraintViolation<CD>> constr = validator.validateValue(CD.class, "numberOfCDs", 2);