一、引言
动态定时任务是指可以动态添加、修改、删除定时任务的功能,一般应用于需要灵活控制定时任务的业务场景。SpringBoot作为一个非常火热的Java框架,提供了非常便捷的定时任务的实现方式,本文主要介绍如何使用SpringBoot实现动态定时任务。下面我们将从多个方面进行详细的阐述。
二、定时任务的基本实现方式
SpringBoot中基于注解的定时任务实现方式非常便捷,只需在任务方法上添加注解@Scheduled即可实现简单的定时任务功能。例如,在SpringBoot应用程序中,执行某个方法,每隔一段时间输出某个信息,可以使用如下注解配置:
@Scheduled(fixedRate = 5000) public void reportCurrentTime() { logger.info("当前时间是:{}", dateFormat.format(new Date())); }
上述代码中,@Scheduled注解指示该方法应该执行一个定时任务,fixedRate是一个参数,它规定任务每隔多少毫秒执行一次。在这种情况下,任务将每隔5秒查询一次数据库并记录当前时间。但是,这种方法只适合固定间隔的任务,如果想要控制任务的实现,就需要使用Cron表达式来定义定时策略。例如:
@Scheduled(cron = "0 15 10 ? * *") public void scheduledTask() { // 执行任务 }
上述代码中,@Scheduled注解中通过cron属性设置了一个Cron表达式,它表示任务将在每天的上午10点15分执行。
三、动态定时任务的实现方式
1. 存储定时任务信息
为了实现动态定时任务的功能,我们需要在数据库中存储定时任务的相关信息,如任务名称、任务描述、Cron表达式等。 我们可以建立一个定时任务数据表,将任务的相关信息存储在该表中。
CREATE TABLE `task_schedule` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '任务ID', `job_name` varchar(64) NOT NULL COMMENT '任务名称', `job_desc` varchar(256) DEFAULT NULL COMMENT '任务描述', `job_group` varchar(64) DEFAULT NULL COMMENT '任务所属分组', `job_cron` varchar(64) NOT NULL COMMENT 'Cron表达式', `job_status` int(2) NOT NULL COMMENT '任务状态,1:启用,0:禁用', `job_start_time` datetime DEFAULT NULL COMMENT '任务开始时间', `job_end_time` datetime DEFAULT NULL COMMENT '任务结束时间', `create_time` datetime NOT NULL COMMENT '任务创建时间', `update_time` datetime DEFAULT NULL COMMENT '任务更新时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='动态任务调度表';
2. 使用Quartz实现动态定时任务
SpringBoot集成了Quartz,并且提供了官方的Quartz工具包starter,因此,我们可以基于Quartz实现动态定时任务。
2.1 添加依赖
首先我们需要添加Quartz相关的依赖和SpringBoot的依赖。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency>
2.2 实现动态添加任务
SpringBoot提供了一个SchedulerFactoryBean来配置Quartz,我们可以通过SchedulerFactoryBean创建调度工厂,并使用任务调度工厂创建Scheduler调度器。下面我们来实现动态添加任务的代码。
/** * 任务调度核心类 */ @Configuration public class QuartzConfig { @Autowired private DataSource dataSource; /** * 配置SchedulerFactoryBean */ @Bean public SchedulerFactoryBean schedulerFactoryBean() { SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean(); // 加载quartz数据源 schedulerFactoryBean.setDataSource(dataSource); return schedulerFactoryBean; } /** * 创建Scheduler定时器 */ @Bean public Scheduler scheduler() throws SchedulerException { return schedulerFactoryBean().getScheduler(); } /** * 添加任务 * @param jobName 任务名称 * @param jobGroup 任务分组 * @param cronExpression Cron表达式 * @param jobClass 任务类 * @throws SchedulerException */ public void addJob(String jobName, String jobGroup, String cronExpression, Class jobClass) throws SchedulerException { // 获取调度器 Scheduler scheduler = scheduler(); // 构建任务信息 JobDetail jobDetail = JobBuilder.newJob(jobClass) .withIdentity(jobName, jobGroup) .build(); // 设置任务触发器 CronTrigger cronTrigger = TriggerBuilder.newTrigger() .withIdentity(jobName, jobGroup) .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)) .build(); // 调度器中添加任务 scheduler.scheduleJob(jobDetail, cronTrigger); // 启动调度器 if(!scheduler.isShutdown()) { scheduler.start(); } } }
上述代码中,我们定义了一个SchedulerFactoryBean的Bean,并通过@Autowired注解将数据源注入到该Bean中。然后通过该Bean的方法getScheduler()获取到Scheduler调度器。 可以看到,我们通过Quartz提供的JobBuilder和TriggerBuilder创建JobDetail和CronTrigger决定了动态定时任务的任务执行和触发方式。最后调用调度器的方法scheduleJob()将任务添加到调度器中。
2.3 动态添加任务的调用
我们可以在任意位置调用添加任务方法addJob(),从而实现动态添加任务的功能。
@Autowired private QuartzConfig quartzConfig; public boolean addTask(String jobName, String jobGroup, String cron, Class jobClass) { try { quartzConfig.addJob(jobName, jobGroup, cron, jobClass); return true; } catch (SchedulerException e) { // ... return false; } }
2.4 动态修改任务
动态修改任务需要调用Quartz的Scheduler修改任务,我们可以在上一步的代码中添加该功能。
/** * 修改任务 * @param jobName 任务名称 * @param jobGroup 任务分组 * @param cronExpression Cron表达式 * @throws SchedulerException */ public void modifyJob(String jobName, String jobGroup, String cronExpression) throws SchedulerException { // 获取调度器 Scheduler scheduler = scheduler(); // 根据任务名称和分组名称获取任务Key TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup); // 根据任务Key获取Trigger CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey); // 重新设置Cron表达式 CronScheduleBuilder builder = CronScheduleBuilder.cronSchedule(cronExpression); CronTrigger newTrigger = cronTrigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(builder).build(); // 重置触发器中的Cron表达式 scheduler.rescheduleJob(triggerKey, newTrigger); }
2.5 动态删除任务
在Quartz中删除任务需要调用Scheduler删除任务,Quartz提供了暂停、恢复和删除任务的方法,我们可以基于这些方法实现动态删除任务的功能。
/** * 删除任务 * @param jobName 任务名称 * @param jobGroup 任务分组 * @throws SchedulerException */ public void deleteJob(String jobName, String jobGroup) throws SchedulerException { // 获取调度器 Scheduler scheduler = scheduler(); // 根据任务名称和分组名称获取任务Key JobKey jobKey = JobKey.jobKey(jobName, jobGroup); // 删除任务 scheduler.deleteJob(jobKey); }
四、总结
本文详细介绍了如何使用SpringBoot实现动态定时任务功能,从定时任务的基本实现方式到动态定时任务的实现方式,逐步展示了动态定时任务的全过程,相信读完本文后,你已经掌握了使用SpringBoot实现动态定时任务的方法。