由于业务需求,需要提供一个能够让用户动态配置定时任务的入口,定时去同步数据
1、简单的业务处理,直接使用@Scheduled注解就能开启定时任务,例如在方法上@Scheduled(cron = “0 0/1 * * * ?”),书写cron表达式就能配置定时任务。
@Scheduled(cron = "0 0/1 * * * ?")
public void execEveryDay() {
checkPlan();
}
2、但是随着业务复杂化,使用注解目前是满足不了动态配置定时任务的,以下代码能够实现cron表达式的动态配置。
@Lazy(false)
@Component
@EnableScheduling
@Slf4j
public class OutPutTask implements SchedulingConfigurer {
private String cron = "0 55 23 ? * *";
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.addTriggerTask(() -> {
// 分布式锁,避免高并发同时执行方法
try {
Boolean lockStatus = redisTemplate.opsForValue().setIfAbsent(RedisKeyPrefix.RECORD_OUT_PUT, new Date(), 1, TimeUnit.MINUTES);
if (lockStatus == null || !lockStatus) {
return;
}
log.info("产能计算定时任务{}", new Date());
recordOutput();
} finally {
// 释放锁
redisTemplate.delete(RedisKeyPrefix.RECORD_OUT_PUT);
}
}, triggerContext -> {
//此方法用于动态拿到cron表达式
cron = this.getCronString();
CronTrigger trigger;
try {
// 一旦设置,立即生效
trigger = new CronTrigger(cron);
return trigger.nextExecutionTime(triggerContext);
} catch (Exception e) {
// 如果格式有问题就按默认时间(时间为每天23点55分)
trigger = new CronTrigger("0 55 23 ? * *");
return trigger.nextExecutionTime(triggerContext);
}
});
}
private String getCronString() {
// 获取时间(当前方法返回的时间格式为yyyy-MM-dd HH:mm:ss)
Date beginDate = dictService.getDayOutputBeginTime(new Date());
// 截取分钟和小时
String hour = beginDate.toString().substring(11, 13);
String min = beginDate.toString().substring(14, 16);
// 替换min,hour
String cron = "0 min hour ? * *";
return cron.replaceAll("min", min).replaceAll("hour", hour);
}
然后我们只需要在页面上提供一个能够让用户配置定时任务的入口,就能实现动态配置。
如果面向的用户懂得cron表达式,也可以直接让用户配置cron表达式也是可以的,省的程序员进行额外的数据处理,只要配置正确,任何处理方式都行,例如:



