Содержание
Аннотация @Valid ограничения Java Bean Validation гарантирует, что при проверке объекта проверка повторяется во всех полях, аннотированных @Valid . Это действительно облегчает выполнение обычно сложной задачи проверки целых графов объектов.
Чтобы разобраться в этом посте, вы должны знать основы использования Java Bean Validation .
Проверка графов объектов за один шаг с @Valid
Чтобы лучше понять, почему аннотация @Valid является такой ценной функцией, я начну с того, что @Valid вам, что нужно сделать для проверки графа объектов, который его не использует.
Раздутый код без @Valid
Рассмотрим случай ограниченного класса A который объявляет зависимость от другого набора ограниченных классов B и C Здесь у нас есть простой граф объектов, где у каждого сотрудника в этой ассоциации есть свой набор ограничений проверки. Без аннотации @Valid проверка графа является довольно трудоемкой задачей, поскольку каждый экземпляр A , B и C необходимо проверять отдельно, с помощью многочисленных вызовов метода validate() реализации интерфейса Validator .
Рассмотрим следующие классы:
public class AccountProcessor { @NotEmpty(message = "Account number may not be empty") @Size(min = 8, max = 8, message = "Account number must be an 8-digit string") private String accountNumber; public AccountProcessor(String accountNumber) { this.accountNumber = accountNumber; } public void processAccount() { // process the account here } } public class PaymentService { private AccountProcessor accountProcessor; @NotEmpty(message = "Payment method may not be empty") private String paymentMethod; public PaymentService(AccountProcessor accountProcessor, String paymentMethod) { this.accountProcessor = accountProcessor; this.paymentMethod = paymentMethod; } }
На данный момент нам удалось создать базовый граф объектов с помощью AccountProcessor с использованием AccountProcessor . Без аннотации @Valid график должен проверяться для каждого объекта следующим образом:
Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); AccountProcessor accountProcessor = new AccountProcessor(""); PaymentService paymentService = new PaymentService(accountProcessor, ""); validator .validate(accountProcessor) .stream() .forEach(violation -> System.out.println(violation.getMessage())); validator .validate(paymentService) .stream() .forEach(violation -> System.out.println(violation.getMessage()));
В этом случае ни экземпляр AccountProcessor ни его PaymentService не были правильно инициализированы и взяты вместе, что вызовет три нарушения ограничения.
Хотя валидация работает, как и ожидалось, код раздут от необходимости вызывать validate отдельно для каждого экземпляра.
Использование @Valid для @Valid объектов
Чтобы улучшить код проверки, давайте PaymentService рефакторинг класса PaymentService и @Valid аннотацию @Valid с ее полем AccountProcessor :
public class PaymentService { @Valid private AccountProcessor accountProcessor; // other class members and methods as before }
Влияние использования аннотации @Valid можно заметить здесь:
Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); AccountProcessor defaultAccountProcessor = new DefaultAccountProcessor(""); PaymentService paymentService = new PaymentService(defaultAccountProcessor, ""); validator .validate(paymentService) .stream() .forEach(violation -> System.out.println(violation.getMessage()));
Код более компактен и оптимизирован, но приведет к тому же результату проверки, что и более длинный блок ранее. Всякий раз, когда экземпляр PaymentService проверяется, AccountProcessor будет проверяться рекурсивно. Мы убиваем двух зайцев одним выстрелом!
С точки зрения клиентского кода, проверка, по-видимому, выполняется посредством одного вызова validate() , который является правильным способом сделать это, так как это аккуратно скрывает от разработчика сложности, связанные с сканированием всей структуры графов объектов. Внутренне, однако, метод фактически вызывается рекурсивно, в то время как валидатор пересекает дерево от корневого объекта до конечных объектов. Более того, использование @Valid не ограничивается только полями классов, так как его можно использовать и в коллекциях и массивах.
Это проверка графов объектов стала проще.
Резюме
Аннотация @Valid является ключевой особенностью Bean Validation, поскольку она позволяет проверять графы объектов с помощью одного вызова валидатора. Чтобы использовать его, все поля, которые должны быть рекурсивно проверены, должны быть аннотированы @Valid .
Еще одна интересная функция, которая выходит за рамки базовой проверки bean-компонентов — это проверка отдельных полей и значений с помощью validateProperty() и validateValue() . API, конечно, может предложить гораздо больше, поэтому обязательно ознакомьтесь с официальными документами и будьте в курсе последних новостей .
