SpringBoot验证一个bean方法的参数和return

SpringBoot validation of a bean method parameters and return

我无法正确进行方法级别验证。或者我不明白它是如何工作的。

我的申请 class 如下。很简单的。它包含 MethodValidationPostProcessor bean 定义。它还运行 Greeter 服务。

@SpringBootApplication
public class App implements CommandLineRunner {
    private final Greeter greeter;

    public App(Greeter greeter) {
        this.greeter = greeter;
    }

    public static void main(String[] args) {
        new SpringApplicationBuilder().main(App.class).sources(App.class).web(false).run(args).close();
    }

    @Bean
    public org.springframework.validation.beanvalidation.MethodValidationPostProcessor methodValidationPostProcessor() {
        return new MethodValidationPostProcessor();
    }

    @Override
    public void run(String... args) throws Exception {
        final Input input = new Input();
        input.setName("j");
        final String messageFromInput = greeter.getMessageFromInput(input);

        final String messageFromString = greeter.getMessageFromString("j");
    }
}

下面的迎宾服务。在这里我确实希望验证输入和输出。

@Service
@Validated
public class Greeter {
    String getMessageFromInput(@Valid @NotNull Input name) {
        return "[From Input] Greetings! Oh mighty " + name + "!";
    }

    String getMessageFromString(@Size(min = 4) String name) {
        return "[From String] Greetings! Oh mighty " + name + "!";
    }
}

输入DTO也很简单

public class Input {
    @NotEmpty
    @Size(min = 3)
    private String name;

    // Getters, setters and toString ommited.
}

由于这两种情况下的名称(直接字符串和 DTO)都只有一个字母,我希望此设置会引发异常。不幸的是,没有任何反应,应用程序成功完成。它适用于控制器的方法。但我希望它能与任何 bean 的方法一起使用。

您正在将 Greeter bean 作为构造函数参数注入 class 并用 @SpringBootApplication 注释,这是一个 @Configuration class。为了满足这种依赖性,Greeter 是在 ApplicationContext 的启动过程中很早就创建的,因此将删除它作为代理创建的候选者。

与其将其作为构造函数参数注入,不如将您的 CommandLineRunner 逻辑移至 @Bean 注释方法,并简单地将 Greeter 作为依赖项注入。这将延迟 bean 的创建,并因此使其可用于代理。

@Bean
public CommandLineRunner runner(Greeter greeter) {
    return new CommandLineRunner() {

        @Override
        public void run(String... args) throws Exception {
            final Input input = new Input();
            input.setName("j");
            final String messageFromInput = greeter.getMessageFromInput(input);

            final String messageFromString = greeter.getMessageFromString("j");
        }
    };
}

另一件事是,由于代理的性质,Greeter 的方法应该是 public