文章目錄
- 概述
- Cron表達式的組成
- cron表達式中的問号(?) 的含義
-
- 1、當星期和日期都為*或數字時,報錯
- 2、當星期和日期都為?時,報錯
- 時間格式
- 特殊字元
- Cron 表達式樣例
-
- CronTrigger 樣例 1 – 時鐘從 0 分鐘開始,每 5 分鐘執行一次
- CronTrigger 樣例 2 – 時鐘從 0 分鐘開始,每 5 分鐘執行一次,并且秒鐘是 10(例如 10:00:10 am, 10:05:10 am 等)
- CronTrigger 樣例 3 – 每個周三和周五的 10:30, 11:30, 12:30 和 13:30 執行一次
- CronTrigger 樣例 4 – 每個月 5 日到 20 日,早上 8 點 到 10 點,時鐘從 0 開始,每半小時執行一次。注意,不會在上午 10:00 執行,隻會在 8:00, 8:30, 9:00 和 9:30 執行。
- 建立 CronTrigger
- CronTrigger 錯過觸發機制
- Cron表達式生成器線上網站
- 示例
- 示例源碼
概述
CronTrigger 比 SimpleTrigger 更有用,如果你需要基于日期的概念來觸發任務的話,可以使用 CronTrigger。
使用 CronTrigger,你可以指定以下的這些日期:“每周五中午”,或“每天上午 9:30”,或者“每周一上午 9:00 到 10:00 每 5 分鐘,一月的每個周四和周五”。
雖然如此,就像 SimpleTrigger 一樣,CronTrigger 也可以設定 startTime 和 endTime。
Cron表達式的組成
Cron 表達式用于配置 CornTrigger 執行個體。Cron 表達式是一個字元串,由 7 個子表達式組成,這 7 個部分用空格分隔,它們分别表示:
- 秒
- 分鐘
- 小時
- 日
- 月份
- 星期幾
- 年(可選字段)
Cron Schedule用的了Cron表達式**【秒】【分】【時】【日】【月】【周】【年】**
例如,Cron 表達式
“0 0 12 ? * WED”
表示“每周三下午 12:00:00”。
cron表達式中的問号(?) 的含義
問号(?)的作用是指明該字段‘沒有特定的值’
其實這也很好了解,比如:“0/5 * * 3 * SUN”,既指定了每個月的3号,并且又指定了每個星期天,那麼并不可能存在每個3号都是星期天的可能性,是以,表達式也就不成立了。
cronExpression對日期和星期字段的處理規則是它們必須互斥,即隻能且必須有一個字段有特定的值,另一個字段必須是‘沒有特定的值’;
1、當星期和日期都為*或數字時,報錯
Support for specifying both a day-of-week AND a day-of-month parameter is not implemented.
複制
即兩個字段不能都指明的特定的值,必須互斥。這裡的*和數字是一樣的,如果都指明特定的數字,也是報一樣的錯。
2、當星期和日期都為?時,報錯
'?' can only be specfied for Day-of-Month -OR- Day-of-Week.
複制
即兩個字段不能都‘沒有特定的值’。
時間格式
特殊字元
特殊字元 | 含義 |
---|---|
* | 字元可以用于所有字段,在“分”字段中設為"*"表示"每一分鐘"的含義 |
? | 字元可以用在“日”和“周幾”字段. 它用來指定 ‘不明确的值’. 這在你需要指定這兩個字段中的某一個值而不是另外一個的時候會被用到 |
- | 字元被用來指定一個值的範圍,比如在“小時”字段中設為"10-12"表示"10點到12點" |
, | 字元指定數個值。比如在“周幾”字段中設為"MON,WED,FRI"表示"the days Monday, Wednesday, and Friday" |
/ | 字元用來指定一個值的的增加幅度,比如在“秒”字段中設定為"0/15"表示"第0, 15, 30, 和 45秒"。而 “5/15"則表示"第5, 20, 35, 和 50”. 在’/'前加"*“字元相當于指定從0秒開始. 每個字段都有一系列可以開始或結束的數值。對于“秒”和“分”字段來說,其數值範圍為0到59,對于“小時”字段來說其為0到23, 對于“日”字段來說為0到31, 而對于“月”字段來說為0到11。”/"字段僅僅隻是幫助你在允許的數值範圍内從開始"第n"的值。 是以對于“月”字段來說"7/6"隻是表示7月被開啟而不是“每六個月”, 請注意其中微妙的差别 |
L | 字元可用在“日”和“周幾”這兩個字段。它是"last"的縮寫, 但是在這兩個字段中有不同的含義。例如,“日”字段中的"L"表示"一個月中的最後一天" —— 對于一月就是31号對于二月來說就是28号(非閏年)。而在“周幾”字段中, 它簡單的表示"7" or “SAT”,但是如果在“周幾”字段中使用時跟在某個數字之後, 它表示"該月最後一個星期×" —— 比如"6L"表示"該月最後一個周五"。當使用’L’選項時,指定确定的清單或者範圍非常重要,否則你會被結果搞糊塗的 |
W | 可用于“日”字段。用來指定曆給定日期最近的工作日(周一到周五) 。比如你将“日”字段設為"15W",意為: “離該月15号最近的工作日”。是以如果15号為周六,觸發器會在14号即周五調用。如果15号為周日, 觸發器會在16号也就是周一觸發。如果15号為周二,那麼當天就會觸發。然而如果你将“日”字段設為"1W", 而一号又是周六, 觸發器會于下周一也就是當月的3号觸發,因為它不會越過當月的值的範圍邊界。'W’字元隻能用于“日”字段的值為單獨的一天而不是一系列值的時候 |
LW | 可以組合用于“日”字段表示為’LW’,意為"該月最後一個工作日" |
# | 字元可用于“周幾”字段。該字元表示“該月第幾個周×”,比如"6#3"表示該月第三個周五( 6表示周五而"#3"該月第三個)。再比如: “2#1” = 表示該月第一個周一而 “4#5” = 該月第五個周三。注意如果你指定"#5"該月沒有第五個“周×”,該月是不會觸發的 |
C | 字元可用于“日”和“周幾”字段,它是"calendar"的縮寫。它表示為基于相關的月曆所計算出的值(如果有的話)。如果沒有關聯的月曆, 那它等同于包含全部月曆。“日”字段值為"5C"表示"月曆中的第一天或者5号以後",“周幾”字段值為"1C"則表示"月曆中的第一天或者周日以後" |
Cron 表達式樣例
CronTrigger 樣例 1 – 時鐘從 0 分鐘開始,每 5 分鐘執行一次
0 0/5 * * * ?
複制
CronTrigger 樣例 2 – 時鐘從 0 分鐘開始,每 5 分鐘執行一次,并且秒鐘是 10(例如 10:00:10 am, 10:05:10 am 等)
10 0/5 * * * ?
複制
CronTrigger 樣例 3 – 每個周三和周五的 10:30, 11:30, 12:30 和 13:30 執行一次
0 30 10-13 ? * WED,FRI
複制
CronTrigger 樣例 4 – 每個月 5 日到 20 日,早上 8 點 到 10 點,時鐘從 0 開始,每半小時執行一次。注意,不會在上午 10:00 執行,隻會在 8:00, 8:30, 9:00 和 9:30 執行。
0 0/30 8-9 5,20 * ?
複制
注意,有的時候使用一個單獨的 Trigger 來執行任務将會很複雜,例如“早上 9 點到早上 10 點,每 5 分鐘執行一次,下午 1 點到下午 10 點,每 20 分鐘執行一次”。這樣的話,你可以建立兩個 Trigger,并且讓兩個 Trigger 都關聯到同一個 Job。
建立 CronTrigger
可以使用 TriggerBuilder 來建立 CronTrigger(基于 Trigger 的主要屬性),或使用 CronScheduleBuilder 來建立 CronTrigger(基于 CronTrigger 特殊屬性)為了使用 DSL 風格,需要進行靜态導入:
import static org.quartz.TriggerBuilder.*;
import static org.quartz.CronScheduleBuilder.*;
import static org.quartz.DateBuilder.*:
複制
建立一個 Trigger,并且在每天的上午 8 點到下午 5 點,每隔 1 分鐘執行一次:
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(cronSchedule("0 0/2 8-17 * * ?"))
.forJob("myJob", "group1")
.build();
複制
建立一個 Trigger,并且在每天的上午 10:42 執行一次:
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(dailyAtHourAndMinute(10, 42))
.forJob(myJobKey)
.build();
複制
或
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(cronSchedule("0 42 10 * * ?"))
.forJob(myJobKey)
.build();
複制
建立一個 Trigger,并在每周三上午 10:42 執行,使用設定的時區而非系統預設時區:
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(weeklyOnDayAndHourAndMinute(DateBuilder.WEDNESDAY, 10, 42))
.forJob(myJobKey)
.inTimeZone(TimeZone.getTimeZone("America/Los_Angeles"))
.build();
複制
或
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(cronSchedule("0 42 10 ? * WED"))
.inTimeZone(TimeZone.getTimeZone("America/Los_Angeles"))
.forJob(myJobKey)
.build();
複制
CronTrigger 錯過觸發機制
下面的政策将通知 Quartz 如果發生了錯過觸發将會如何處理(關于錯過觸發的概念可參看 Triggers 詳解)。這些機制以常量形式定義在 CronTrigger 類中(JavaDoc 中較長的描述了它們各自的行為)。
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
MISFIRE_INSTRUCTION_DO_NOTHING
MISFIRE_INSTRUCTION_FIRE_NOW
複制
所有 Trigger 的預設總是使用 Trigger.MISFIRE_INSTRUCTION_SMART_POLICY (智能政策)。對于 CronTrigger 來說,隻能政策就是 MISFIRE_INSTRUCTION_FIRE_NOW。CronTrigger.updateAfterMisfire() 方法的 JavaDoc 詳細解釋了這個行為的細節。
當建立 CronTrigger 的時候,可以通過 CronSchedulerBuilder 指定錯過觸發機制:
trigger = newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(cronSchedule("0 0/2 8-17 * * ?")
.withMisfireHandlingInstructionFireAndProceed())
.forJob("myJob", "group1")
.build();
複制
Cron表達式生成器線上網站
http://www.pdtools.net/tools/becron.jsp
http://cron.qqe2.com/
示例
package com.xgj.quartz.quartzItself.cronTriggerDemo;
import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;
import java.util.Date;
import org.apache.log4j.Logger;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SchedulerMetaData;
import org.quartz.impl.StdSchedulerFactory;
/**
*
*
* @ClassName: CronTriggerExample
*
* @Description: This Example will demonstrate all of the basics of scheduling
* capabilities of Quartz using Cron Triggers.
*
* @author: Mr.Yang
*
* @date: 2017年10月7日 下午10:46:05
*/
public class CronTriggerExample {
public void run() throws Exception {
Logger log = Logger.getLogger(CronTriggerExample.class);
log.info("------- Initializing -------------------");
// First we must get a reference to a scheduler
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
log.info("------- Initialization Complete --------");
log.info("------- Scheduling Jobs ----------------");
// jobs can be scheduled before sched.start() has been called
// job 1 will run every 20 seconds
JobDetail job = newJob(SimpleJob.class).withIdentity("job1", "group1")
.build();
CronTrigger trigger = newTrigger().withIdentity("trigger1", "group1")
.withSchedule(cronSchedule("0/20 * * * * ?")).build();
Date ft = sched.scheduleJob(job, trigger);
log.info(job.getKey() + " has been scheduled to run at: " + ft
+ " and repeat based on expression: "
+ trigger.getCronExpression());
// job 2 will run every other minute (at 15 seconds past the minute)
job = newJob(SimpleJob.class).withIdentity("job2", "group1").build();
trigger = newTrigger().withIdentity("trigger2", "group1")
.withSchedule(cronSchedule("15 0/2 * * * ?")).build();
ft = sched.scheduleJob(job, trigger);
log.info(job.getKey() + " has been scheduled to run at: " + ft
+ " and repeat based on expression: "
+ trigger.getCronExpression());
// job 3 will run every other minute but only between 8am and 5pm
job = newJob(SimpleJob.class).withIdentity("job3", "group1").build();
trigger = newTrigger().withIdentity("trigger3", "group1")
.withSchedule(cronSchedule("0 0/2 8-17 * * ?")).build();
ft = sched.scheduleJob(job, trigger);
log.info(job.getKey() + " has been scheduled to run at: " + ft
+ " and repeat based on expression: "
+ trigger.getCronExpression());
// job 4 will run every three minutes but only between 5pm and 11pm
job = newJob(SimpleJob.class).withIdentity("job4", "group1").build();
trigger = newTrigger().withIdentity("trigger4", "group1")
.withSchedule(cronSchedule("0 0/3 17-23 * * ?")).build();
ft = sched.scheduleJob(job, trigger);
log.info(job.getKey() + " has been scheduled to run at: " + ft
+ " and repeat based on expression: "
+ trigger.getCronExpression());
// job 5 will run at 10am on the 1st and 15th days of the month
job = newJob(SimpleJob.class).withIdentity("job5", "group1").build();
trigger = newTrigger().withIdentity("trigger5", "group1")
.withSchedule(cronSchedule("0 0 10am 1,15 * ?")).build();
ft = sched.scheduleJob(job, trigger);
log.info(job.getKey() + " has been scheduled to run at: " + ft
+ " and repeat based on expression: "
+ trigger.getCronExpression());
// job 6 will run every 30 seconds but only on Weekdays (Monday through
// Friday)
job = newJob(SimpleJob.class).withIdentity("job6", "group1").build();
trigger = newTrigger().withIdentity("trigger6", "group1")
.withSchedule(cronSchedule("0,30 * * ? * MON-FRI")).build();
ft = sched.scheduleJob(job, trigger);
log.info(job.getKey() + " has been scheduled to run at: " + ft
+ " and repeat based on expression: "
+ trigger.getCronExpression());
// job 7 will run every 30 seconds but only on Weekends (Saturday and
// Sunday)
job = newJob(SimpleJob.class).withIdentity("job7", "group1").build();
trigger = newTrigger().withIdentity("trigger7", "group1")
.withSchedule(cronSchedule("0,30 * * ? * SAT,SUN")).build();
ft = sched.scheduleJob(job, trigger);
log.info(job.getKey() + " has been scheduled to run at: " + ft
+ " and repeat based on expression: "
+ trigger.getCronExpression());
log.info("------- Starting Scheduler ----------------");
// All of the jobs have been added to the scheduler, but none of the
// jobs
// will run until the scheduler has been started
sched.start();
log.info("------- Started Scheduler -----------------");
log.info("------- Waiting five minutes... ------------");
try {
// wait five minutes to show jobs
Thread.sleep(300L * 1000L);
// executing...
} catch (Exception e) {
//
}
log.info("------- Shutting Down ---------------------");
sched.shutdown(true);
log.info("------- Shutdown Complete -----------------");
SchedulerMetaData metaData = sched.getMetaData();
log.info("Executed " + metaData.getNumberOfJobsExecuted() + " jobs.");
}
public static void main(String[] args) throws Exception {
CronTriggerExample example = new CronTriggerExample();
example.run();
}
}
複制
/*
* All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
package com.xgj.quartz.quartzItself.cronTriggerDemo;
import java.util.Date;
import org.apache.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
/**
*
* This is just a simple job that gets fired off many times by example 1
*
*
*/
public class SimpleJob implements Job {
private static Logger _log = Logger.getLogger(SimpleJob.class);
/**
* Quartz requires a public empty constructor so that the
* scheduler can instantiate the class whenever it needs.
*/
public SimpleJob() {
}
/**
*
* Called by the {@link org.quartz.Scheduler} when a
* {@link org.quartz.Trigger} fires that is associated with
* the Job.
*
*
* @throws JobExecutionException
* if there is an exception while executing the job.
*/
public void execute(JobExecutionContext context)
throws JobExecutionException {
// This job simply prints out its job name and the
// date and time that it is running
JobKey jobKey = context.getJobDetail().getKey();
_log.info("SimpleJob says: " + jobKey + " executing at " + new Date());
}
}
複制
示例源碼
代碼已托管到Github—> https://github.com/yangshangwei/SpringMaster