# spring boot 配置 quartz
# 导入依赖
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-quartz</artifactId> | |
<version>2.6.7</version> | |
</dependency> |
# 配置文件
server: | |
port: 8090 | |
spring: | |
datasource: | |
driver-class-name: com.mysql.jdbc.Driver | |
username: root | |
password: root | |
url: jdbc:mysql://127.0.0.1:3306/quartz?characterEncoding=utf-8&useSSL=false | |
quartz: | |
jdbc: | |
initialize-schema: never # 是否自动使用 SQL 初始化 Quartz 表结构。always: 总是,never: 不需要 | |
job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。 | |
properties: | |
org: | |
quartz: | |
scheduler: | |
instanceName: QuartzScheduler # 调度标识名 集群中每一个实例都必须使用相同的名称 | |
instanceId: AUTO # 定时任务的实例编号,如果手动指定需要保证每个节点的唯一性 | |
threadPool: | |
class: org.quartz.simpl.SimpleThreadPool | |
threadCount: 100 # 线程池大小。默认为 10 。 | |
threadPriority: 5 # 线程优先级 | |
jobStore: | |
misfireThreshold: 120000 |
# 代码实现
# 编写工具类 QuartzCronDateUtils 日期转换 cron 表达式
public class QuartzCronDateUtils { | |
/*** | |
* 功能描述:日期转换 cron 表达式时间格式 | |
* @param date | |
* @param dateFormat : e.g:yyyy-MM-dd HH:mm:ss | |
* @return | |
*/ | |
public static String formatDateByPattern(Date date,String dateFormat){ | |
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); | |
String formatTimeStr = null; | |
if (date != null) { | |
formatTimeStr = sdf.format(date); | |
} | |
return formatTimeStr; | |
} | |
/*** | |
* convert Date to cron ,eg. "14 01 17 22 07 ? 2017" | |
* @param date: 时间点 | |
* @return | |
*/ | |
public static String getCron(java.util.Date date){ | |
String dateFormat="ss mm HH dd MM ? yyyy"; | |
return formatDateByPattern(date,dateFormat); | |
} | |
} |
# 编写动态任务调度管理器工具类,实现 CRUD 管理定时器
public class QuartzManager { | |
private static SchedulerFactory schedulerFactory = new StdSchedulerFactory(); | |
/** | |
* 功能: 添加一个定时任务 | |
* @param jobName 任务名 | |
* @param jobGroupName 任务组名 | |
* @param triggerName 触发器名 | |
* @param triggerGroupName 触发器组名 | |
* @param jobClass 任务的类类型 eg:TimedMassJob.class | |
* @param cron 时间设置 表达式,参考 quartz 说明文档 | |
* @param objects 可变参数需要进行传参的值 | |
*/ | |
public static void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, Class jobClass, String cron,Object...objects) { | |
try { | |
Scheduler scheduler = schedulerFactory.getScheduler(); | |
// 任务名,任务组,任务执行类 | |
JobDetail jobDetail= JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build(); | |
// 触发器 | |
if(objects!=null){ | |
for (int i = 0; i < objects.length; i++) { | |
// 该数据可以通过 Job 中的 JobDataMap dataMap = context.getJobDetail ().getJobDataMap (); 来进行参数传递值 | |
jobDetail.getJobDataMap().put("data"+(i+1), objects[i]); | |
} | |
} | |
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger(); | |
// 触发器名,触发器组 | |
triggerBuilder.withIdentity(triggerName,triggerGroupName); | |
triggerBuilder.startNow(); | |
// 触发器时间设定 | |
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron)); | |
// 创建 Trigger 对象 | |
CronTrigger trigger = (CronTrigger) triggerBuilder.build(); | |
// 调度容器设置 JobDetail 和 Trigger | |
scheduler.scheduleJob(jobDetail, trigger); | |
// 启动 | |
if (!scheduler.isShutdown()) { | |
scheduler.start(); | |
} | |
} catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
/** | |
* 功能:修改一个任务的触发时间 | |
* @param jobName | |
* @param jobGroupName | |
* @param triggerName 触发器名 | |
* @param triggerGroupName 触发器组名 | |
* @param cron 时间设置,参考 quartz 说明文档 | |
*/ | |
public static void modifyJobTime(String jobName, String jobGroupName, String triggerName, String triggerGroupName, String cron) { | |
try { | |
Scheduler scheduler = schedulerFactory.getScheduler(); | |
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName); | |
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); | |
if (trigger == null) { | |
return; | |
} | |
String oldTime = trigger.getCronExpression(); | |
if (!oldTime.equalsIgnoreCase(cron)) { | |
// 触发器 | |
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger(); | |
// 触发器名,触发器组 | |
triggerBuilder.withIdentity(triggerName, triggerGroupName); | |
triggerBuilder.startNow(); | |
// 触发器时间设定 | |
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron)); | |
// 创建 Trigger 对象 | |
trigger = (CronTrigger) triggerBuilder.build(); | |
// 方式一 :修改一个任务的触发时间 | |
scheduler.rescheduleJob(triggerKey, trigger); | |
} | |
} catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
/** | |
* 功能:移除一个任务 | |
* @param jobName | |
* @param jobGroupName | |
* @param triggerName | |
* @param triggerGroupName | |
*/ | |
public static void removeJob(String jobName, String jobGroupName,String triggerName, String triggerGroupName) { | |
try { | |
Scheduler scheduler = schedulerFactory.getScheduler(); | |
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName,triggerGroupName); | |
// 停止触发器 | |
scheduler.pauseTrigger(triggerKey); | |
// 移除触发器 | |
scheduler.unscheduleJob(triggerKey); | |
// 删除任务 | |
scheduler.deleteJob(JobKey.jobKey(jobName,jobGroupName)); | |
} catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
/** | |
* | |
* 功能:启动所有定时任务 | |
*/ | |
public static void startJobs() { | |
try { | |
Scheduler scheduler = schedulerFactory.getScheduler(); | |
scheduler.start(); | |
} catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
/** | |
* 功能:关闭所有定时任务 | |
*/ | |
public static void shutdownJobs() { | |
try { | |
Scheduler scheduler = schedulerFactory.getScheduler(); | |
if (!scheduler.isShutdown()) { | |
scheduler.shutdown(); | |
} | |
} catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
public static List getTotal() throws SchedulerException { | |
Scheduler scheduler = schedulerFactory.getScheduler(); | |
GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup(); | |
Set<JobKey> jobKeys = null; | |
List jobList = new ArrayList(); | |
try { | |
jobKeys = scheduler.getJobKeys(matcher); | |
for (JobKey jobKey : jobKeys) { | |
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey); | |
for (Trigger trigger : triggers) { | |
HashMap job = new HashMap(); | |
job.put("jobDetailName",jobKey.getName()); | |
job.put("groupName",jobKey.getGroup()); | |
job.put("jobCronExpression","触发器:" + trigger.getKey()); | |
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey()); | |
job.put("status",triggerState.name()); | |
if (trigger instanceof CronTrigger) { | |
CronTrigger cronTrigger = (CronTrigger) trigger; | |
String cronExpression = cronTrigger.getCronExpression(); | |
job.put("jobCronExpression",cronExpression); | |
} | |
jobList.add(job); | |
} | |
} | |
} catch (SchedulerException e) { | |
e.printStackTrace(); | |
} | |
return jobList; | |
} | |
} |
# 自定义 Job,实现 org.quartz.Job 接口
data : 是我们需要处理的数据
在执行后取消定时任务
@Slf4j | |
public class TimedMassJob implements org.quartz.Job { | |
@SneakyThrows | |
@Override | |
public void execute(JobExecutionContext context) throws JobExecutionException { | |
JobDataMap dataMap = context.getJobDetail().getJobDataMap(); | |
String job=dataMap.getString("data1"); | |
String jobName =job+"Job"; | |
String jobGroupName =job+"JobGroup"; | |
String triggerName =job+"Trigger"; | |
String triggerGroupName =job+"TriggerGroup"; | |
String chapterName =dataMap.getString("data2"); | |
log.info("所有的定时任务:{}",QuartzManager.getTotal().toString()); | |
log.info("执行定时任务时间{},接收到到的数据{}",new Date(),chapterName); | |
log.info("开始销毁:JobName={},JobGroupName={},triggerName={},triggerGroupName={}",jobName,jobGroupName,triggerName,triggerGroupName); | |
QuartzManager.removeJob(jobName,jobGroupName,triggerName,triggerGroupName); | |
log.info("所有的定时任务:{}",QuartzManager.getTotal().toString()); | |
} | |
} |
# Controller 层实现业务接口
在 addJob() 最后有可变长参数来传递参数
@Slf4j | |
@RestController | |
@RequestMapping("/test") | |
public class ScheduleController { | |
/** | |
* 更新 cron | |
* http://127.0.0.1:8090/test/updateCron | |
*/ | |
@GetMapping("/updateCron") | |
public void updateCron() { | |
Date date =new Date(); | |
Date afterDate = new Date(date .getTime() + 60000); | |
QuartzManager.addJob("testJob", "testJobGroup", "testTrigger", "testTriggerGroup", TimedMassJob.class, QuartzCronDateUtils.getCron(afterDate),"test","asdasd"); | |
} | |
public static void main(String[] args) { | |
QuartzManager.removeJob("testJob", "job", "testTrigger", "testTriggerGroup"); | |
} | |
} |
# 相关参数说明
# 定时任务(Job)
定时任务是指需要按照一定的时间规则来执行的任务,比如每天早上 6 点执行一次数据备份操作。在 Quartz 中,一个定时任务由以下几个部分组成:
- Job:定义任务执行的逻辑代码,需要实现 Job 接口并重写 execute 方法。
- JobDetail:封装 Job 对象和任务相关的元数据,包括任务名称、任务组、Job 实现类等信息。
- JobDataMap:存储任务执行所需的参数,可以在 JobDetail 中设置,也可以在触发器中设置。
# 触发器 (Trigger)
触发器是用来触发定时任务执行的,它定义了任务应该在何时执行,如何执行等信息。在 Quartz 中,一个触发器由以下几个部分组成:
- Trigger:定义任务触发的时间规则,如何触发任务等信息。
- TriggerBuilder:用于构建 Trigger 对象,可以设置触发器的名称、触发器组、触发时间、触发规则等信息。
- Cron 表达式:定义触发器的触发时间规则,可以设置年、月、日、周、时、分、秒等。
# 持久化到数据库
配置 quartz.properties
# ThreadPool 中的简单线程池 SimpleThreadPool | |
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool | |
#线程池中线程数量 | |
org.quartz.threadPool.threadCount = 5 | |
#线程的优先级 10 最高 | |
org.quartz.threadPool.threadPriority = 5 | |
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true | |
org.quartz.jobStore.misfireThreshold = 5000 | |
#存储方式使用 JobStoreTX,也就是数据库 | |
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX | |
#数据库中 quartz 表的表名前缀 | |
org.quartz.jobStore.tablePrefix = QRTZ_ | |
#配置数据源 | |
org.quartz.jobStore.dataSource = qzDS | |
org.quartz.dataSource.qzDS.driver = com.mysql.cj.jdbc.Driver | |
org.quartz.dataSource.qzDS.URL = jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=UTF-8 | |
org.quartz.dataSource.qzDS.user = root | |
org.quartz.dataSource.qzDS.password = root | |
org.quartz.dataSource.qzDS.maxConnections = 10 |
超过八小时会出现当使用 Quartz 调度器时,如果遇到连接超时和 wait_timeout 问题.
