SpringBoot中实现接口执行定时任务

2,812 阅读2分钟

这是我参与8月更文挑战的第29天,活动详情查看:8月更文挑战

上篇文章学习了SpringBoot中使用@Scheduled注解实现定时任务:SpringBoot中使用@Scheduled创建定时任务

尽管使用@Scheduled注解配置定时任务是十分方便的,但是由于其设置是在注解中,因此如果需要改变当前任务的定时规划,则需要重新启动项目才可以生效。为了解决这种不能及时变更的问题,我们可以使用实现接口的方式来完成定时任务的创建。

引入依赖

由于需要实时的修改定时任务执行的规则,那么就不能将定时规则写在代码中,因此我们将定时任务规则写入数据库中,每次执行定时任务时会获取数据库中最新规则设定到任务中。 我们需要在项目中使用数据库,那么要引入MySQl、MyBatis等依赖信息:

<dependency>
     <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.1</version>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.5</version>
    <scope>compile</scope>
</dependency>

数据库中新增任务规则表和数据

在本地数据库中新增一个task表,用来记录定时任务的规则信息,

CREATE TABLE `task`  (
  `id` int NOT NULL PRIMARY KEY,
  `cron` varchar(30) NOT NULL  
);
INSERT INTO `task` VALUES (1, '* * * ? * ?');

由上述sql语句中的'* * * ? * ?'值可以看出,我们添加数据的定时任务规则是每秒执行一次。 随后在SpringBoot项目的配置文件中配置数据源信息:

spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource..password=123456

创建定时器类

准备好数据并配置数据源信息后,我们定义一个定时器类,并在该类上使用@EnableScheduling注解开启定时任务。

@Configuration
@EnableScheduling 
public class TaskDemo implements SchedulingConfigurer {
    @Mapper
    public interface CronMapper {
        @Select("select cron from cron limit 1")
        public String getCron();
    }

    @Autowired 
    @SuppressWarnings("all")
    CronMapper cronMapper;

    /**
     * 执行定时任务.
     */
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(
                () -> System.out.println("执行动态定时任务: " + LocalDateTime.now().toLocalTime()),
                triggerContext -> {
                    String cron = cronMapper.getCron();
                    if (StringUtils.isEmpty(cron)) {
                        
                    }
                    return new CronTrigger(cron).nextExecutionTime(triggerContext);
                }
        );
    }

}

测试定时任务

配置完成后,我们启动项目,发现定时任务按照设定的每秒执行输出,而如果我们修改数据库中cron字段对应的值为'0/5 * * ? * ?'时,定时任务的规则自动发生了变化。如果最终修改的值不符合cron表达式规范,那么定时器类会报错停止执行。