Spring Boot構建動態定時任務


前言

前陣子,有動態定時任務的需求,工期緊張且項目中未引入Quartz
此時,似乎只剩下Spring Boot提供的定時任務可以考慮了。

調研

Spring Boot中定時任務,一般是使用@Scheduled注解進行標注,可以設置對應的cron表達式或者設置運行間隔周期。
樣例代碼如下所示:

    @Scheduled(cron="0/5 * * * * ?")
    void testPlaceholder1() {
        System.out.println("Execute at " + System.currentTimeMillis());
    }

不過使用注解標注定時任務,無法滿足定時任務周期定時更新的需求。

解救

查詢資料,發現可以使用繼承SchedulingConfigurer接口,實現動態定時任務。

@Slf4j
@Configuration
public class ImepStatusSchedulingConfig implements SchedulingConfigurer {

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(
            ()->{
                // 業務邏輯
            },
            triggerContext -> {
                // 此處,cron表達式從數據庫查詢得到
                String cron = cronMapper.getCron();
                // 根據cron表達式,構建CronTrigger,計算下一次的執行時間
                CronTrigger trigger = new CronTrigger(cron);
                return trigger.nextExecutionTime(triggerContext);
            }
        );
    }
}

由代碼可知,每次運行定時任務時,均會動態計算下一次的運行時間點。

改動

Cron表達式比較復雜(項目由多人維護),而需求里只要求支持間隔固定秒數執行任務。
因此CronTrigger不再適合,因此需要進行相應改動。改動如下所示:

    // 出於篇幅,此處省略無關代碼
    triggerContext -> {
        // 此處,duration可以從數據庫查詢得到
        int duration = 1;
        Date date = triggerContext.lastCompletionTime();
        if (date != null) {
            Date scheduled = triggerContext.lastScheduledExecutionTime();
            if (scheduled != null && date.before(scheduled)) {
                // Previous task apparently executed too early...
                // Let's simply use the last calculated execution time then,
                // in order to prevent accidental re-fires in the same second.
                date = scheduled;
            }
        } else {
            date = new Date();
        }
        date.setTime(date.getTime() + duration * 1000);
        return date;
    }

如此,就實現了動態設置間隔秒數的定時任務。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM