SpringBoot学习(九)--SpringBoot定时任务@Scheduled和动态定时任务

2021年1月23日 18点热度 0条评论 来源: Super_PF

版权声明:作者原创,转载请注明出处。
本系列文章目录地址:http://blog.csdn.net/u011961421/article/details/79416510

简介

定时任务或者说定时调度,是系统中比较普遍的一个功能,例如数据归档、清理,数据定时同步(非实时),定时收发,流量控制等等都需要用到定时任务,常见的定时调度框架有Quartz、TBSchedule等。

同样,Spring自3.0版本起也增加了任务调度功能Schedule,它好比是一个轻量级的Quartz,使用起来方便、简洁,且不需要依赖其他的JAR包。之所以说它是轻量级Quartz,是因为在现如今遍地分布式的大环境下,Spring自带的Schedule不支持分布式部署,所以若是分布式环境开发请忽略此文章,可以选用Quartz、TBSchedule等,且一般稍大点的公司都有独立的统一调度中心。

正文

Schedule写在core包当中,在SpringBoot中使用定时任务只需要简单配置。

1.首先在**Application启动类中加入@EnableScheduling注解开启定时任务。

@SpringBootApplication
//这里开启定时任务
@EnableScheduling
public class CmsApplication { 

    public static void main(String[] args) {
        SpringApplication.run(CmsApplication.class, args);
    }
}

2.编写具体的定时任务组件(@Component注解),并且在需要定时调度的方法上添加@Scheduled触发器。Spring实现了Quartz简单的和cron表达式两种触发方式,这里我们用cron表达式,”0/20 * * * * ?”表示每20秒触发一次,具体cron表达式逻辑可以自行百度。

@Component
public class MyStaticTask { 

    /** * 固定cron配置定时任务 */
    @Scheduled(cron = "0/20 * * * * ?")
    public void doTask(){
        System.out.println("执行了MyStaticTask,时间为:"+new Date(System.currentTimeMillis()));
    }
}

以上,一个简单的定时任务便已完成,但是触发器是硬编码,相信肯定满足不了绝大部分业务场景,同样Spring提供了SchedulingConfigurer接口,下面介绍可配置、动态修改触发器的定时任务。

可配置的定时任务组件需要实现SchedulingConfigurer接口中的configureTasks方法,该方法有两个入参(Runnable task, Trigger trigger),第一个为我们任务的具体逻辑实现,第二个为触发器,动态的定时任务则意味着Trigger需要动态获取,由于之前我们已经集成redis,因此这里我们从redis获取相关配置。

@Component
public class MyDynamicTask implements SchedulingConfigurer { 
    private static Logger log = LoggerFactory.getLogger(MyDynamicTask.class);

    @Autowired
    RedisManager redisManager;

    private static String cron;

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        scheduledTaskRegistrar.addTriggerTask(doTask(), getTrigger());
    }

    private Runnable doTask() {
        return new Runnable() {
            @Override
            public void run() {
                // 业务逻辑
                log.info("执行了MyDynamicTask,时间为:" + new Date(System.currentTimeMillis()));
            }
        };
    }

    private Trigger getTrigger() {
        return new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                // 触发器
                CronTrigger trigger = new CronTrigger(getCron());
                return trigger.nextExecutionTime(triggerContext);
            }
        };
    }

    public String getCron() {
        String newCron = redisManager.getStr("cms:MyDynamicTask");
        if (StringUtils.isEmpty(newCron)) {
            throw new CmsException("The config cron expression is empty");
        }
        if (!newCron.equals(cron)) {
            log.info(new StringBuffer("Cron has been changed to:'").append(newCron).append("'. Old cron was:'").append(cron).append("'").toString());
            cron = newCron;
        }
        return cron;
    }
}

上述cron也可以从其他地方动态获取,这样在配置值修改后,定时任务调度器便被更新了,不过需要注意的是,此种方式修改了配置值后,需要在下一次调度结束后,才会更新调度器,并不会在修改配置值时实时更新,实时更新需要在修改配置值时额外增加相关逻辑处理。

最后补一张运行日志,相关代码请参考https://github.com/15651037763/cms

    原文作者:Super_PF
    原文地址: https://blog.csdn.net/u011961421/article/details/79779650
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。