«1. Обзор
Одной из особенностей Java JSR 380 является разрешение выражений при интерполяции сообщений проверки с параметрами.
Когда мы используем Hibernate Validator, нам необходимо добавить одну из унифицированных реализаций Java JSR 341 в качестве зависимости к нашему проекту. JSR 341 также называется API языка выражений.
Однако добавление дополнительной библиотеки может быть обременительным, если нам не нужно поддерживать синтаксический анализ выражений в соответствии с нашим вариантом использования.
В этом коротком руководстве мы рассмотрим, как настроить ParameterMessageInterpolator в Hibernate Validator.
2. Интерполяторы сообщений
Помимо основ проверки Java-бина, MessageInterpolator API Bean Validation представляет собой абстракцию, которая дает нам способ выполнять простые интерполяции без хлопот синтаксического анализа выражений.
Кроме того, Hibernate Validator предлагает ParameterMessageInterpolator, не основанный на выражениях, и поэтому нам не нужны дополнительные библиотеки для его настройки.
3. Настройка пользовательских интерполяторов сообщений
Чтобы удалить зависимость от языка выражений, мы можем использовать пользовательские интерполяторы сообщений и настроить Hibernate Validator без поддержки выражений.
Давайте покажем несколько удобных способов настройки пользовательских интерполяторов сообщений. В нашем случае мы будем использовать встроенный ParameterMessageInterpolator.
3.1. Настройка ValidatorFactory
Одним из способов настройки пользовательского интерполятора сообщений является настройка ValidatorFactory при начальной загрузке.
Таким образом, мы можем построить экземпляр ValidatorFactory с ParameterMessageInterpolator:
ValidatorFactory validatorFactory = Validation.byDefaultProvider()
.configure()
.messageInterpolator(new ParameterMessageInterpolator())
.buildValidatorFactory();
3.2. Настройка Validator
Точно так же мы можем установить ParameterMessageInterpolator при инициализации экземпляра Validator:
Validator validator = validatorFactory.usingContext()
.messageInterpolator(new ParameterMessageInterpolator())
.getValidator();
4. Выполнение проверок
Чтобы увидеть, как работает ParameterMessageInterpolator, нам нужен образец Java-бина с некоторыми аннотациями JSR 380 на нем. .
4.1. Пример Java-бина
Давайте определим наш образец Java-бина Person:
public class Person {
@Size(min = 10, max = 100, message = "Name should be between {min} and {max} characters")
private String name;
@Min(value = 18, message = "Age should not be less than {value}")
private int age;
@Email(message = "Email address should be in a correct format: ${validatedValue}")
private String email;
// standard getters and setters
}
4.2. Тестирование параметров сообщения
Конечно, для выполнения наших проверок мы должны использовать экземпляр Validator, доступ к которому осуществляется из ValidatorFactory, который мы уже настроили ранее.
Итак, нам нужно получить доступ к нашему валидатору:
Validator validator = validatorFactory.getValidator();
После этого мы можем написать наш тестовый метод для поля имени:
@Test
public void givenNameLengthLessThanMin_whenValidate_thenValidationFails() {
Person person = new Person();
person.setName("John Doe");
person.setAge(18);
Set<ConstraintViolation<Person>> violations = validator.validate(person);
assertEquals(1, violations.size());
ConstraintViolation<Person> violation = violations.iterator().next();
assertEquals("Name should be between 10 and 100 characters", violation.getMessage());
}
Сообщение проверки интерполируется с переменными {min} и {max} правильно:
Name should be between 10 and 100 characters
Далее, давайте напишем аналогичный тест для поля age:
@Test
public void givenAgeIsLessThanMin_whenValidate_thenValidationFails() {
Person person = new Person();
person.setName("John Stephaner Doe");
person.setAge(16);
Set<ConstraintViolation<Person>> violations = validator.validate(person);
assertEquals(1, violations.size());
ConstraintViolation<Person> violation = violations.iterator().next();
assertEquals("Age should not be less than 18", violation.getMessage());
}
Точно так же сообщение проверки корректно интерполируется с переменной {value}, как мы и ожидали:
Age should not be less than 18
4.3. Тестирование выражений
Чтобы увидеть, как ParameterMessageInterpolator ведет себя с выражениями, давайте напишем еще один тест для поля электронной почты, который включает простое выражение ${validatedValue}:
@Test
public void givenEmailIsMalformed_whenValidate_thenValidationFails() {
Person person = new Person();
person.setName("John Stephaner Doe");
person.setAge(18);
person.setEmail("johndoe.dev");
Set<ConstraintViolation<Person>> violations = validator.validate(person);
assertEquals(1, violations.size());
ConstraintViolation<Person> violation = violations.iterator().next();
assertEquals("Email address should be in a correct format: ${validatedValue}", violation.getMessage());
}
На этот раз выражение ${validatedValue} не интерполируется.
ParameterMessageInterpolator поддерживает только интерполяцию параметров, а не синтаксический анализ выражений, использующих нотацию $. Вместо этого он просто возвращает их без интерполяции.
5. Заключение
В этой статье мы узнали, для чего нужен ParameterMessageInterpolator и как его настроить в Hibernate Validator.
Как всегда, все примеры из этого руководства доступны на GitHub.