SpringBoot外部化配置定时任务cron表达式

SpringBoot外部化配置定时任务cron表达式

背景

在日常开发中我们经常会使用到定时任务的情况,SpringBoot为我们很方便的集成了定时任务。我们只需要简单的几部就可以配置好一个定时任务。

@Component
public class LocationTask {

    @Scheduled(cron = "0/10 * * * * ?")
    public void runTask() {
        System.out.println("hello");
    }
}

@SpringBootApplication
@EnableScheduling
public class DynamicScheduledDemoApplication {

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

}

我们只需要定义一个Task将它交给Spring管理,然后再在需要执行的任务上添加上具体的cron表达式即可。但是这种硬编码的方式其实不太合适,不方便我们后面修改。所以我们可以更改一下,将corn表达式改成外部化配置。

配置文件

最简单的一种就是直接将cron表达式的值配置在配置文件中来注入

@Component
public class LocationTask {

    @Scheduled(cron = "${my.task.cron}")
    public void runTask() {
        System.out.println("hello");
    }
}

然后再在配置文件中配置一下:

my:
  task:
    cron: 0/10 * * * * ?

MySQL配置

我们同样可以将cron配置在数据库中

我们在数据库中创建一张这样的表来存放配置文件

CREATE TABLE `scheduled_task` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `cron_expression` varchar(255) NOT NULL,
  `enabled` bit(1) NOT NULL,
  `task_name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
  • ScheduledTask 为我们的Entity对象
  • ScheduledTask1、ScheduledTask2为我们具体执行定时任务的类
  • TaskSchedulerConfig用来配置定时任务执行的线程池
  • ScheduledTaskManager中通过查询所有的task配置,然后通过taskName从spring容器中找到具体的对象,将他们注入线程池中执行。
@Entity
@Table(name = "scheduled_task")
@Data
public class ScheduledTask {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "cron_expression", nullable = false)
    private String cronExpression;

    @Column(name = "task_name", nullable = false)
    private String taskName;

    @Column(name = "enabled", nullable = false)
    private Boolean enabled;

}

public interface ScheduledTaskRepository extends JpaRepository<ScheduledTask, Long> {
    List<ScheduledTask> findAllByEnabledTrue();

}

@Component
public class ScheduledTask1 implements Runnable {
    @Override
    public void run() {
        // 定时任务1的执行逻辑
        System.out.println("task1");
    }
}

@Component
public class ScheduledTask2 implements Runnable {
    @Override
    public void run() {
        // 定时任务2的执行逻辑
        System.out.println("task2");
    }
}

@Configuration
public class TaskSchedulerConfig {
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(10);
        scheduler.setThreadNamePrefix("TaskScheduler-");
        scheduler.initialize();
        return scheduler;
    }
}

@Component
@RequiredArgsConstructor
public class ScheduledTaskManager {
    private final TaskScheduler taskScheduler;
    private final ScheduledTaskRepository taskRepository;
    private final ApplicationContext applicationContext;


    @PostConstruct
    public void registerTasks() {
        List<ScheduledTask> tasks = taskRepository.findAllByEnabledTrue();
        tasks.forEach(task -> {
            try {
                Runnable taskInstance = (Runnable) applicationContext.getBean(task.getTaskName());

                taskScheduler.schedule(taskInstance, new CronTrigger(task.getCronExpression()));
            } catch (Exception e) {
                // handle exception
            }
        });
    }
}

posted @ 2023-04-03 23:43  loveletters  阅读(595)  评论(0编辑  收藏  举报