Java Bean Validation
Bean Validation обеспечивает общий способ проверки достоверности с помощью объявления ограничений и метаданных для Java-приложений. Чтобы использовать его, вы аннотируете свойства модели предметной области декларативными ограничениями проверки достоверности, которые затем применяются средой выполнения. Существуют встроенные ограничения, но вы также можете определить свои собственные ограничения.
Рассмотрим следующий пример, в котором показана простая модель PersonForm с двумя свойствами:
class PersonForm( private val name: String, private val age: Int )
Bean Validation позволяет объявлять ограничения, как показано в следующем примере:
class PersonForm( @get:NotNull @get:Size(max=64) private val name: String, @get:Min(0) private val age: Int )
Затем валидатор Bean Validation проверяет экземпляры этого класса, основываясь на объявленных ограничениях. Общую информацию о данном API-интерфейсе см. в разделе «Bean Validation». Конкретные ограничения см. в документации по Hibernate Validator. Чтобы узнать, как настроить поставщика проверки достоверности бинов в качестве бина Spring, продолжайте читать.
Конфигурирование поставщика Bean Validation
Spring обеспечивает полную поддержку API-интерфейса Bean Validation, включая начальную загрузку поставщика Bean Validation в качестве бина Spring. Это позволяет внедрять javax.validation.ValidatorFactory или javax.validation.Validator всюду, где требуется проверка достоверности в приложении.
Вы можете использовать LocalValidatorFactoryBean для настройки валидатора по умолчанию в качестве бина Spring, как показано в следующем примере:
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; @Configuration public class AppConfig < @Bean public LocalValidatorFactoryBean validator() < return new LocalValidatorFactoryBean(); >>
Базовая конфигурация в предыдущем примере вызывает инициализацию проверки достоверности бинов, используя механизм загрузки по умолчанию. Поставщик Bean Validation, такой как Hibernate Validator, должен находиться в пути классов и определяться автоматически.
Внедрение валидатора
LocalValidatorFactoryBean реализует как javax.validation.ValidatorFactory и javax.validation.Validator , так и org.springframework.validation.Validator из Spring. Вы можете внедрить ссылку на любой из этих интерфейсов в бины, которые должны вызывать логику проверки достоверности.
Можно внедрить ссылку на javax.validation.Validator , если предпочтение отдается прямой работе с API-интерфейсом Bean Validation, как показано в следующем примере:
import javax.validation.Validator; @Service public class MyService
import javax.validation.Validator; @Service class MyService(@Autowired private val validator: Validator)
Можно внедрить ссылку на org.springframework.validation.Validator , если бин требует API-интерфейс Spring Validation, как показано в следующем примере:
import org.springframework.validation.Validator; @Service public class MyService
import org.springframework.validation.Validator @Service class MyService(@Autowired private val validator: Validator)
Настройка специальных ограничений
Каждое ограничение проверки достоверности бинов состоит из двух частей:
- Аннотации @Constraint , которая объявляет ограничение и его настраиваемые свойства.
- Реализации интерфейса javax.validation.ConstraintValidator , который реализует логику работы ограничения.
Чтобы связать объявление с реализацией, каждая аннотация @Constraint ссылается на соответствующий класс реализации ConstraintValidator . Во время выполнения ConstraintValidatorFactory создает экземпляр реализации, на которую ссылаются, если аннотация ограничения встречается в вашей модели предметной области.
По умолчанию LocalValidatorFactoryBean конфигурирует SpringConstraintValidatorFactory , которая использует Spring для создания экземпляров ConstraintValidator . Это позволяет специальным ConstraintValidators пользоваться внедрением зависимостей, как и любым другим бином Spring.
В следующем примере показано специальное объявление @Constraint , за которым следует связанная реализация ConstraintValidator , использующая Spring для внедрения зависимостей:
@Target() @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy=MyConstraintValidator.class) public @interface MyConstraint
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.FIELD) @Retention(AnnotationRetention.RUNTIME) @Constraint(validatedBy = MyConstraintValidator::class) annotation class MyConstraint
import javax.validation.ConstraintValidator; public class MyConstraintValidator implements ConstraintValidator < @Autowired; private Foo aDependency; // . >
import javax.validation.ConstraintValidator class MyConstraintValidator(private val aDependency: Foo) : ConstraintValidator < // . >
Как следует из предыдущего примера, реализация ConstraintValidator может иметь свои зависимости, помеченные аннотацией @Autowired , как и любой другой бин Spring.
Проверка достоверности методов, управляемая Spring
Вы можете внедрить функцию проверки методов, поддерживаемую Bean Validation 1.1 (и, в качестве специального расширения, также Hibernate Validator 4.3), в контекст Spring через определение бина MethodValidationPostProcessor :
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; @Configuration public class AppConfig < @Bean public MethodValidationPostProcessor validationPostProcessor() < return new MethodValidationPostProcessor(); >>
Чтобы осуществлять проверку достоверности методов, управляемую Spring, все целевые классы должны быть аннотированы аннотацией @Validated из Spring, в которой по желанию можно также объявить группы поверки достоверности для использования. См. MethodValidationPostProcessor для получения более подробной информации о настройке с использованием поставщиков Hibernate Validator и Bean Validation 1.1.
Проверка достоверности методов использует АОП-прокси в обход целевых классов, либо динамические прокси из JDK для методов на интерфейсах, либо прокси из CGLIB. Существуют определенные ограничения при использовании прокси. Кроме того, помните, что для проксированных классов всегда нужно использовать методы и акцессоры; прямой доступ к полям работать не будет.
Дополнительные параметры конфигурации
Конфигурация LocalValidatorFactoryBean по умолчанию достаточна для большинства случаев. Существует ряд опций конфигурации для различных конструкций Bean Validation, от интерполяции сообщений до разрешения обхода. См. javadoc по LocalValidatorFactoryBean для получения дополнительной информации об этих опциях.
Конфигурирование DataBinder
Начиная со Spring 3, вы можете конфигурировать экземпляр DataBinder с помощью Validator . После конфигурирования можно вызывать Validator , обратившись к binder.validate() . Любые Errors проверки достоверности автоматически добавляются к привязке BindingResult .
В следующем примере показано, как программно использовать DataBinder для вызова логики проверки достоверности после привязывания к целевому объекту:
Foo target = new Foo(); DataBinder binder = new DataBinder(target); binder.setValidator(new FooValidator()); // привязываем к целевому объекту binder.bind(propertyValues); // валидируем целевой объект binder.validate(); // получаем результат BindingResult, включающий все ошибки валидации BindingResult results = binder.getBindingResult();
val target = Foo() val binder = DataBinder(target) binder.validator = FooValidator() // привязываем к целевому объекту binder.bind(propertyValues) // валидируем целевой объект binder.validate() // получаем результат BindingResult, включающий все ошибки валидации val results = binder.bindingResult
Также можно настроить DataBinder с использованием нескольких экземпляров Validator через dataBinder.addValidators и dataBinder.replaceValidators . Это имеет смысл при комбинировании глобально сконфигурированной валидации бинов с использованием Validator из Spring, настроенного локально для экземпляра DataBinder.