为什么 Spring 没有参与 JSR-303 bean 验证?

问题描述 投票:0回答:1

想知道为什么 Spring 没有启动 Hibernate Bean 验证。根据文档 HERE,它需要上下文中的

MethodValidationPostProcessor
以及使用
@Validated
注释来注释目标 Spring bean。我已经完成了这两个要求,但它仍然不起作用。

我预计在调用

backgroundCheck
方法时会出现异常,因为该人的名字是
null
并且年龄小于 18 岁。但是,出于某种原因,
Person
对象未经过验证,并且方法无异常地完成。

这是我的设置:

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;

@SpringBootApplication
public class Application implements CommandLineRunner {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public LocalValidatorFactoryBean validator() {
        return new LocalValidatorFactoryBean();
    }

    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
        methodValidationPostProcessor.setValidator(validator());
        return methodValidationPostProcessor;
    }

    @Override
    public void run(String... args) {

        PersonService personService = new PersonService();

        try {
            personService.backgroundCheck(new Person(null, 4));
        } catch (Exception e) {
            System.out.println("<<< EXCEPTION >>>");
            return;
        }

        System.out.println("<<< NO VALIDATIONS THROWN >>>");
    }
}
import jakarta.validation.Valid;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

@Validated
@Service
public class PersonService {

    public void backgroundCheck(@Valid Person person) {
        System.out.printf("Running background check for %s%n", person.name());
    }
}
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;

public record Person(
        @NotBlank(message = "Name must not be blank")
        String name,

        @Min(value = 18, message = "Age should not be less than 18")
        int age) {
}
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.3</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
    <java.version>21</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

知道我错过了什么吗?

spring bean-validation hibernate-validator spring-framework-beans jakarta-validation
1个回答
0
投票
  • org.springframework.validation.annotation.Validated
    @Validated 必须是 Spring Bean 才能执行验证。
    • 这是一个基于AOP的方法,拦截并处理方法请求。
    • 因此,可以在任何 Spring bean 上执行验证,无论控制器、服务或存储库等层次结构如何。
  • 问题在于代码只是创建并使用了 PersonService 实例。
    • 它不是 Spring Bean,因为它是一个没有注入依赖的实例。
    • 所以@Validated也没有效果。
  • 在下面的代码中,我将更改代码以使其按预期工作。
@SpringBootApplication
public class Application implements CommandLineRunner {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
    
    @Bean
    public LocalValidatorFactoryBean validator() {
        return new LocalValidatorFactoryBean();
    }

    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
        methodValidationPostProcessor.setValidator(validator());
        return methodValidationPostProcessor;
    }

    @Bean
    public PersonService personService() {
        return new PersonService();
    }

    @Override
    public void run(String... args) {

        try {
            personService().backgroundCheck(new Person(null, 4));
        } catch (ConstraintViolationException e) {
            System.out.println("<<< EXCEPTION >>>");
            return;
        }
        System.out.println("<<< NO VALIDATIONS THROWN >>>");
    }
}

结果。

2024-03-20T13:09:23.676+09:00  INFO 4384 --- [           main]
<<< EXCEPTION >>>
  • ConstraintViolationException 正常发生。

希望对您有所帮助:)谢谢。

© www.soinside.com 2019 - 2024. All rights reserved.