版权声明:作者原创,转载请注明出处。
本系列文章目录地址: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也可以从其他地方动态获取,这样在配置值修改后,定时任务调度器便被更新了,不过需要注意的是,此种方式修改了配置值后,需要在下一次调度结束后,才会更新调度器,并不会在修改配置值时实时更新,实时更新需要在修改配置值时额外增加相关逻辑处理。