ParameterMessageInterpolator指南

2023/05/12

1. 概述

Java JSR 380 的特性之一是允许在使用参数插入验证消息时使用表达式。

当我们使用 Hibernate Validator 时,有一个要求我们需要将JavaJSR 341 的统一实现之一作为依赖添加到我们的项目中。JSR 341 也称为表达式语言 API。

但是,如果我们不需要根据我们的用例支持解析表达式,那么添加额外的库可能会很麻烦。

在这个简短的教程中,我们将了解如何在 Hibernate Validator中配置ParameterMessageInterpolator 。

2. 消息插值器

除了验证Javabean 的基础知识之外,Bean Validation API 的MessageInterpolator是一种抽象,它为我们提供了一种执行简单插值的方法,而无需解析表达式的麻烦。

此外,Hibernate Validator 提供了一个基于非表达式的ParameterMessageInterpolator,因此,我们不需要任何额外的库来配置它。

3. 设置自定义消息插值器

要删除表达式语言依赖性,我们可以使用自定义消息插值器并配置不支持表达式的 Hibernate Validator。

让我们展示一些设置自定义消息插值器的便捷方法。在我们的案例中,我们将使用内置的ParameterMessageInterpolator。

3.1. 配置ValidatorFactory

设置自定义消息插值器的一种方法是在引导时配置ValidatorFactory 。

因此,我们可以使用ParameterMessageInterpolator构建一个ValidatorFactory实例:

ValidatorFactory validatorFactory = Validation.byDefaultProvider()
  .configure()
  .messageInterpolator(new ParameterMessageInterpolator())
  .buildValidatorFactory();

3.2. 配置验证器

同样,我们可以在初始化Validator实例时设置ParameterMessageInterpolator :

Validator validator = validatorFactory.usingContext()
  .messageInterpolator(new ParameterMessageInterpolator())
  .getValidator();

4. 执行验证

要查看ParameterMessageInterpolator的工作原理,我们需要一个带有一些 JSR 380 注解的示例Javabean。

4.1. 示例JavaBean

让我们定义我们的示例Javabean 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. 测试消息参数

当然,要执行我们的验证,我们应该使用从我们之前配置的ValidatorFactory访问的Validator实例。

所以,我们需要访问我们的验证器:

Validator validator = validatorFactory.getValidator();

之后,我们可以为name字段编写我们的测试方法:

@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

接下来,让我们为年龄字段编写一个类似的测试:

@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上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章