绿色健康小清新

耐得住寂寞,守得住繁华

Quartz

什么是Quartz

Quartz是一个由java编写的开源作业调度框架,简单来说,Quartz就是启动定时任务的框架,像linux系统中的corntab,可以定时启动任务.
Quartz的单独使用

Quartz的使用必须掌握下面三个对象

  • Scheduler 定时器对象

  • JobDetail 任务对象

  • Trigger 触发器对象

    SimpleTrigger 简单触发器
    CornTrigger任务调度触发器

使用案列

导入Maven依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz-jobs -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.3.2</version>
</dependency>

Job

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @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);
}
}

测试调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @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 点执行任务
测试结果

各种触发器

常用的触发器有下面四个

  • SimpleTrigger:简单的触发器
  • CalendarIntervalTrigger:日历触发器
  • CronTrigger:Cron表达式触发器
  • DailyTimeIntervalTrigger:日期触发器

SimpleTrigger

一个quartz简单的触发器。指定从某一个时间开始,以一定的时间间隔(单位是毫秒)执行的任务。

它适合的任务类似于:9:00 开始,每隔1小时,每隔几分钟,每隔几秒钟执行一次。

它的属性有:

  • repeatInterval:重复间隔
  • repeatCount:重复次数。实际执行次数是 repeatCount+1。因为在startTime的时候一定会执行一次。
1
2
3
4
SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startAt(startTime).withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(10)
.withRepeatCount(5)
).build();

CalanderInteervalTrigger

类似于SimpleTrigger,指定从某一个时间开始,以一定的时间间隔执行的任务。 但是不同的是SimpleTrigger指定的时间间隔为毫秒,没办法指定每隔一个月执行一次(每月的时间间隔不是固定值),而CalendarIntervalTrigger支持的间隔单位有秒,分钟,小时,天,月,年,星期。

相较于SimpleTrigger有两个优势:

  • 1、更方便,比如每隔1小时执行,你不用自己去计算1小时等于多少毫秒。
  • 2、支持不是固定长度的间隔,比如间隔为月和年。但劣势是精度只能到秒。

它适合的任务类似于:9:00 开始执行,并且以后每周 9:00 执行一次

它的属性有:

  • interval:执行间隔
  • intervalUnit:执行间隔的单位(秒,分钟,小时,天,月,年,星期)
1
2
3
4
// 每两秒执行
CalendarIntervalTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").withSchedule(
CalendarIntervalScheduleBuilder.calendarIntervalSchedule().withInterval(2, DateBuilder.IntervalUnit.SECOND)
).build();

DatlyTimeIntervalTrigger

指定每天的某个时间段内,以一定的时间间隔执行任务。并且它可以支持指定星期。

它适合的任务类似于:指定每天9:00 至 18:00 ,每隔70秒执行一次,并且只要周一至周五执行。

它的属性有:

  • startTimeOfDay:每天开始时间
  • endTimeOfDay:每天结束时间
  • daysOfWeek:需要执行的星期
  • interval:执行间隔
  • intervalUnit:执行间隔的单位(秒,分钟,小时,天,月,年,星期)
  • repeatCount:重复次数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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();

CronTrigger

适合于更复杂的任务,它支持类型于Linux Cron的语法(并且更强大)。基本上它覆盖了以上三个Trigger的绝大部分能力(但不是全部)

CronTrigger 允许设定非常复杂的触发时间表。然而有时也许不得不使用两个或多个 SimpleTrigger 来满足你的触发需求,这时候你仅仅需要一个CronTrigger 实例就够了。

它的属性只有: Cron表达式,详解点击

1
2
3
4
 // 每两秒执行
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").withSchedule(
CronScheduleBuilder.cronSchedule("/2 * * * * ?")
).build();

NthIncludedDayTrigger

org.quartz.NthIncludedDayTrigger 是 Quartz 开发团队最新加入到框架中的一个 Trigger。它设计用于在每一间隔类型的第几天执行 Job。

例如,你要在每个月的 15 号执行开票的 Job,用 NthIncludedDayTrigger 就再合适不过了。Quartz 的 Caldendar 也可与 Trigger 关联以此把周末与节假日考虑进来,并在必要时跳开这些日期。

1
2
3
NthIncludedDayTrigger trigger = new NthIncludedDayTrigger("MyTrigger", Scheduler.DEFAULT_GROUP);
trigger.setN(15);
trigger.setIntervalType(NthIncludedDayTrigger.INTERVAL_TYPE_MONTHLY);

Job并发控制

Job执行时,设置了间隔时间,但是有一个并发的过程。

@DisallowConcurrentExecution注解可以取消并发

1
2
3
4
5
6
7
8
9
10
11
12
13
@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);
}
}

SpringBoot整合Quartz

引入依赖

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

建表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160

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;

配置application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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

周期性的定时任务

job类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@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()));
}
}

注册定时任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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();
}
}

结果

无周期性的定时任务

job类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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();
}
}
}

注册定时任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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());
}
}

结果

执行一次后没有删除的结果

执行一次后删除的结果

在这里插入图片描述

Cron表达式详解

字段允许值允许的特殊字符
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触发
-------------本文结束感谢您的阅读-------------
六经蕴籍胸中久,一剑十年磨在手

欢迎关注我的其它发布渠道