Prefacio
Hace un tiempo, había una demanda de tareas de sincronización dinámica, el período de construcción era ajustado y no se introdujo en el proyecto Quartz
.
En este punto, parece que solo se pueden considerar las tareas de sincronización proporcionadas por Spring Boot.
Investigación
Las tareas programadas en Spring Boot generalmente se @Scheduled
anotan con anotaciones, y puede establecer la cron
expresión correspondiente o establecer el período de intervalo de ejecución.
El código de muestra es el siguiente:
@Scheduled(cron="0/5 * * * * ?")
void testPlaceholder1() {
System.out.println("Execute at " + System.currentTimeMillis());
}
Sin embargo, el uso de anotaciones para marcar tareas cronometradas no puede satisfacer las necesidades de actualizaciones periódicas de tareas cronometradas.
rescate
Consulte datos y descubrió que puede usar la SchedulingConfigurer
interfaz de herencia para implementar tareas de sincronización dinámica.
@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);
}
);
}
}
Se puede ver en el código que cada vez que se ejecuta una tarea programada, el siguiente punto de tiempo de ejecución se calculará dinámicamente.
cambio
Las expresiones cron son más complicadas (el proyecto lo mantienen varias personas) y los requisitos solo requieren soporte para ejecutar tareas en intervalos fijos de segundos.
Por tanto, ya CronTrigger
no es adecuado y, por tanto, debe modificarse en consecuencia. Los cambios son los siguientes:
// 出于篇幅,此处省略无关代码
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;
}
De esta manera, se realiza la tarea de temporización de establecer dinámicamente los segundos de intervalo.