当前位置: 首页 > 知识库问答 >
问题:

Spring中@Scheduled tasks(Boot)的通用异常处理程序(Java配置)

吕俊美
2023-03-14

在我的Spring Boot(1.4.2版)应用程序中,我有很多计划的任务,希望使用一个处理程序捕获所有异常,就像使用@ExceptionHandler注释的普通控制器一样。由于线程问题,这种方法不适用于使用@Scheduled annotation定义的任务:

@Component
public class UpdateJob {
    @Transactional
    @Scheduled(cron = "0 1 0 * * *")
    public void runUpdateUsers() {
        userService.updateUsers();
    }

    @ExceptionHandler
    public void handle(Exception e) {
       // some more logic here
       logger.error(e.getMessage());
    }

 }

@ExceptionHandler不适用于@计划方法(事实证明它并不意味着)。相反,Spring Boot使用它自己的LoggingErrorHandler:

2016-12-08 15:49:20.016 ERROR 23119 --- [pool-7-thread-1] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task.

我能以某种方式为计划任务替换或提供默认的异常处理程序吗?或者切换到传播错误处理程序有意义吗?据我所知,它会进一步传播错误。有没有其他方法只使用Java配置(没有XML)来实现这个目标?

这并不是这个问题的重复,因为它明确要求基于Java配置而不是XML的解决方案(因此,在没有任何XML配置的情况下将其合并到Spring Boot项目中是不错的)。

还有一些答案演示了如何从头开始配置TaskScheduler。例如,这个答案要求您还定义池大小、最大池大小、队列容量。这里有一个解决方案,它也需要非常广泛的配置。文档显示了如何配置其他方面,但没有显示如何指定错误处理。但是Java配置需要花费多少精力才能最大限度地保持Spring Boot缺省值(线程池、执行器配置等)。

共有3个答案

支智志
2023-03-14

您使用PropagatingErrorHandler的方法是正确的,但您稍微误解了目的。它会导致异常在堆栈的更上层继续,导致计划的任务在将来不会运行。此外,它是TaskUtils的私有文件,因此您无法访问它。

您需要实现自己的错误处理程序,但只能有一个处理程序。至少,您需要记录异常,因为Spring不再为您记录它。

假设您没有自己的自定义TaskSchedulerbean,要在Spring Boot中创建自己的ErrorHandler,请在@Configance类中实现org.springframework.boot.task.TaskSchedulerCustomzer

@Override
public void customize(ThreadPoolTaskScheduler taskScheduler) {
    taskScheduler.setErrorHandler(new CustomErrorHandler());
}

private static class CustomErrorHandler implements ErrorHandler {
    private static final Logger logger = LoggerFactory.getLogger(CustomErrorHandler.class);

    @Override
    public void handleError(Throwable t) {
        logger.error("Scheduled task threw an exception: {}", t.getMessage(), t);
    }
}

因为ErrorHandler是一个@keytionalInterface,您可以这样做:

taskScheduler.setErrorHandler(t -> { /* Handle exception here */});

(这是基于Spring Boot 2.1.8)

甄华清
2023-03-14

如注释中所述,@ExceptionHandler适用于Spring MVC控制器。

如果您想为单个调度器提供异常处理逻辑,最简单、最可维护的方法是将其包装到try-catch块中,并在其中处理错误。

如果您想对不同的调度器应用相同的错误处理程序,请遵循@M.Deinum的建议。

年凯康
2023-03-14

下面是一个设置自定义错误处理程序(Spring 2.0.2)的示例:

@Bean
public TaskScheduler taskScheduler() {
    ConcurrentTaskScheduler scheduler = new ConcurrentTaskScheduler();
    scheduler.setErrorHandler(throwable -> { /* custom handler */ });
    return scheduler;
}
 类似资料:
  • 我是一个有Spring和Spring靴的新手。在创建了一个简单的REST API来对用户执行CRUD操作之后,我还创建了自定义的异常处理程序来捕获应用程序中发生的任何异常。这是我写的代码 controller类 使用@ControllerAdvice注释的异常处理程序类 但是,当发生任何异常时,应用程序将被重定向到/error page,而不是由异常处理程序类处理。谁能给出正确的方法来做这件事。

  • 我试图用spring Boot开发一个应用程序。我被困在管理应用程序的异常/错误上。到目前为止,我有服务层和控制器,我已经创建了特定于服务类的异常。对于。(如)异常类是。服务抛出各自的。我被困在如何处理控制器中的异常/错误,如果那里有异常?特别针对api方法调用的格式不正确的输入。我正在读取控制器的输入。我应该把它包括在服务中吗? 所有服务异常都以500个内部应用程序错误的形式返回HTTP代码。我

  • 我的RestController类: 我的ExceptionHandler: 例外响应:

  • 我正在用spring boot 2开发Rest API,我试图创建一个ExceptionHandler,但它似乎不起作用。 我有以下@GetMapping方法: customerRepository是扩展CrudRepository接口的接口。 customerNotFoundException的@ExceptionHandler如下所示: 我还对ResponseEntityExceptionHa

  • 我正在用Spring Boot开发一个rest应用程序。此应用程序有一个自定义筛选器,只允许在某些请求下访问。如果用户需要特定的资源,筛选器将抛出异常。如何在全局级别处理此筛选器中生成的所有异常? 我尝试了注释,但不起作用。

  • 1. 前言 程序中出现异常是普遍现象, Java 程序员想必早已习惯,根据控制台输出的异常信息,分析异常产生的原因,然后进行针对性处理的过程。 Spring Boot 项目中,数据持久层、服务层到控制器层都可能抛出异常。如果我们在各层都进行异常处理,程序代码会显得支离破碎,难以理解。 实际上,异常可以从内层向外层不断抛出,最后在控制器层进行统一处理。 Spring Boot 提供了全局性的异常处理