Валидация 2

Download Report

Transcript Валидация 2

Java-2
Валидация
Контекст валидации
Обобщенное ограничение
public class ItemServerConnection {
@URL
private String resourceURL;
@NotNull
@URL(protocol = "http", host = "www.cdbookstore.com")
private String itemURL;
@URL(protocol = "ftp", port = 21)
private String ftpServerURL;
private Date lastConnectionDate;
// Конструкторы, геттеры, сеттеры
}
Обобщенное ограничение
@Constraint(validatedBy = {URLValidator.class})
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR,
PARAMETER})
@Retention(RUNTIME)
public @interface URL {
String message() default "Malformed URL";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String protocol() default "";
String host() default "";
int port() default -1;
}
public class URLValidator implements ConstraintValidator<URL, String> {
private String protocol; private String host; private int port;
public void initialize(URL url) {
protocol=url.protocol(); host=url.host(); port = url.port();
}
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null || value.length() == 0) {return true;}
java.net.URL url;
try {
url = new java.net.URL(value);
} catch (MalformedURLException e) {return false;}
if(protocol!=null&&protocol.length()>0&&!url.getProtocol().equals(protocol))
{
return false;
}
if (host!=null && host.length()>0 && !url.getHost().startsWith(host)) {
return false;
}
if (port != -1 && url.getPort() != port) {
return false;
}
return true;
}
}
Контекст
Если рассмотреть пример с ограничением @URL, то мы
увидим, что всему ограничению здесь соответствует лишь
одно сообщение об ошибке (Malformed URL).
Но у этого ограничения несколько атрибутов (protocol, host и
port), и нам могут понадобиться специфичные сообщения
для каждого из этих атрибутов, например: Invalid protocol
или Invalid host.
public boolean isValid(String value, ConstraintValidatorContext context) {
...
if(protocol!=null&&protocol.length()>0&&!url.getProtocol().equals(protocol))
{
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("Неверный
протокол").addConstraintViolation();
return false;
}
...
}
Группы валидации
Группы
public interface Payment {}
@ChronologicalDates(groups = Delivery.class)
public class Order {
@NotNull private Long id;
@NotNull @Past
private Date creationDate;
private Double totalAmount;
@NotNull(groups = Payment.class)
@Past(groups = Payment.class)
private Date paymentDate;
@NotNull(groups = Delivery.class)
@Past(groups = Delivery.class)
private Date deliveryDate;
private List<OrderLine> orderLines;
// ...
}
Валидация
Validator
Порядок работы:
1. Устанавливается подходящая реализация
ConstraintValidator, которая будет использоваться при
определении данного ограничения (например,
определяется ConstraintValidator для ограничения @Size,
применяемого со строкой).
2. Выполняется метод isValid.
3. Если isValid возвращает true, программа переходит к
следующему ограничению.
4. Если isValid возвращает false, поставщик валидации
компонентов добавляет ConstraintViolation в список
нарушений ограничений.
Методы Validator
ExecutableValidator
Как пользоваться? (1)
Первый этап валидации компонента — приобрести
экземпляр интерфейса Validator. Вы можете либо получить
Validator программно (если ваш код выполняется вне
контейнера), либо внедрить его.
ValidatorFactory factory =
Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Или
@Inject ValidatorFactory;
@Inject Validator;
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;
}
}
Как пользоваться? (2)
Чтобы валидировать свойства целого компонента, мы просто
должны создать экземпляр CD и вызвать метод
Validator.validate(). Если экземпляр валиден, то
возвращается пустое множество ConstraintViolation
CD cd = new CD("Kind of Blue", 12.5f);
Set<ConstraintViolation<CD>> violations = validator.validate(cd);
assertEquals(0, violations.size());
CD cd = new CD();
Set<ConstraintViolation<CD>> violations = validator.validate(cd);
assertEquals(2, violations.size());
Валидация свойств
CD cd = new CD();
cd.setNumberOfCDs(2);
Set<ConstraintViolation<CD>> violations =
validator.validateProperty(cd, "numberOfCDs");
assertEquals(0, violations.size());
Валидация значений
Пользуясь методом Validator.validateValue(), можно проверять,
удастся ли успешно валидировать конкретное свойство
указанного класса при наличии у свойства заданного значения.
Этот метод удобен при опережающей валидации, так как не
требует даже создавать экземпляр компонента, заполнять или
обновлять его значения.
Set<ConstraintViolation<CD>> constr =
validator.validateValue(CD.class, "numberOfCDs", 2);
assertEquals(0, constr.size());
Set<ConstraintViolation<CD>> constr =
validator.validateValue(CD.class, "numberOfCDs", 7);
assertEquals(1, constr.size());
Валидация методов
CD cd = new CD("Kind of Blue", 12.5f);
Method method =
CD.class.getMethod("calculatePrice", Float.class);
ExecutableValidator methodValidator =
validator.forExecutables();
Set<ConstraintViolation<CD>> violations =
methodValidator.validateParameters
(cd, method, new Object[] { new Float(1.2) });
assertEquals(1, violations.size());
Валидация групп
• Группа определяет подмножество ограничений. Вместо
валидации всех ограничений для данного компонента
проверяется только нужное подмножество. При
объявлении каждого ограничения указывается список
групп, в которые входит это ограничение. Если явно не
объявлена ни одна группа, то ограничение относится к
группе Default.
CD cd = new CD();
cd.setDescription("Too short");
Set<ConstraintViolation<CD>> violations =
validator.validate(cd, Default.class,
PrintingCatalog.class);
assertEquals(3, violations.size());