• 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;
        }
    

    如此,就实现了动态设置间隔秒数的定时任务。

  • 相关阅读:
    洛谷 P3389 【模板】高斯消元法
    洛谷 P2090 数字对
    树链剖分
    bzoj3784 树上的路径
    K Seq HihoCoder
    一些奇怪的注意事项
    洛谷 P3437 [POI2006]TET-Tetris 3D
    洛谷 P2048 [NOI2010]超级钢琴 || Fantasy
    JVM字节码指令
    java中什么是Bridge Method(桥接方法)
  • 原文地址:https://www.cnblogs.com/jason1990/p/13639556.html
Copyright © 2020-2023  润新知