具有Java配置的Spring中@Scheduled tasks(启动)的通用异常处理程序
我在Spring Boot(1.4.2版)应用程序中有很多计划的任务,我希望使用一个处理程序捕获所有异常,这对于带注释的普通控制器来说是可能的。由于线程问题,此方法不适用于使用@Scheduled annotation定义的任务:具有Java配置的Spring中@Scheduled tasks(启动)的通用异常处理程序,spring,spring-boot,scheduled-tasks,spring-scheduled,Spring,Spring Boot,Scheduled Tasks,Spring Scheduled,我在Spring Boot(1.4.2版)应用程序中有很多计划的任务,我希望使用一个处理程序捕获所有异常,这对于带注释的普通控制器来说是可能的。由于线程问题,此方法不适用于使用@Scheduled annotation定义的任务: @Component public class UpdateJob { @Transactional @Scheduled(cron = "0 1 0 * * *") public void runUpdateUsers() {
@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不适用于@Scheduled方法(事实证明它并不适用)。相反,Spring Boot使用它自己的:
我是否可以替换或提供计划任务的默认异常处理程序?或者切换到我所理解的会进一步传播错误的位置是否有意义(并且是否可能)?是否有其他方法可以仅使用Java配置(无XML)来实现此目标
这不是的重复,因为它明确要求一个基于Java配置的解决方案,而不是基于XML的解决方案(因此在没有任何XML配置的情况下并入Spring Boot项目是不错的)
还有一些答案演示了如何从头配置TaskScheduler。例如,这要求您还定义池大小、最大池大小和队列容量。是一个也需要非常广泛配置的解决方案。显示如何配置其他方面,但不显示如何指定错误处理。但是使用Java配置所需的最小工作量是多少?这样我就可以最大限度地保持Spring启动的默认值(线程池、执行器配置等) 如评论中所述,
@ExceptionHandler
用于Spring MVC控制器
若您想为单个调度器提供异常处理逻辑,最简单和最可维护的方法是将其包装到try-catch块中,并在其中处理错误
如果您想对不同的调度程序应用相同的错误处理程序,请遵循@M.Deinum的建议 下面是一个设置自定义错误处理程序(Spring 2.0.2)的示例:
我认为使用AOP可以解决您的问题 步骤
@Aspect
@Component
public class UpdateJobAOP {
@Pointcut("execution(* com.foo.bar.UpdateJob.*(..))")
public void all() {}
@AfterThrowing(pointcut="all()", throwing="ex")
public void afterThrowing(Exception ex) {
// Do what you want
ex.printStackTrace();
}
}
您使用
PropagatingErrorHandler
的方法是正确的,但您稍微误解了目的。它会导致异常在堆栈的更上层继续,从而导致计划的任务将来不会运行。此外,它是TaskUtils
的私有文件,因此您无法访问它
您需要实现自己的错误处理程序
,但只能有一个处理程序。至少您需要记录异常,因为您不再需要Spring为您记录它
假设您没有自己的自定义TaskScheduler
bean,要在Spring Boot中创建自己的ErrorHandler
,请在@Configuration类中实现org.springframework.Boot.task.TaskSchedulerCustomizer
@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
是一个@功能界面
,所以您可以执行以下操作:
taskScheduler.setErrorHandler(t -> { /* Handle exception here */});
(这基于Spring Boot 2.1.8)异常处理程序用于Web处理程序方法。请提供理由,是否有任何原因使您不能将异常处理程序用于任何方法或类?术语“web处理程序”适用于ASP.net,可能与ASP.net有所不同?它是webmvc基础设施的一部分。它将与
@Controller
一起使用。阅读您链接的javadoc。Spring Boot没有配置任何东西。在配置TaskScheduler
时,设置要在其上使用的ErrorHandler
。@M.Deinum,您能举个例子吗?是否可以与“@Scheduled”批注一起实现?谢谢!这个特定的@ExceptionHandler似乎并不是为此目的而设计的。我只想提供错误处理程序,但不想更改其他执行器属性。我明白,除非我也愿意管理计划程序本身,否则无法为计划任务(作为@Bean?)提供异常处理?请参阅下面关于TaskSchedulerCustomizer
的评论,似乎是一个干净的解决方案。您可以通过在@配置中实现TaskSchedulerCustomizer
并仅设置错误处理程序来定制Spring Boot的默认TaskScheduler
。这使您可以保持Spring Boot的默认配置。
@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);
}
}
taskScheduler.setErrorHandler(t -> { /* Handle exception here */});