1. 概述
上一篇介绍了Springboot整合quartz实现简单定时任务,本篇主要介绍Springboot整合quartz实现动态新建、暂停、恢复和删除定时任务,并实现数据库持久化。
2. 核心依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
3. 新建数据库表
从官网下载示例
在目录src\org\quartz\impl\jdbcjobstore下找到对应数据库版本的sql文件
4. yml配置文件
server:
port: 8395
spring:
application:
name: springboot-quartz-complex
datasource:
type: com.mysql.cj.jdbc.MysqlDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: xx.xx.xx.xx:3306/springboot?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
username: 用户名
password: 密码
hikari:
max-lifetime: 540000 #连接最大存活时间,默认30分钟
maximum-pool-size: 20 #最大连接数
minimum-idle: 10 #最小空闲连接,默认10
idle-timeout: 600000 #空闲连接超时时间,默认600000(10分钟)
auto-commit: true
pool-name: HikariCP
connection-timeout: 60000 #连接超时时间,默认30秒
connection-test-query: SELECT 1 #测试连接是否可用查询语句
quartz:
job-store-type: jdbc #将任务保存到数据库
wait-for-jobs-to-complete-on-shutdown: true #程序结束时会等待quartz相关内容结束
overwrite-existing-jobs: true #启动时更新已存在的job
jdbc:
initialize-schema: never
properties:
org:
quartz:
scheduler:
instanceName: scheduler #实例名
instanceId: AUTO #实例编号自动生成
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX #数据保存方式为数据库持久化
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate #数据库代理类
tablePrefix: QRTZ_ #数据表的前缀
isClustered: false #是否以集群方式运行
clusterCheckinInterval: 10000 #调度实例失效的检查时间间隔,单位毫秒
useProperties: true #JobDataMaps是否都为String类型
misfireThreshold: 60000 #最大能忍受的触发超时时间
threadPool:
class: org.quartz.simpl.SimpleThreadPool #连接池实现类
threadCount: 10 #线程数量
threadPriority: 5 #线程优先级
threadsInheritContextClassLoaderOfInitializingThread: true #配置是否启动自动加载数据库内的定时任务,默认true
5. 定时任务配置类
@Configuration
public class ScheduleConfig {
@Resource
private SchedulerFactoryBean schedulerFactoryBean;
@Bean
public Scheduler scheduler() {
return schedulerFactoryBean.getScheduler();
}
}
6. 业务接口
public interface ScheduleService {
/**
* 添加定时任务Job
* @param jobName
* @param jobGroup
* @param jobClassName
* @param triggerName
* @param triggerGroup
* @param cronExpression
*/
void addSchedule(String jobName, String jobGroup, String jobClassName, String triggerName, String triggerGroup, String cronExpression);
/**
* 暂停定时任务
* @param jobName
* @param jobGroup
*/
void pauseSchedule(String jobName, String jobGroup);
/**
* 重启定时任务
* @param jobName
* @param jobGroup
*/
void resumeSchedule(String jobName, String jobGroup);
/**
* 删除定时任务
* @param jobName
* @param jobGroup
*/
void deleteSchedule(String jobName, String jobGroup);
}
7. 业务接口实现类
@Service
public class ScheduleServiceImpl implements ScheduleService {
@Autowired
private Scheduler scheduler;
@Override
public void addSchedule(String jobName, String jobGroup, String jobClassName, String triggerName, String triggerGroup, String cronExpression) {
try {
Class className = Class.forName(jobClassName);
QuartzJobBean jobBean = (QuartzJobBean) className.newInstance();
JobDetail jobDetail = JobBuilder.newJob(jobBean.getClass())
.withIdentity(jobName, jobGroup)
.storeDurably()
.build();
CronTrigger cronTrigger = TriggerBuilder.newTrigger()
.withIdentity(triggerName, triggerGroup)
.startNow()
.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))
.build();
scheduler.scheduleJob(jobDetail, cronTrigger);
scheduler.start();
} catch (SchedulerException | ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
@Override
public void pauseSchedule(String jobName, String jobGroup) {
try {
scheduler.pauseJob(JobKey.jobKey(jobName, jobGroup));
} catch (SchedulerException e) {
e.printStackTrace();
}
}
@Override
public void resumeSchedule(String jobName, String jobGroup) {
try {
scheduler.resumeJob(JobKey.jobKey(jobName, jobGroup));
} catch (SchedulerException e) {
e.printStackTrace();
}
}
@Override
public void deleteSchedule(String jobName, String jobGroup) {
try {
scheduler.deleteJob(JobKey.jobKey(jobName, jobGroup));
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
8. 任务实现类
public class CronJob extends QuartzJobBean {
private static final Logger logger = LoggerFactory.getLogger(CronJob.class);
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
logger.info("执行cron定时任务{}", LocalDateTime.now());
}
}
9. 验证
@SpringBootTest
public class QuartzComplexApplicationTests {
@Autowired
private ScheduleService scheduleService;
@Test
void contextLoads() {
scheduleService.addSchedule("cronScheduleDetail", "cronScheduleGroup", "com.xlhj.boot.job.CronJob", "cronScheduleTrigger", "cronTriggerGroup", "0/30 * * * * ?");
//scheduleService.pauseSchedule("cronScheduleDetail", "cronScheduleGroup");
//scheduleService.resumeSchedule("cronScheduleDetail", "cronScheduleGroup");
}
}
启动服务,观察控制台
2021-11-01 19:31:30.292 INFO 21356 --- [eduler_Worker-1] com.xlhj.boot.job.CronJob : 执行cron定时任务2021-11-01T19:31:30.292
2021-11-01 19:32:00.433 INFO 21356 --- [eduler_Worker-2] com.xlhj.boot.job.CronJob : 执行cron定时任务2021-11-01T19:32:00.433