quartz工具类实现动态配置定时任务
1.封装的quartz工具类
1.1 QuartzManager.java
package com.quartz.scheduler.util;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
public class QuartzManager {
private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();
/**
* @Description: 添加一个定时任务
*
* @param jobName 任务名
* @param jobGroupName 任务组名
* @param triggerName 触发器名
* @param triggerGroupName 触发器组名
* @param jobClass 任务
* @param cron 时间设置,参考quartz说明文档
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void addJob(String jobName, String jobGroupName,
String triggerName, String triggerGroupName, Class jobClass, String cron) {
try {
Scheduler sched = schedulerFactory.getScheduler();
// 任务名,任务组,任务执行类
JobDetail jobDetail= JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
// 触发器
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
// 触发器名,触发器组
triggerBuilder.withIdentity(triggerName, triggerGroupName);
triggerBuilder.startNow();
// 触发器时间设定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
// 创建Trigger对象
CronTrigger trigger = (CronTrigger) triggerBuilder.build();
// 调度容器设置JobDetail和Trigger
sched.scheduleJob(jobDetail, trigger);
// 启动
if (!sched.isShutdown()) {
sched.start();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description: 修改一个任务的触发时间
*
* @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 sched = schedulerFactory.getScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
if (trigger == null) {
return;
}
String oldTime = trigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(cron)) {
/** 方式一 :调用 rescheduleJob 开始 */
// 触发器
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
// 触发器名,触发器组
triggerBuilder.withIdentity(triggerName, triggerGroupName);
triggerBuilder.startNow();
// 触发器时间设定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
// 创建Trigger对象
trigger = (CronTrigger) triggerBuilder.build();
// 方式一 :修改一个任务的触发时间
sched.rescheduleJob(triggerKey, trigger);
/** 方式一 :调用 rescheduleJob 结束 */
/** 方式二:先删除,然后在创建一个新的Job */
//JobDetail jobDetail = sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
//Class<? extends Job> jobClass = jobDetail.getJobClass();
//removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
//addJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, cron);
/** 方式二 :先删除,然后在创建一个新的Job */
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description: 移除一个任务
*
* @param jobName
* @param jobGroupName
* @param triggerName
* @param triggerGroupName
*/
public static void removeJob(String jobName, String jobGroupName,
String triggerName, String triggerGroupName) {
try {
Scheduler sched = schedulerFactory.getScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
sched.pauseTrigger(triggerKey);// 停止触发器
sched.unscheduleJob(triggerKey);// 移除触发器
sched.deleteJob(JobKey.jobKey(jobName, jobGroupName));// 删除任务
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description:启动所有定时任务
*/
public static void startJobs() {
try {
Scheduler sched = schedulerFactory.getScheduler();
sched.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description:关闭所有定时任务
*/
public static void shutdownJobs() {
try {
Scheduler sched = schedulerFactory.getScheduler();
if (!sched.isShutdown()) {
sched.shutdown();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description:暂停某任务
* @param jobName
* @param jobGroupName
*/
public static void pauseJob(String jobName, String jobGroupName) {
try {
Scheduler sched = schedulerFactory.getScheduler();
JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
sched.pauseJob(jobKey);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description:启动某任务
* @param jobName
* @param jobGroupName
*/
public static void resumeJob(String jobName, String jobGroupName) {
try {
Scheduler sched = schedulerFactory.getScheduler();
JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
sched.resumeJob(jobKey);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
2.cron表达式规范
CronExpression类提供了类似unix中的定时任务的表达式—— cron 表达式,可以用来表示复杂的时间组合。如每周一到周五早上八点。
格式: 秒 分 时 日 月 周 [年]
序号 | 字段名 | 是否必填 | 允许填写的值 | 允许的通配符 |
---|---|---|---|---|
1 | 秒 | 是 | 0-59 | , - * / |
2 | 分 | 是 | 0-59 | , - * / |
3 | 小时 | 是 | 0-23 | , - * / |
4 | 日 | 是 | 1-31 | , - * ? / L W |
5 | 月 | 是 | 1-12 or JAN-DEC | , - * / |
6 | 周 | 是 | 1-7 or SUN-SAT | , - * ? / L # |
7 | 年(可选) | 否 | empty 或 1970-2199 | , - * / |
通配符说明:
*
表示所有值. 例如:在分的字段上设置 “*”,表示每一分钟都会触发。
?
表示不指定值。只可以使用在”日“和“周”字段上。使用的场景为不需要关心当前设置这个字段的值。例如:要在每月的10号触发一个操作,但不关心是周几,所以需要周位置的那个字段设置为”?” 具体设置为 0 0 0 10 * ?
-
表示区间。例如 在小时上设置 “10-12”,表示 10,11,12点都会触发。
,
表示指定多个值,例如在周字段上设置 “MON,WED,FRI” 表示周一,周三和周五触发
/
用于递增触发。如在秒上面设置”5/15” 表示从5秒开始,每增15秒触发(5,20,35,50)。 在月字段上设置’1/3’所示每月1号开始,每隔三天触发一次。秒上设置*/5表示从0开始,每5秒。月上设置7/6表示从7月开始,且仅有7月。因为增6后大于12,超出了月份的范围。
L
表示最后的意思。只可以使用在”日“和“周”字段上。在日字段设置上,表示当月的最后一天(依据当前月份,如果是二月还会判断是否是润年)
在周字段上表示星期六,相当于”7”或”SAT”。如果在”L”前加上数字,则表示该数据的最后一个。例如在周字段上设置”6L”这样的格式,则表示“本月最后一个星期五”。”L-3”意思是本月倒数第三天。注意使用L的时候,不要使用范围值或列表,否则会得到不期望得到的结果。
W
表示离指定日期的最近那个工作日(周一至周五). 只可以用在日字段上。例如在日字段上设置”15W”,表示离本月15号最近的那个工作日触发。如果15号正好是周六,则找最近的周五(14号)触发,
如果15号是周未,则找最近的下周一(16号)触发.如果15号正好在工作日(周一至周五),则就在该天触发。如果指定格式为
“1W”,它则表示每月1号往后最近的工作日触发。如果1号正是周六,则将在3号下周一触发。(注,”W”前只能设置具体的数字,不允许区间”-“).
#
序号(表示每月的第几个周几),只可以用在周字段上。例如在周字段上设置”6#3”表示在每月的第三个周六.注意如果指定”#5”,正好第五周没有周六,则不会触发该配置。若在周字段使用了#,那么只可以在周字段上面设置一个表达式,“3#1,6#3”是不允许的。
小提示 | ‘L’和 ‘W’可以一组合使用。如果在日字段上设置”LW”,则表示在本月的最后一个工作日触发 |
---|---|
小提示 | 月和周字段,若使用英文字母是不区分大小写的 MON 与 mon 相同 . |
---|---|
表达式 | 意思 |
---|---|
"0 0 12 * * ?" |
每天中午12点执行 |
"0 15 10 ? * *" |
每天上午10:15执行 |
"0 15 10 * * ?" |
每天上午10:15执行 |
"0 15 10 * * ? *" |
每天上午10:15执行 |
"0 15 10 * * ? 2005" |
2005年里的每天上午10:15执行 |
"0 * 14 * * ?" |
每天从下午两点开始到下午2:59结束的每分钟执行 |
"0 0/5 14 * * ?" |
每天从下午两点开始到下午2:55结束的每5分钟执行 |
"0 0/5 14,18 * * ?" |
每天从下午两点开始到下午2:55结束的每5分钟执行,从下午六点开始到下午6:55结束的每5分钟执行 |
"0 0-5 14 * * ?" |
每天从下午两点开始到下午2:05结束的每分钟执行 |
"0 10,44 14 ? 3 WED" |
3月每周三的下午2:10和下午2:44执行 |
"0 15 10 ? * MON-FRI" |
每个工作日的上午10:15执行 |
"0 15 10 15 * ?" |
每个月15号的上午10:15执行 |
"0 15 10 L * ?" |
每个月最后一天的上午10:15执行 |
"0 15 10 ? * 6L" |
每个月最后一个星期五的早上10:15执行 |
"0 15 10 ? * 6L 2002-2005" |
2002到2005每个月的最后一个星期五的早上10:15执行 |
"0 15 10 ? * 6#3" |
每月第三个星期五的早上10:15执行 |
3.spring+springmvc+jpa+quartz
此例子中可做到动态配置定时任务,并可做到定时操作数据库
3.1 pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yztc</groupId>
<artifactId>quartz_springmvc</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>quartz_springmvc Maven Webapp</name>
<url>http://maven.apache.org</url>
<build>
<finalName>quartz_springmvc</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>
4.12
</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<!--dbcp-->
<dependency>
<groupId&g