1. 概述
在本教程中,我們將研究和比較不同方法以觸發和停止計劃中的 Spring Batch 作業,以滿足任何所需業務用例。
如果您需要有關 Spring Batch 和 Scheduler 的介紹,請參閲 Spring-Batch 和 Spring-Scheduler 文章。
2. 觸發計劃中的 Spring Batch 任務
首先,我們有一個名為 SpringBatchScheduler 的類,用於配置調度和批處理任務。 launchJob() 方法將被註冊為計劃任務。
為了以最直觀的方式觸發計劃中的 Spring Batch 任務,我們添加一個條件標誌,僅當標誌設置為 true 時才觸發任務。
private AtomicBoolean enabled = new AtomicBoolean(true);
private AtomicInteger batchRunCounter = new AtomicInteger(0);
@Autowired
private JobLauncher jobLauncher;
@Autowired
private JobRepository jobRepository;
@Autowired
private PlatformTransactionManager transactionManager;
@Scheduled(fixedRate = 2000)
public void launchJob() throws Exception {
Date date = new Date();
logger.debug("scheduler starts at " + date);
if (enabled.get()) {
JobExecution jobExecution = jobLauncher.run(job(jobRepository, transactionManager), new JobParametersBuilder().addDate("launchDate", date)
.toJobParameters());
batchRunCounter.incrementAndGet();
logger.debug("Batch job ends with status as " + jobExecution.getStatus());
}
logger.debug("scheduler ends ");
}變量 batchRunCounter 將在集成測試中使用,以驗證批次作業是否已停止。
3. 停止計劃中的 Spring Batch 任務
通過上述條件標誌,我們可以觸發計劃中的 Spring Batch 任務,即使任務處於活動狀態。
如果不需要恢復任務,我們可以實際停止計劃任務以節省資源。
在下一節中,我們將探討兩種選擇。
3.1. 使用調度器後處理器
由於我們使用 @Scheduled 註解來調度一個方法,因此調度器後處理器 ScheduledAnnotationBeanPostProcessor 應該首先被註冊。
我們可以顯式地調用 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());
}考慮到多個調度器,最好將每個調度器放在自己的類中,這樣我們就可以根據需要停止特定的調度器。
3.2. 取消計劃任務 未來任務
手動取消調度器的一種方式是取消其 未來任務。
以下是一個自定義任務調度器,用於捕獲 未來任務 映射:
@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;
}
}然後,我們迭代 Future 地圖,並取消對我們的批次作業調度器的 Future:
public void cancelFutureSchedulerTasks() {
scheduledTasks.forEach((k, v) -> {
if (k instanceof SpringBatchScheduler) {
v.cancel(false);
}
});
}在具有多個調度器任務的情況下,我們可以維護自定義調度器池中的 Future 映射,並根據調度器類取消相應的已調度 Future。
4. 結論
在本文中,我們嘗試了三種不同的方法來觸發或停止 Spring Batch 任務。
當需要重啓批處理任務時,使用條件標誌來管理任務運行狀態將是一種靈活的解決方案。 否則,我們可以遵循其他兩種選項來完全停止調度器。