一、引言
动态定时任务是指可以动态添加、修改、删除定时任务的功能,一般应用于需要灵活控制定时任务的业务场景。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<? extends Job> 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<? extends Job> 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实现动态定时任务的方法。