Quartz是一个由java编写的开源作业调度框架,简单来说,Quartz就是启动定时任务的框架,像linux系统中的corntab,可以定时启动任务.
Quartz的单独使用
Quartz的使用必须掌握下面三个对象
Scheduler 定时器对象
JobDetail 任务对象
Trigger 触发器对象
SimpleTrigger 简单触发器
CornTrigger任务调度触发器
<dependency>
<groupId>org.quartz-schedulergroupId>
<artifactId>quartzartifactId>
<version>2.3.2version>
dependency>
<dependency>
<groupId>org.quartz-schedulergroupId>
<artifactId>quartz-jobsartifactId>
<version>2.3.2version>
dependency>
/**
* @author codekiller
* @date 2020/6/4 23:31
*/
public class HelloJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//输出当前时间
Date date=new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dataStr = format.format(date);
//工作内容
System.out.println("正在进行数据库的备份工作,备份数据库的时间是:"+dataStr);
}
}
/**
* @author codekiller
* @date 2020/6/4 23:34
*/
public class HelloScheduleDemo {
public static void main(String[] args) throws SchedulerException {
//定时器对象
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
//定义一个工作对象 设置工作名称与组名
JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job41","group1").build();
//定义一个触发器 简单Trigger 设置工作名称与组名 5秒触发一次
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1","group1").startNow().withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5)).build();
//定义一个任务调度的Trigger 设置工作名称与组名 每天的24:00触发一次
//Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1","group1").withSchedule(CronScheduleBuilder.cronSchedule("0 0 0 * * ?")).build();
//设置工作 与触发器
scheduler.scheduleJob(job, trigger);
// and start it off
//开始定时任务
scheduler.start();
}
}
CornTrigger表达式的写法
* * * * * *
分别代表秒、分、时、日、月、周
例子:
0 0 12 ? * 3 每周二中午 12 点执行任务
0 0 0 0 * ? 每月 1 日 0 点执行任务
测试结果
常用的触发器有下面四个
一个quartz简单的触发器。指定从某一个时间开始,以一定的时间间隔(单位是毫秒)执行的任务。
它适合的任务类似于:9:00 开始,每隔1小时,每隔几分钟,每隔几秒钟执行一次。
它的属性有:
SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startAt(startTime).withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(10)
.withRepeatCount(5)
).build();
类似于SimpleTrigger,指定从某一个时间开始,以一定的时间间隔执行的任务。 但是不同的是SimpleTrigger指定的时间间隔为毫秒,没办法指定每隔一个月执行一次(每月的时间间隔不是固定值),而CalendarIntervalTrigger支持的间隔单位有秒,分钟,小时,天,月,年,星期。
相较于SimpleTrigger有两个优势:
它适合的任务类似于:9:00 开始执行,并且以后每周 9:00 执行一次
它的属性有:
// 每两秒执行
CalendarIntervalTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").withSchedule(
CalendarIntervalScheduleBuilder.calendarIntervalSchedule().withInterval(2, DateBuilder.IntervalUnit.SECOND)
).build();
指定每天的某个时间段内,以一定的时间间隔执行任务。并且它可以支持指定星期。
它适合的任务类似于:指定每天9:00 至 18:00 ,每隔70秒执行一次,并且只要周一至周五执行。
它的属性有:
DailyTimeIntervalTrigger trigger = dailyTimeIntervalSchedule()
.startingDailyAt(TimeOfDay.hourAndMinuteOfDay(9, 0)) // 第天9:00开始
.endingDailyAt(TimeOfDay.hourAndMinuteOfDay(16, 0)) // 16:00 结束
.onDaysOfTheWeek(MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY) // 周一至周五执行
.withIntervalInHours(1) // 每间隔1小时执行一次
.withRepeatCount(100) // 最多重复100次(实际执行100+1次)
.build();
DailyTimeIntervalTrigger trigger = dailyTimeIntervalSchedule()
.startingDailyAt(TimeOfDay.hourAndMinuteOfDay(9, 0)) // 第天9:00开始
.endingDailyAfterCount(10) // 每天执行10次,这个方法实际上根据 startTimeOfDay+interval*count 算出 endTimeOfDay
.onDaysOfTheWeek(MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY) // 周一至周五执行
.withIntervalInHours(1) // 每间隔1小时执行一次
.build();
// 每两秒执行
DailyTimeIntervalTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").withSchedule(
DailyTimeIntervalScheduleBuilder.dailyTimeIntervalSchedule().withInterval(2, DateBuilder.IntervalUnit.SECOND)
).build();
适合于更复杂的任务,它支持类型于Linux Cron的语法(并且更强大)。基本上它覆盖了以上三个Trigger的绝大部分能力(但不是全部)
CronTrigger 允许设定非常复杂的触发时间表。然而有时也许不得不使用两个或多个 SimpleTrigger 来满足你的触发需求,这时候你仅仅需要一个CronTrigger 实例就够了。
它的属性只有: Cron表达式,详解点击
// 每两秒执行
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").withSchedule(
CronScheduleBuilder.cronSchedule("/2 * * * * ?")
).build();
org.quartz.NthIncludedDayTrigger 是 Quartz 开发团队最新加入到框架中的一个 Trigger。它设计用于在每一间隔类型的第几天执行 Job。
例如,你要在每个月的 15 号执行开票的 Job,用 NthIncludedDayTrigger 就再合适不过了。Quartz 的 Caldendar 也可与 Trigger 关联以此把周末与节假日考虑进来,并在必要时跳开这些日期。
NthIncludedDayTrigger trigger = new NthIncludedDayTrigger("MyTrigger", Scheduler.DEFAULT_GROUP);
trigger.setN(15);
trigger.setIntervalType(NthIncludedDayTrigger.INTERVAL_TYPE_MONTHLY);
Job执行时,设置了间隔时间,但是有一个并发的过程。
@DisallowConcurrentExecution
注解可以取消并发
@DisallowConcurrentExecution
public class HelloJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//输出当前时间
Date date=new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dataStr = format.format(date);
//工作内容
System.out.println("正在进行数据库的备份工作,备份数据库的时间是:"+dataStr);
}
}
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-quartzartifactId>
dependency>
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS;
CREATE TABLE QRTZ_JOB_DETAILS
(
SCHED_NAME VARCHAR(120) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
JOB_CLASS_NAME VARCHAR(250) NOT NULL,
IS_DURABLE VARCHAR(1) NOT NULL,
IS_NONCONCURRENT VARCHAR(1) NOT NULL,
IS_UPDATE_DATA VARCHAR(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
);
CREATE TABLE QRTZ_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
NEXT_FIRE_TIME BIGINT(13) NULL,
PREV_FIRE_TIME BIGINT(13) NULL,
PRIORITY INTEGER NULL,
TRIGGER_STATE VARCHAR(16) NOT NULL,
TRIGGER_TYPE VARCHAR(8) NOT NULL,
START_TIME BIGINT(13) NOT NULL,
END_TIME BIGINT(13) NULL,
CALENDAR_NAME VARCHAR(200) NULL,
MISFIRE_INSTR SMALLINT(2) NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
);
CREATE TABLE QRTZ_SIMPLE_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
REPEAT_COUNT BIGINT(7) NOT NULL,
REPEAT_INTERVAL BIGINT(12) NOT NULL,
TIMES_TRIGGERED BIGINT(10) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_CRON_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
CRON_EXPRESSION VARCHAR(200) NOT NULL,
TIME_ZONE_ID VARCHAR(80),
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_SIMPROP_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
STR_PROP_1 VARCHAR(512) NULL,
STR_PROP_2 VARCHAR(512) NULL,
STR_PROP_3 VARCHAR(512) NULL,
INT_PROP_1 INT NULL,
INT_PROP_2 INT NULL,
LONG_PROP_1 BIGINT NULL,
LONG_PROP_2 BIGINT NULL,
DEC_PROP_1 NUMERIC(13,4) NULL,
DEC_PROP_2 NUMERIC(13,4) NULL,
BOOL_PROP_1 VARCHAR(1) NULL,
BOOL_PROP_2 VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_BLOB_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
BLOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_CALENDARS
(
SCHED_NAME VARCHAR(120) NOT NULL,
CALENDAR_NAME VARCHAR(200) NOT NULL,
CALENDAR BLOB NOT NULL,
PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
);
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_FIRED_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
ENTRY_ID VARCHAR(95) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
FIRED_TIME BIGINT(13) NOT NULL,
SCHED_TIME BIGINT(13) NOT NULL,
PRIORITY INTEGER NOT NULL,
STATE VARCHAR(16) NOT NULL,
JOB_NAME VARCHAR(200) NULL,
JOB_GROUP VARCHAR(200) NULL,
IS_NONCONCURRENT VARCHAR(1) NULL,
REQUESTS_RECOVERY VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,ENTRY_ID)
);
CREATE TABLE QRTZ_SCHEDULER_STATE
(
SCHED_NAME VARCHAR(120) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
CHECKIN_INTERVAL BIGINT(13) NOT NULL,
PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
);
CREATE TABLE QRTZ_LOCKS
(
SCHED_NAME VARCHAR(120) NOT NULL,
LOCK_NAME VARCHAR(40) NOT NULL,
PRIMARY KEY (SCHED_NAME,LOCK_NAME)
);
commit;
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/manager?characterEncoding=UTF-8&serverTimezone=UTC
driver-class-name: com.mysql.jdbc.Driver
quartz:
# 将任务等保存化到数据库
job-store-type: jdbc
# 程序结束时会等待quartz相关的内容结束
wait-for-jobs-to-complete-on-shutdown: true
# QuartzScheduler启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录
overwrite-existing-jobs: true
# 这里居然是个map,搞得智能提示都没有,佛了
properties:
org:
quartz:
# scheduler相关
scheduler:
# scheduler的实例名
instanceName: scheduler
instanceId: AUTO
# 持久化相关
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# 表示数据库中相关表是QRTZ_开头的
tablePrefix: QRTZ_
useProperties: false
# 线程池相关
threadPool:
class: org.quartz.simpl.SimpleThreadPool
# 线程数
threadCount: 10
# 线程优先级
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true
@DisallowConcurrentExecution
public class Job1 extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("开始执行Job1------"+sdf.format(new Date()));
}
}
--------------------------------------------------
@DisallowConcurrentExecution
public class Job2 extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("开始执行Job2------"+sdf.format(new Date()));
}
}
package top.codekiller.test.quartz.quartz_springboot;
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author codekiller
* @date 2020/6/5 14:40
* @description 注册周期性的定时任务,会被持久化
*/
@Configuration
public class QuartzConfig {
@Bean
public JobDetail job1Detail(){
return JobBuilder.newJob(Job1.class).withIdentity("testJob1","testJob").storeDurably().build();
}
@Bean
public Trigger testQuartzTrigger1() {
//5秒执行一次
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever();
return TriggerBuilder.newTrigger().forJob(job1Detail())
.withIdentity("testJob1","testJob")
.startNow()
.withSchedule(scheduleBuilder)
.build();
}
@Bean
public JobDetail job2Detail() {
return JobBuilder.newJob(Job2.class).withIdentity("testJob2","testJob").storeDurably().build();
}
@Bean
public Trigger testQuartzTrigger2() {
//cron方式,每隔5秒执行一次
return TriggerBuilder.newTrigger().forJob(job2Detail())
.withIdentity("testJob2","testJob")
.startNow()
.withSchedule(CronScheduleBuilder.cronSchedule("*/5 * * * * ?"))
.build();
}
}
package top.codekiller.test.quartz.quartz_springboot;
import com.mchange.util.StringObjectMap;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
/**
* @author codekiller
* @date 2020/6/5 15:28
* @description DES
*/
@DisallowConcurrentExecution
@Slf4j
public class Job3 extends QuartzJobBean {
@Autowired
private Scheduler scheduler;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
JobDetail jobDetail = jobExecutionContext.getJobDetail();
Trigger trigger = jobExecutionContext.getTrigger();
log.info("jobDetail: {}",jobDetail);
log.info("trigger: {}",trigger);
JobDataMap jobDataMap = jobDetail.getJobDataMap();
log.info("username: {};age: {}",jobDataMap.getString("username"),jobDataMap.getInt("age"));
// 编写任务的逻辑
// 执行之后删除任务
try {
// 暂停触发器的计时
scheduler.pauseTrigger(trigger.getKey());
// 移除触发器中的任务
scheduler.unscheduleJob(trigger.getKey());
// 删除任务
scheduler.deleteJob(jobDetail.getKey());
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
package top.codekiller.test.quartz.controller;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import top.codekiller.test.quartz.quartz_springboot.Job3;
import java.time.LocalDateTime;
/**
* @author codekiller
* @date 2020/6/5 16:14
* @description DES
*/
@RestController
public class QuartzController {
@Autowired
private Scheduler scheduler;
@GetMapping("/test")
public ResponseEntity testQuartz() {
//任务的cron表达式
LocalDateTime localDateTime = LocalDateTime.now();
String cronStr = String.format("0/5 %d %d %d %d ? %d", localDateTime.getMinute() + 1, localDateTime.getHour(), localDateTime.getDayOfMonth(), localDateTime.getMonth().getValue(), localDateTime.getYear());
System.out.println(cronStr);
//指定Job
JobDetail jobDetail = JobBuilder.newJob(Job3.class).withIdentity("testJob3", "testJob")
//添加一些参数,执行的时候用
.usingJobData("username", "张三")
.usingJobData("age", 18)
.build();
//触发器
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("testJob3", "testJob")
.withSchedule(CronScheduleBuilder.cronSchedule(cronStr)).build();
try {
scheduler.scheduleJob(jobDetail, cronTrigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
return ResponseEntity.ok(HttpStatus.OK.value());
}
}
字段 | 允许值 | 允许的特殊字符 | ||
---|---|---|---|---|
秒 |
0-59 |
, - * / |
||
分 |
0-59 |
, - * / |
||
小时 |
0-23 |
, - * / |
||
日期 |
1-31 |
, - * / L W C |
||
月份 |
1-12 或者 JAN-DEC |
, - * / |
||
星期 |
1-7 或者 SUN-SAT |
, - * / L C # |
||
年(可选) |
留空, 1970-2099 |
, - * / |
如上面的表达式所示:
** * **字符被用来指定所有的值。如:”*“在分钟的字段域里表示“每分钟”。
**-**字符被用来指定一个范围。如:“10-12”在小时域意味着“10点、11点、12点”。
**,**字符被用来指定另外的值。如:“MON,WED,FRI”在星期域里表示”星期一、星期三、星期五”. 在Minutes域使用5,20,则意味着在5和20分每分钟触发一次。
/:表示起始时间开始触发,然后每隔固定时间触发一次。例如在Minutes域使用5/20,则意味着5分钟触发一次,而25,45等分别触发一次.
**?*只能用在DayofMonth和DayofWeek两个域。它也匹配域的任意值,但实际不会。因为DayofMonth和DayofWeek会相互影响。例如想在每月的20日触发调度,不管20日到底是星期几,则只能使用如下写法: 13 13 15 20 * ?, 其中最后一位只能用?,而不能使用,如果使用*表示不管星期几都会触发,实际上并不是这样。
L字符指定在月或者星期中的某天(最后一天)。即“Last ”的缩写。但是在星期和月中“L”表示不同的意思,如:在月子段中“L”指月份的最后一天-1月31日,2月28日,如果在星期字段中则简单的表示为“7”或者“SAT”。如果在星期字段中在某个value值得后面,则表示“某月的最后一个星期value”,如“6L”表示某月的最后一个星期五。
W表示有效工作日(周一到周五),只能出现在DayofMonth域,系统将在离指定日期的最近的有效工作日触发事件。例如:在 DayofMonth使用5W,如果5日是星期六,则将在最近的工作日:星期五,即4日触发。如果5日是星期天,则在6日(周一)触发;如果5日在星期一到星期五中的一天,则就在5日触发。另外一点,W的最近寻找不会跨过月份 。
LW:这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五。
**#**字符只能用在星期字段,该字段指定了第几个星期value在某月中.例如在4#2,表示某月的第二个星期三。
每一个元素都可以显式地规定一个值(如6),一个区间(如9-12),一个列表(如9,11,13)或一个通配符(如*)。“月份中的日期”和“星期中的日期”这两个元素是互斥的,因此应该通过设置一个问号(?)来表明你不想设置的那个字段。表7.1中显示了一些cron表达式的例子和它们的意义:
表达式 | 意义 | |
---|---|---|
"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点到下午2:59期间的每1分钟触发 |
|
"0 0/5 14 * * ?" |
在每天下午2点到下午2:55期间的每5分钟触发 |
|
"0 0/5 14,18 * * ?" |
在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发 |
|
"0 0-5 14 * * ?" |
在每天下午2点到下午2:05期间的每1分钟触发 |
|
"0 10,44 14 ? 3 WED" |
每年三月的星期三的下午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触发 |
参考:https://segmentfault.com/a/1190000022552084