【问题标题】:Java Bean method constraint validation with Spring does not work for constructors使用 Spring 的 Java Bean 方法约束验证不适用于构造函数
【发布时间】:2018-07-05 05:59:38
【问题描述】:

我目前正在尝试使用Hibernate Validator 实现一些方法约束验证。 我已经定义了

  1. 方法的参数约束
  2. 方法的返回值约束
  3. 构造函数的参数约束
  4. 构造函数的返回值约束

Hibernate Validator documentation 中所述,使用ExecutableValidator 接口的手动验证非常适用于1.-4。

与 Spring 的集成基本上可以使用 @Validated 注释 bean。 当我尝试使用 @Validated 在 Spring 容器中验证我的约束时,只有 1. 和 2.,即e.验证方法、工作,但不适用于构造函数(3. 和 4.)。

任何想法,出了什么问题?

我创建了一个最小的工作示例: 第一个测试用例成功,即使它应该抛出异常 第二个测试用例失败,因为在调用setter的那一刻抛出了ConstraintViolationException(实际上也应该在前一行抛出异常)。

我的客户 bean,应该被验证(注意:setFirstName() 的参数有一个 @NotNull 注释):

@Validated
public class Customer {

  private String firstName;

  private String lastName;

  public Customer(@NotNull String firstName, @NotNull String lastName) {
      this.firstName = firstName;
      this.lastName = lastName;
  }

  public String getFirstName() {
      return firstName;
  }

  public void setFirstName(@NotNull String firstName) {
      this.firstName = firstName;
  }

  public String getLastName() {
      return lastName;
  }

  public void setLastName(String lastName) {
      this.lastName = lastName;
  }
}

所属配置:

@Configuration
@ComponentScan({ "com.example.demo" })
public class MethodValidationConfig {

  @Bean
  public MethodValidationPostProcessor methodValidationPostProcessor() {
      return new MethodValidationPostProcessor();
  }

  @Bean("customer")
  @Scope(BeanDefinition.SCOPE_PROTOTYPE)
  public Customer customer(String firstName, String lastName) {

      Customer customer = new Customer(firstName, lastName);
      return customer;
  }
}

然后是两个测试用例。 如前所述,第一个不会抛出异常,即使它应该。 第二个抛出异常,但在调用 setter 的那一刻,而不是之前。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { MethodValidationConfig.class }, loader = 
AnnotationConfigContextLoader.class)
public class DemoApplicationTests {

  @Autowired
  private ApplicationContext applicationContext;

  @Test
  public void callConstructorWithInvalidParameter(){

      Customer c = (Customer) applicationContext.getBean("customer", null, null);
  }

  @Test
  public void callSetterWithInvalidParameter(){

      Customer c = (Customer) applicationContext.getBean("customer", "John", "Doe");
      c.setFirstName(null);
  }

}

最后是我的 pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
    http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.0.7.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator-annotation-processor</artifactId>
            <version>6.0.7.Final</version>
        </dependency>
        <dependency>
            <groupId>javax.el</groupId>
            <artifactId>javax.el-api</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>javax.el</artifactId>
            <version>2.2.6</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.2.RELEASE</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
    <packaging>jar</packaging>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
</project>

【问题讨论】:

    标签: java spring hibernate-validator spring-validator


    【解决方案1】:

    Spring 验证使用 AOP。默认情况下使用 Spring AOP。 Spring AOP 是代理托管组件(又名 bean)的运行时 AOP 实现。

    出于同样的原因,构造函数无法使用 Spring AOP 进行建议,因此验证将不起作用。

    对于更复杂的 AOP,请考虑 Aspectj。或者只是尝试将验证移至方法执行。 (spring AOP 中唯一支持的连接点)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-08
      • 2019-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-26
      相关资源
      最近更新 更多