动态控制 Spring Boot 中的 @Scheduled 定时任务

1. 概论

Spring Boot 中的 @Scheduled 注解为定时任务提供了一种很简单的实现,只须要在注解中加上一些属性,例如 fixedRate、fixedDelay、cron(最经常使用)等等,而且在启动类上面加上 @EnableScheduling 注解,就能够启动一个定时任务了。java

可是在某些状况下,并无这么简单,例如项目部署上线以后,咱们可能会修改定时任务的执行时间,而且中止、重启定时任务等,由于定时任务是直接写死在程序中的,修改起来不是很是的方便。因此,简单记录一下本身的一些解决方案,仅供参考。segmentfault

2. 在配置文件中设置参数

以 cron 表达式为例,通常的作法是将 @Scheduled 的属性写在程序中的,例如这样:app

@Component
public class TestTask {
    private static SimpleDateFormat dateFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Scheduled(cron = "0/5 * * * * ?")
    public void test(){
        System.out.println(dateFmt.format(new Date()) + " : 执行定时任务");
    }
}

若是须要修改的话,咱们能够将 cron 表达式配在 application.yml 中:ide

#application.yml中的配置
scheduled:
  cron: 0/5 * * * * ?

而后在 @Scheduled 中获取这个配置:code

@Scheduled(cron = "${scheduled.cron}")
public void test(){
    System.out.println(dateFmt.format(new Date()) + " : 执行定时任务");
}

等到了线上的时候,再经过修改配置文件中的内容来进行控制。具体怎么动态的修改配置文件中的内容,后面我会专门写一篇文章来讲明。orm

3. 如何关闭定时任务

一种方式是根据实际的需求,设置一个好久以后的时间再执行,例如明年的某个时间点,你可能会想何不设置一个已通过去的时间(例如 2012 年),可是很遗憾,@Scheduled 并不支持设置年份。部署

另外 Spring Boot 2.1 以上的版本还提供了一种中止定时任务的方案,就是在 cron 中配置 "-" 便可,你也能够在配置文件中设置这个符号:get

#application.yml中的配置
scheduled:
  cron: "-"

注意这里必须加上一个双引号,由于在 application.yml 中, - 是一个特殊的字符。it

4. 为定时任务设置开关

若是嫌上面这种方式比较死板,能够尝试另外一种,给定时任务加上开关的方案,在配置文件中配置一个 boolean 属性,若是是 true 的话,就开启定时任务,不然不开启。io

#application.yml中的配置
scheduled:
  cron: 0/5 * * * * ?
enable:
  scheduled: true

而后咱们可使前面说到的 @Conditional 注解来实现这个功能,若是你还不了解,能够看我这篇文章:浅谈 Spring Boot 中的 @Conditional 注解

其实 @Scheduled 注解,是被一个叫作 ScheduledAnnotationBeanPostProcessor 的类所拦截的,因此咱们能够根据配置,决定是否建立这个 bean,若是没有这个 bean,@Scheduled 就不会被拦截,那么定时任务确定不会执行了,有了这个思路,实现起来就很简单了。须要注意的是:这种方式,启动类上面的 @EnableScheduling 须要去掉。

而后建立一个 ScheduledCondtion 类,内容以下:

public class ScheduledCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //读取配置中的属性
        return Boolean.valueOf(context.getEnvironment().getProperty("enable.scheduled"));
    }
}

这个类的功能很简单,就是去读取配置,而后返回一个 boolean 值。

而后建立一个配置类 ScheduledConfig ,内容以下:

@Configuration
public class ScheduledConfig {

    @Conditional(ScheduledCondition.class)
    @Bean
    public ScheduledAnnotationBeanPostProcessor processor() {
        return new ScheduledAnnotationBeanPostProcessor();
    }
}

这个配置,就是以 ScheduledCondtion 为条件,决定是否建立 bean。而后,启动项目,定时任务就会执行,若是咱们将配置修改成 false,则不会执行。

这样的话,咱们就可以很容易的启动或者关闭定时任务了,而且也能够实时修改 cron 表达式的值。

相关文章
相关标签/搜索