Spring Boot builds dynamic timing tasks

Preface

A while ago, there was a demand for dynamic timing tasks, the construction period was tight and was not introduced in the project Quartz.
At this point, it seems that only the timing tasks provided by Spring Boot can be considered.

Research

Timed tasks in Spring Boot are generally @Scheduledannotated with annotations, and you can set the corresponding cronexpression or set the run interval period.
The sample code is as follows:

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

However, using annotations to mark timed tasks cannot meet the needs of periodic updates of timed tasks.

rescue

Query data and found that you can use the inheritance SchedulingConfigurerinterface to implement dynamic timing tasks.

@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);
            }
        );
    }
}

It can be seen from the code that every time a timed task is run, the next run time point will be dynamically calculated.

change

Cron expressions are more complicated (the project is maintained by multiple people), and the requirements only require support for executing tasks at fixed intervals of seconds.
Therefore it is CronTriggerno longer suitable and therefore needs to be modified accordingly. The changes are as follows:

 // 出于篇幅,此处省略无关代码
    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;
    }

In this way, the timing task of dynamically setting the interval seconds is realized.

Guess you like

Origin blog.csdn.net/a159357445566/article/details/108603666