本文已参与「新人创作礼」活动,一起开启掘金创作之路。
Trigger介绍
graph TD
A[TriggerBuilder] -->|创建| B(Trigger)
C[AbstractTrigger] --> B
C1[DailyTimeIntervalTriggerImpl] --> C
C2[CalendarIntervalTriggerImpl] --> C
C3[SimpleTriggerImpl] --> C
C4[CronTriggerImpl] --> C
Quartz有一些不同的触发类型,常用的时SimpleTrigger和CronTrigger。
-
JobKey 表示Job实例的标识,触发器被出发时,该指定的Job实例会被执行。
-
startTime 表示触发器的时间表,第一次开始被触发的时间,它的数据类型时java.util.Date,要配合startAt()方法使用。
-
endTime 指定触发器终止被触发的时间,它的数据类型是java.util.Date,要配合endAt()方法使用。
案例: HelloJobTrigger.java
// 定义任务类
public class HelloJobTrigger implements Job{
@Override
public void execute(JobExecutionContext context) throws JobExecutionException{
// 定义时间
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = dateFormat.format(date);
// 定义工作任务内容
System.out.println("进行数据库备份操作,当前任务执行的时间:"+dateString);
// 获取jobKey,startTime,endTime
Trigger trigger = context.getTrigger();
System.out.println("jobKey的标识:"+trigger.getJobKey().getName()+",jobkey的组名"+trigger.getJobKey().getGroup());
System.out.println("任务的开始时间:"+trigger.getStartTime+",任务的结束时间"+trigger.getEndTime());
}
}
HelloSchedulerDemoTrigger.java
public class HelloSchedulerDemoTrigger{
public static void main(Stringp[] args) throws Exception{
//1:从工厂中获取任务调度的实例
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 定义日期
Date startDate = new Date();
// 启动任务,任务在当前时间3秒后执行
startDate.setTime(startDate.getTime()+3000);
// 定义日期
Date endDate = new Date();
// 启动任务,任务在当前时间10秒后停止
endDate.setTime(endDate.getTime()+10000);
//2:定义一个任务调度实例,将该实例与HelloJob绑定,任务类需要实现Job接口
JobDetail job = JobBuilder.newJob(HelloJobTrigger.class)
.withIdentity("job1", "group1") //定义该实例唯一标识
.build();
//3:定义触发器,马上执行,然后每5秒重复执行一次
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1") // 定义该实例唯一标识
.startAt(startDate)
.endAt(endDate)
.withScheduler(SimpleSchedulerBuilder.simpleScheduler() .repeatSecondlyForever(5)) // 每5秒执行一次
.build();
//4:使用触发器调度任务的执行
scheduler.schedulerJob(job, trigger);
//5:开启
scheduler.start();
//6:关闭
scheduler.shutdown();
}
}
SimpleTrigger触发器
SimpleTrigger对于设定和使用是最为简单的一种QuartzTrigger。
它是为那种在特定的日期/时间启动,且以一个可能的间隔时间重复执行n次的Job所设计的。
案例一:表示在一个指定的时间段内,执行一次作业任务;
HelloJobSimpleTrigger.java
// 定义任务类
public class HelloJobSimpleTrigger implements Job{
@Override
public void execute(JobExecutionContext context) throws JobExecutionException{
// 定义时间
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = dateFormat.format(date);
// 定义工作任务内容
System.out.println("进行数据库备份操作,当前任务执行的时间:"+dateString);
}
}
HelloSchedulerDemoSimpleTrigger.java
public class HelloSchedulerDemoSimpleTrigger{
public static void main(Stringp[] args) throws Exception{
//1:从工厂中获取任务调度的实例
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 设置任务的开始时间
Date startDate = new Date();
// 启动任务,任务在当前时间3秒后执行
startDate.setTime(startDate.getTime()+3000);
//2:定义一个任务调度实例,将该实例与HelloJob绑定,任务类需要实现Job接口
JobDetail job = JobBuilder.newJob(HelloJobSimpleTrigger.class)
.withIdentity("job1", "group1") //定义该实例唯一标识
.build();
//3:定义触发器,马上执行,然后每5秒重复执行一次
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1") // 定义该实例唯一标识
.startAt(startDate)
.build();
//4:使用触发器调度任务的执行
scheduler.schedulerJob(job, trigger);
//5:开启
scheduler.start();
//6:关闭
scheduler.shutdown();
}
}
案例二:或在指定的时间间隔内多次执行作业任务
修改HelloSchedulerDemoSimpleTrigger.java
// 3:定义触发器,马上执行,然后每5秒重复执行一次
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1") // 定义该实例唯一标识
.startAt(startDate)
.withSchedule(SimpleScheduleBuilder.simpleSchedule().repeateSecondlyForever(5)
.withRepeatCount(3)) // withRepeatCount()方法设定执行次数,参数是int类型,默认值是0
.build();
案例三:指定任务的结束时间(结束时间优先级高于重复次数)
修改HelloSchedulerDemoSimpleTrigger.java
// 定义日期
Date endDate = new Date();
// 启动任务,任务在当前时间10秒后停止
endDate.setTime(endDate.getTime()+10000);
//2:定义一个任务调度实例,将该实例与HelloJob绑定,任务类需要实现Job接口
JobDetail job = JobBuilder.newJob(HelloJobSimpleTrigger.class)
.withIdentity("job1", "group1") //定义该实例唯一标识
.build();
//3:定义触发器,马上执行,然后每5秒重复执行一次
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1") // 定义该实例唯一标识
.startAt(startDate)
.endAt(endDate)
.withScheduler(SimpleScheduleBuilder.simpleSchedule().repeateSecondlyForever(5)
.withRepeatCount(3)) // 每5秒执行一次
.build();
注意:
- SimpleTrigger的属性有:开始时间、结束时间、重复次数、重复的时间间隔
- 重复次数属性的值可以为0,正整数、常量 SimpleTrigger.REPEAT_INDEFINITELT(值为-1,反复执行;相当于不设该属性)
- 重复的时间间隔属性值必须为大于0或长整形的正整数,以毫秒作为时间的那位,当重复的时间间隔为0时,意味着与Trigger同时触发执行
- 如果有指定结束时间属性值,则结束时间属性优先于重复次数属性,这样的好处在于:当我们需要创建一个每间隔10秒钟触发一次直到指定的结束时间的Trigger,而无需取计算从开始到结束的所重复的次数,我们只需简单的指定结束时间和使用REPEAT_INDEFINITELY作为重复次数的属性值即可。
CronTrigger触发器
如果需要像日历那样按日程来触发任务,而不是像SimpleTrigger那样每隔特定的间隔时间触发,CronTrigger通常比SimpleTrigger更有用,因为他是基于日历的作业调度器。
使用CronTrigger,你可以指定诸如“每个周五中午”,或者“每个工作日的9:30”或者“从每个周一、周三、周五的上午9:00到10:00之间每间隔五分钟”这样日程安排来触发。甚至,像SimpleTrigger一样,CronTrigger也有一个startTime以指定日期从什么时候开始,也有一个(可选的)endTime以指定何时日程不再继续。
CronExpression —— Cron表达式
Cron表达式被用来配置CronTrigger实例。Cron表达式是一个由7个子表达式组成的字符串。每个子表达式都描述了一个单独的日程细节。这些子表达式用空格分隔,分别表示:
- Seconds 秒
- Minutes 分钟
- Hours 小时
- Day-of-Month 月中的天
- Month 月
- Day-of-Week 周中的天
- Year(optional field)年(可选的域)
取值:
| 字段 | 是否必填 | 允许值 | 运行的特殊字符 |
|---|---|---|---|
| 秒 | 是 | 0-59 | , - * / |
| 分 | 是 | 0-59 | , - * / |
| 小时 | 是 | 0-23 | , - * / |
| 日 | 是 | 1-31 | , - * / ? L W C |
| 月 | 是 | 1-12 或 JAN-DEC | , - * / |
| 周 | 是 | 1-7 或 SUN-SAT(1=星期天) | , - * / ? L C # |
| 年 | 否 | 不填写 或 1970-2009 | , - * / |
| 特殊符号 | 含义 |
|---|---|
| * | 用来表示域中“每个”可能的值。因此在“Month”域中的 * 表示每个月,而在 Day-of-Week 域中表示的 * 则表示“周中的每一天” |
| ? | 表示不指定值,使用的场景为不需要关系当前设置这个字段的值。因此“月份中的日期”和“星期中的日期”这两个元素是互斥的,因此应该通过设置一个问号 (?) 来表明不设置的那个字段 |
| - | 表示区间,例如在小时商设置10-12,表示10、11、12点都会触发 |
| , | 表示指定多个值,例如在周字段上设置“MON, WED, FRI”,表示周一、周三、周五触发 |
| / | 表示值的增量,例如如果分钟域中放入“0/15”,它表示“每隔15分钟,从0开始”,如果在分钟域中使用“3/20”,则表示“小时中每隔20分钟,从3分钟开始”或者另外相同的形式就是“3,23,43” |
| L | 可以在day-of-month、day-of-week中使用,这个字符是“last”的简写,但是在两个域中的意义不同。例如:在day-of-month域中“L”表示这个月的最后一天;造day-of-week中,表示“7”或“SAT”。但是如果在day-of-week域中,这个字符跟在别的值后面,则表示“当月的最后的周XXX”,例如:“6L”或者“FRIL”都表示本月的最后一个周五。当使用“L”选项时,最重要的时不要指定列表或者值范围,否则会导致混乱 |
| W | 用来指定距离给定日最接近的周几(在day-of-week域中指定),例如:如果为day-of-month域指定为“15w”,则表示“距离月中15号最近的周几” |
| # | 表示月中国的第几个周几,例如:day-of-week 域中的“6#3”或者“FRI#3”表示“月中第三个周五” |
案例: HelloJobCronTrigger.java
// 定义任务类
public class HelloJobCronTrigger implements Job{
@Override
public void execute(JobExecutionContext context) throws JobExecutionException{
// 定义时间
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = dateFormat.format(date);
// 定义工作任务内容
System.out.println("进行数据库备份操作,当前任务执行的时间:"+dateString);
}
}
HelloSchedulerDemoCronTrigger.java
public class HelloSchedulerDemoCronTrigger{
public static void main(Stringp[] args) throws Exception{
//1:从工厂中获取任务调度的实例
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 设置任务的开始时间
Date startDate = new Date();
// 启动任务,任务在当前时间3秒后执行
startDate.setTime(startDate.getTime()+3000);
// 设置任务的开始时间
Date endDate = new Date();
// 启动任务,任务在当前时间10秒后结束
endDate.setTime(endDate.getTime()+10000);
//2:定义一个任务调度实例,将该实例与HelloJob绑定,任务类需要实现Job接口
JobDetail job = JobBuilder.newJob(HelloJobSimpleTrigger.class)
.withIdentity("job1", "group1") //定义该实例唯一标识
.build();
//3:定义触发器,马上执行,然后每5秒重复执行一次
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1") // 定义该实例唯一标识
//.startAt(startDate)
//.endAt(endDate)
.withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")) // 日历 每隔5秒执行一次
.build();
//4:使用触发器调度任务的执行
scheduler.schedulerJob(job, trigger);
//5:开启
scheduler.start();
//6:关闭
scheduler.shutdown();
}
}
提示:
- L和W可以一起用。(企业可用在工资计算)
- #可表示月中第几个周几。(企业可用在计算母亲节、父亲节)
- 周字段英文字母不区分大小写,例如MON==mon
- 利用工具,在线生成