1. Overview
1.概述
In this tutorial, we’ll investigate and compare different ways to trigger and stop a scheduled Spring Batch job for any required business cases.
在本教程中,我们将研究和比较不同的方式,以触发和停止预定的Spring Batch作业,以满足任何所需的业务情况。
If you need introductions about Spring Batch and Scheduler, please refer to Spring-Batch and Spring-Scheduler articles.
如果您需要关于Spring Batch和Scheduler的介绍,请参考Spring-Batch和Spring-Scheduler文章。
2. Trigger a Scheduled Spring Batch Job
2.触发一个预定的Spring批处理作业
Firstly, we have a class SpringBatchScheduler to configure scheduling and batch job. A method launchJob() will be registered as a scheduled task.
首先,我们有一个SpringBatchScheduler类来配置调度和批量作业。一个方法launchJob()将被注册为一个计划任务。
Furtherly, to trigger the scheduled Spring Batch job in the most intuitive way, let’s add a conditional flag to fire the job only when the flag is set to true:
此外,为了以最直观的方式触发预定的Spring Batch作业,让我们添加一个条件标志,只有当该标志被设置为 “true “时,才能启动该作业。
private AtomicBoolean enabled = new AtomicBoolean(true);
private AtomicInteger batchRunCounter = new AtomicInteger(0);
@Scheduled(fixedRate = 2000)
public void launchJob() throws Exception {
if (enabled.get()) {
Date date = new Date();
JobExecution jobExecution = jobLauncher()
.run(job(), new JobParametersBuilder()
.addDate("launchDate", date)
.toJobParameters());
batchRunCounter.incrementAndGet();
}
}
// stop, start functions (changing the flag of enabled)
The variable batchRunCounter will be used in integration tests to verify if the batch job has been stopped.
变量batchRunCounter将被用于集成测试,以验证批处理作业是否已经停止。
3. Stop a Scheduled Spring Batch Job
3.停止预定的Spring批处理作业
With above conditional flag, we’re able to trigger the scheduled Spring Batch job with the scheduled task alive.
有了上述条件标志,我们就能在预定任务活着的情况下触发预定的Spring Batch作业。
If we don’t need to resume the job, then we can actually stop the scheduled task to save resources.
如果我们不需要恢复工作,那么我们实际上可以停止计划任务以节省资源。
Let’s take a look at two options in the next two subsections.
让我们在接下来的两个小节中看一下两个选项。
3.1. Using Scheduler Post Processor
3.1.使用调度器后处理器
Since we’re scheduling a method by using @Scheduled annotation, a bean post processor ScheduledAnnotationBeanPostProcessor would’ve been registered first.
因为我们通过使用@Scheduled 注释来调度一个方法,一个bean post processor ScheduledAnnotationBeanPostProcessor将被首先注册。
We can explicitly call the postProcessBeforeDestruction() to destroy the given scheduled bean:
我们可以明确地调用postProcessBeforeDestruction()来销毁给定的预定Bean。
@Test
public void stopJobSchedulerWhenSchedulerDestroyed() throws Exception {
ScheduledAnnotationBeanPostProcessor bean = context
.getBean(ScheduledAnnotationBeanPostProcessor.class);
SpringBatchScheduler schedulerBean = context
.getBean(SpringBatchScheduler.class);
await().untilAsserted(() -> Assert.assertEquals(
2,
schedulerBean.getBatchRunCounter().get()));
bean.postProcessBeforeDestruction(
schedulerBean, "SpringBatchScheduler");
await().atLeast(3, SECONDS);
Assert.assertEquals(
2,
schedulerBean.getBatchRunCounter().get());
}
Considering multiple schedulers, it’s better to keep one scheduler in its own class, so we can stop specific scheduler as needed.
考虑到多个调度器,最好把一个调度器放在自己的类中,这样我们可以根据需要停止特定的调度器。
3.2. Canceling the Scheduled Future
3.2.取消预定的未来
Another way to stop the scheduler would be manually canceling its Future.
另一种停止调度器的方法是手动取消其Future。
Here’s a custom task scheduler for capturing Future map:
这里有一个用于捕捉Future地图的自定义任务调度器。
@Bean
public TaskScheduler poolScheduler() {
return new CustomTaskScheduler();
}
private class CustomTaskScheduler
extends ThreadPoolTaskScheduler {
//
@Override
public ScheduledFuture<?> scheduleAtFixedRate(
Runnable task, long period) {
ScheduledFuture<?> future = super
.scheduleAtFixedRate(task, period);
ScheduledMethodRunnable runnable = (ScheduledMethodRunnable) task;
scheduledTasks.put(runnable.getTarget(), future);
return future;
}
}
Then we iterate the Future map and cancel the Future for our batch job scheduler:
然后我们遍历Future映射,并取消我们的批处理作业调度器的Future。
public void cancelFutureSchedulerTasks() {
scheduledTasks.forEach((k, v) -> {
if (k instanceof SpringBatchScheduler) {
v.cancel(false);
}
});
}
In the cases with multiple scheduler tasks, then we can maintain the Future map inside of the custom scheduler pool but cancel the corresponding scheduled Future based on scheduler class.
在有多个调度器任务的情况下,我们可以在自定义调度器池内维护Future映射,但根据调度器类别取消相应的计划Future。
4. Conclusion
4.总结
In this quick article, we tried three different ways to trigger or stop a scheduled Spring Batch job.
在这篇快速文章中,我们尝试了三种不同的方式来触发或停止预定的Spring Batch作业。
When we need to restart the batch job, using a conditional flag to manage job running would be a flexible solution. Otherwise, we can follow the other two options to stop the scheduler completely.
当我们需要重新启动批处理作业时,使用一个条件标志来管理作业的运行将是一个灵活的解决方案。否则,我们可以按照其他两个选项来完全停止调度器。
As usual, all the code samples used in the article are available over on GitHub.
像往常一样,文章中使用的所有代码样本都可以在GitHub上找到。