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 @Scheduled
annotated with annotations, and you can set the corresponding cron
expression 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 SchedulingConfigurer
interface 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 CronTrigger
no 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.