定时任务执行时间在数据库中修改,无需启动服务

177 阅读2分钟

【开发需求】

每天在tb_base_uplod_cfg表中设定运行时间开始执行,此后设定值修改需立即生效,无需启动程序!

具体实现

  1. 在启动类上添@EnableScheduling注解
  2. 实现SchedulingConfigurer接口
  3. 重写SchedulingConfigurer接口的configureTasks方法

【代码演示】

@Slf4j  
@Component  
public class RealTimeStatisticalDataCalculationJob implements SchedulingConfigurer {  
  
    @Autowired  
    private RealTimeStatisticalDataCalculationJobService realTimeStatisticalDataCalculationJobService;  
    @Autowired  
    private BaseStatisticUploadCfgRepository baseStatisticUploadCfgRepository;  
  
    @Override  
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {  
        taskRegistrar.addTriggerTask(this::execute, triggerContext -> new CronTrigger(getCron()).nextExecutionTime(triggerContext));  
    }  
  
    private String getCron() {  
        BaseStatisticUploadCfg job = baseStatisticUploadCfgRepository.findAllByName("RealTimeStatisticalDataCalculationJob");  
        return job.getCron();  
    }  
  
    private void execute() {  
        final String lockKey = ConstantUtil.REDIS_KEY_JS_KECE_EOMS_CLIENT_REAL_TIME_STATISTICAL_DATA_CALCULATION_TASK_LOCK;  
        long s = System.currentTimeMillis();  
        String taskId = UUID.randomUUID().toString();  
        log.info("实时统计数据定时计算任务开始执行,本次任务ID:{}", taskId);  
        // 具体代码实现逻辑
        log.info("实时统计数据定时计算任务完成,耗时: {} ms", (System.currentTimeMillis() - s));  
    }  
  
}

上述方法虽然能够实现不用重启项目,但没有做到实时监测数据库中修改。只有在定时任务下次执行时调用getCron()方法时获取到新的cron表达式,之后就使用修改后的cron执行定时任务。因此使用下面方式来实现该功能需求

配置TaskSchedulerConfig

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;                            
import org.springframework.scheduling.TaskScheduler; `
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

@Configuration
public class TaskSchedulerConfig {

    @Bean(name = "myTaskScheduler")
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setThreadNamePrefix("MessageBroker-");
        scheduler.setPoolSize(Runtime.getRuntime().availableProcessors());
        scheduler.setRemoveOnCancelPolicy(true);
        scheduler.initialize();
        return scheduler;`
    }

}

@Slf4j  
@Component  
public class RealTimeStatisticalDataCalculationJob {  
  
    @Autowired  
    private RealTimeStatisticalDataCalculationJobService realTimeStatisticalDataCalculationJobService;  
    @Autowired  
    private BaseStatisticUploadCfgRepository baseStatisticUploadCfgRepository;  
    @Autowired  
    @Qualifier("myTaskScheduler")  
    private TaskScheduler taskScheduler;  

    private static final Map<String, ScheduledFuture<?>> JOB = new HashMap<>();  

    @PostConstruct  
        public void scheduleAllJobs() {  
        // 创建定时任务  
        createJob();  
    }  

    /**  
    * 新增调用该方法,创建定时任务  
    */  
    public void createJob() {  
        // 创建任务  
        // 执行任务逻辑  
        Runnable job = this::execute;  
        // 根据cron字段创建CronTrigger触发器  
        CronTrigger cronTrigger = new CronTrigger(getCron());  
        // 安排定时任务  
        ScheduledFuture<?> scheduledFuture = taskScheduler.schedule(job, cronTrigger);  
        // 将任务加入到scheduledJobs映射中  
        JOB.put("RealTimeStatisticalDataCalculationJob", scheduledFuture);  
    }  

    /**  
    * 更新表中记录,调用该方法  
    */  
    public void updateJob() {  
        // 取消旧的定时任务  
        cancelJob("RealTimeStatisticalDataCalculationJob");  
        // 创建新的定时任务  
        createJob();  
    }  

    /**  
    * 删除表中记录,调用该方法  
    *  
    * @param key 定时任务标识  
    */  
    public void deleteJob(String key) {  
        // 取消定时任务  
        cancelJob(key);  

        // 从scheduledJobs映射中移除任务  
        JOB.remove(key);  
    }  

    /**  
    * 取消定时任务  
    *  
    * @param key 定时任务标识  
    */  
    private void cancelJob(String key) {  
    ScheduledFuture<?> scheduledFuture = JOB.get(key);  
        // 取消任务  
        if (scheduledFuture != null) {  
            scheduledFuture.cancel(true);  
        }  
    }  

    private String getCron() {  
        List<BaseStatisticUploadCfgEntity> baseStatisticUploadCfgList = baseStatisticUploadCfgRepository.findAll();  
        if (StringUtils.isNullOrEmpty(baseStatisticUploadCfgList)){  
            log.error("未配置统计上报配置信息对象,本次任务结束!");  
            return "-";  
        }  
        BaseStatisticUploadCfgEntity baseStatisticUploadCfg = baseStatisticUploadCfgList.get(0);  
        // 查询tb_base_statistic_upload_cfg表中的 【实时数据统计周期(分钟)】值 和 【实时统计延迟运行分钟数】值  
        if (baseStatisticUploadCfg != null&& baseStatisticUploadCfg.getRealDataStatPeriods() != null && baseStatisticUploadCfg.getRealStatDelayRunMinutes() != null){  
            // 实时数据统计周期(分钟)  
            Integer realDataStatPeriods = baseStatisticUploadCfg.getRealDataStatPeriods();  
            // 实时统计延迟运行分钟数  
            Integer realStatDelayRunMinutes = baseStatisticUploadCfg.getRealStatDelayRunMinutes();  
            return "0 " + realStatDelayRunMinutes + "/" + realDataStatPeriods + " * * * ?";  
        }  
        return "-";  
    }  
    
    /**
    * 任务功能实现
    */
    private void execute() {  
        long s = System.currentTimeMillis();  
        String taskId = UUID.randomUUID().toString();  
        log.info("实时统计数据定时计算任务开始执行,本次任务ID:{}", taskId);  
        realTimeStatisticalDataCalculationJobService.realTimeStatisticalDataCalculation();  
        log.info("实时统计数据定时计算任务完成,耗时: {} ms", (System.currentTimeMillis() - s));  
    }  
}