序文
少し前に、動的なタイミングタスクの需要があり、建設期間は厳しく、プロジェクトには導入されませんでした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;
}
このようにして、間隔秒を動的に設定するタイミングタスクが実現されます。