在没有控制器上下文的情况下侦听Spring Boot中的异常

时间:2019-07-03 14:35:19

标签: java spring spring-boot tomcat

自从我的项目开始以来,有时会在收到几条RabbitMQ消息后收到臭名昭著的CJCommunicationsException。由于对MySQL服务器几乎没有控制权,因此我需要退出/重新启动Spring Boot应用程序才能摆脱该异常。

由于上下文不涉及@Controller@RestController(我正在使用RabbitMQ侦听器),因此无法使用@ControllerAdvice@ExceptionHandler捕获异常。我正在尝试做类似的事情:

public static void main(String... args) throws Exception {
    while(true){
        try(ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args)) {
            CompletableFuture<Throwable> throwableFuture = new CompletableFuture<>();
            Thread.setDefaultUncaughtExceptionHandler(
                    (thread, throwable) -> throwableFuture.completeExceptionally(throwable));
            throwableFuture.get();
        } catch (Exception | VirtualMachineError t) {
            //log error
        }
    }
}

here所述,但是由于org.apache.catalina.core.StandardWrapperValve.invoke中的嵌入式Tomcat捕获了异常,因此this answer指出,这无济于事。

我该如何克服呢?

1 个答案:

答案 0 :(得分:0)

您似乎应该使用异常策略创建org.springframework.util.ErrorHandler类型的自定义bean(对于org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler,它是org.springframework.amqp.rabbit.listener.FatalExceptionStrategy),并将其传递到您的容器工厂。

如果没有当前配置,很难为您提供有效的配置,但是您的设置可能看起来像这样:

@Configuration
@EnableRabbit
public class RabbitMqConfiguration {

// ... other @Bean-s

@Bean
public SimpleRabbitListenerContainerFactory exportPartyListenerContainer() {
     SimpleRabbitListenerContainerFactory listenerContainer = new SimpleRabbitListenerContainerFactory();
     //... custom setup
     listenerContainer.setErrorHandler(errorHandler());
     return listenerContainer;
}

@Bean
public ErrorHandler errorHandler() {
   return new ConditionalRejectingErrorHandler(new YourCustomExceptionStrategy());
} 

} 

实施:

public class YourCustomExceptionStrategy extends DefaultExceptionStrategy {

    //.. some @Autowire-s if you need      

    @Override
    public boolean isFatal(Throwable t) {
         // ... your handling
    }
}

也许值得实现您的自定义org.springframework.util.ErrorHandler并将其传递给容器工厂。