【问题标题】:Spring boot CommandLineRunner Exception HandlingSpring Boot CommandLineRunner 异常处理
【发布时间】:2015-02-23 01:02:27
【问题描述】:

我们将 Spring-boot 用于命令行应用程序。我们使用 javax.validation 来验证命令行参数。

现在,如果我们遇到验证错误,我们如何打印友好的错误消息?我们不想显示堆栈跟踪。

当我们将 Spring-boot 作为 CommandLineRunner 运行时,是否可以使用 ExceptionHandler 机制?

谢谢 阿伦

来源

    @SpringBootApplication
    public class Deploy implements CommandLineRunner {
    private static final Logger LOGGER = LoggerFactory.getLogger(Deploy.class);

    @Autowired
    private DeployConfig config;

    @Autowired
    private DeployService deployService;

    /**
     * mvn clean package spring-boot:repackage
     * java -jar target/spring-boot-example-1.0.0-SNAPSHOT.jar --spring.profiles.active=qa --version=1.0
     *
     * @param strings arguments
     * @throws Exception
     */

    @Override
    public void run(String... strings) throws Exception {
        try {
            deployService.deploy(config);
        } catch (Exception ve) {
            LOGGER.error("Error : {}", ve.getMessage());
        }

        LOGGER.info("Created stack={}", config.getVersion());
    }

    public static void main(String... args) {
        LOGGER.info("Starting to run...");
        SpringApplication.run(Deploy.class, args);
        LOGGER.info("Completed the run...");
    }
}

配置

@Configuration
@EnableConfigurationProperties
@ConfigurationProperties
public class DeployConfig {

    @NotNull
    private String hello;

    @NotNull
    private String version;

    private String envKey;

    public String getHello() {
        return hello;
    }

    public void setHello(String hello) {
        this.hello = hello;
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public String getEnvKey() {
        return envKey;
    }

    public void setEnvKey(String envKey) {
        this.envKey = envKey;
    }

    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }
}

干净运行

mvn clean package spring-boot:repackage
java -jar target/spring-boot-example-1.0.0-SNAPSHOT.jar --spring.profiles.active=preprod,qa --version=1.0

验证检查

java -jar target/spring-boot-example-1.0.0-SNAPSHOT.jar --spring.profiles.active=preprod,qa

验证错误

2014-12-25 20:51:13,325 ERROR [main] [o.s.b.SpringApplication.run()] - Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'deploy': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.example.DeployConfig com.example.Deploy.config; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'deployConfig': Could not bind properties; nested exception is org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'target' on field 'version': rejected value [null]; codes [NotNull.target.version,NotNull.version,NotNull.java.lang.String,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [target.version,version]; arguments []; default message [version]]; default message [may not be null]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) ~[spring-beans-4.1.3.RELEASE.jar!/:4.1.3.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1202) ~[spring-beans-4.1.3.RELEASE.jar!/:4.1.3.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537) ~[spring-beans-4.1.3.RELEASE.jar!/:4.1.3.RELEASE]

完整来源

来源可以在GitHub找到

【问题讨论】:

    标签: java spring validation spring-boot


    【解决方案1】:

    不,没有用于处理来自 CommandLineRunners 的异常的内置异常处理机制 - 请参阅 org.springframework.boot.SpringApplication#runCommandLineRunners,将其包装在传统的 java 异常处理块周围会更容易

    【讨论】:

    • 不幸的是,在 run() 中的 try catch 块中包装语句没有帮助。无论如何,感谢您的回复。
    • 您能否展示一下您是如何使用 javax.validation 来验证您的论点的,可能正在研究这可能会引发更多想法。
    • 啊,我明白你的意思了。我觉得这是一种可接受的行为——从 Spring 的角度来看,如果启动属性验证失败,则不要启动应用程序,而是在堆栈跟踪中显示确切的验证失败。这不是 CommandLineRunners 特有的,但是,它应该是有/没有 CommandLineRunners 的相同行为。
    • 如果验证失败,应为开发人员提供一个选项来处理错误并显示优雅的错误消息。它类似于在 Web 服务中显示 HTTP 状态代码,例如 BadRequest 而不是堆栈跟踪。再次感谢。
    【解决方案2】:

    我遇到了(几乎)同样的问题,而且(令我惊讶的是)似乎从 Spring Boot 命令行程序向用户显示错误的最简洁的方法实际上是从 @987654322 到 System.exit(1) @,在记录您想要的任何错误消息之后。 Spring 上下文无论如何都会干净地关闭,但它不会触发上下文启动失败事件,因此您不会得到所有其他分散注意力的日志输出。

    您可能需要调整调用验证的方式,以便自己在 run() 中捕获验证错误并将其转换为 log + System.exit()

    【讨论】:

      猜你喜欢
      • 2017-07-15
      • 2023-03-28
      • 2016-09-29
      • 1970-01-01
      • 2022-11-22
      • 1970-01-01
      • 1970-01-01
      • 2017-02-02
      • 2017-09-14
      相关资源
      最近更新 更多