本文主要介紹使用SpringBoot的起步依賴和融入SpringBoot數據庫連接的yml配置。
添加maven依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
配置文件
配置可以直接加到 application.yml
進行自動裝配,數據源會自動使用當前項目的數據源配置或者連接池配置。
具體的配置含義可以參照: https://www.w3cschool.cn/quartz_doc/quartz_doc-ml8e2d9m.html
配置值對應 spring.quartz.properties 後面的那些
spring:
quartz:
# 相關屬性配置
properties:
org:
quartz:
scheduler:
instanceName: clusteredScheduler
instanceId: AUTO
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
tablePrefix: QRTZ_
isClustered: true
clusterCheckinInterval: 10000
useProperties: false
# 線程池的參數配置
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: false
# 指定監聽器的類 進行屬性裝配,這裏我添加了一個監聽器的裝配類
plugin:
runningListener:
class: com.netease.core.job.plugin.RunningListenerPlugin
# 自定義屬性,代碼中讀取,用於控制是否開啓監聽
enableRunningLog: true
# 持久化-數據庫方式存儲
job-store-type: jdbc
數據庫建表
使用的是2.2.3版本的 Oracle 建表語句:建表SQL文件
如果使用別的數據庫,可以到GitHub上直接獲取:https://github.com/quartz-scheduler/quartz
鑑於很多人不太會找,我簡單說下建表語句的查找方法:
- 進入GitHub倉庫之後,切換至Tag,找到你對應的版本;
- 進入切換到tag之後,點擊Find file按鈕, 搜索 .sql,根據文件名大概就能判斷哪個是符合你需求的建表語句;
- 或者你知道文件的路徑,可以直接找,例如:2.1.x版本的建表語句一般放在 docs/dbTables 下面,根據裏面的SQL文件名就能找到你要的建表語句;
配置完啓動就可以使用的了。
實際應用代碼
創建定時任務的可選參數,我們以簡單任務和CRON任務爲例,以下DTO字段主要源於 QRTZ_TRIGGERS
、QRTZ_CRON_TRIGGERS
和 QRTZ_SIMPLE_TRIGGERS
這三張表。 根據表結構不難看出,觸發器的基本屬性在 QRTZ_TRIGGERS
中,另外兩張表保存了不同類型觸發器的特有參數。
TriggerDto.java 對應 QRTZ_TRIGGERS
@Getter
@Setter
public class TriggerDto {
/**
* 調度器名稱
*/
private String schedName;
/**
* 觸發器名稱
*/
private String triggerName;
/**
* 觸發器分組
*/
private String triggerGroup;
/**
* Job名稱
*/
private String jobName;
/**
* Job分組
*/
private String jobGroup;
/**
* Job描述
*/
private String description;
/**
* 下次執行時間 毫秒級時間戳
*/
private Long nextFireTime;
/**
* 上次執行時間 毫秒級時間戳
*/
private Long prevFireTime;
/**
* 優先級
*/
private Integer priority;
/**
* 觸發器狀態
*/
private String triggerState;
/**
* 觸發器類型
*/
@NotEmpty
private String triggerType;
/**
* 開始時間 毫秒級時間戳
*/
private Long startTime;
/**
* 結束時間 毫秒級時間戳
*/
private Long endTime;
private String calendarName;
private Integer misfireInstr;
}
TriggerCreateParam.java 包含CRON和SIMPLE任務的參數
@Getter
@Setter
public class TriggerCreateParam extends TriggerDto {
/**
* 實際執行任務類名
*/
@NotEmpty
private String jobClassName;
/**
* CRON表達式 針對CRON任務
*/
private String cronExpression;
/**
* 開始時間
*/
private Date start;
/**
* 結束時間
*/
private Date end;
/**
* 重複次數 針對簡單任務 0表示無限次數
*/
private Integer repeatCount;
/**
* 重複時間間隔 針對簡單任務
*/
private Integer repeatInterval;
private List<JobData> jobDataList;
}
通用的創建方法
/**
* 創建一個定時任務(觸發器)
*
* @param triggerCreateParam 創建參數
* @throws SchedulerException 任務調度異常
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public void createTrigger(TriggerCreateParam triggerCreateParam) throws SchedulerException {
String jobClassName = triggerCreateParam.getJobClassName();
Class forName;
try {
forName = Class.forName(jobClassName);
if (!org.quartz.Job.class.isAssignableFrom(Class.forName(jobClassName))) {
throw new IllegalArgumentException("任務類需要繼承 org.quartz.Job");
}
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("任務類名不存在, 請先正確創建該執行類" + jobClassName);
}
JobBuilder jobBuilder = JobBuilder.newJob(forName)
.withIdentity(triggerCreateParam.getJobName(), triggerCreateParam.getJobGroup())
.withDescription(triggerCreateParam.getDescription());
// 檢查是否有額外的任務參數,並設置Job Data
if (CollectionUtils.isNotEmpty(triggerCreateParam.getJobDataList())) {
JobDataMap data = new JobDataMap();
List<JobData> jobDataList = triggerCreateParam.getJobDataList();
for (JobData jobData : jobDataList) {
data.put(jobData.getName(), jobData.getValue());
}
jobBuilder = jobBuilder.usingJobData(data);
}
JobDetail jobDetail = jobBuilder.build();
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger()
.withIdentity(triggerCreateParam.getTriggerName(), triggerCreateParam.getTriggerGroup()).forJob(jobDetail);
if (triggerCreateParam.getStartTime() != null && triggerCreateParam.getStartTime() > 0) {
triggerBuilder.startAt(new Date(triggerCreateParam.getStartTime()));
}
if (triggerCreateParam.getEndTime() != null && triggerCreateParam.getEndTime() > 0) {
triggerBuilder.endAt(new Date(triggerCreateParam.getEndTime()));
}
ScheduleBuilder scheduleBuilder;
// 根據不同的類型,設置不同參數,構建對應類型的觸發器
if ("CRON".equalsIgnoreCase(triggerCreateParam.getTriggerType())) {
if (StringUtils.isEmpty(triggerCreateParam.getCronExpression())) {
throw new IllegalArgumentException("CRON任務中,CRON表達式不能爲空");
}
scheduleBuilder = CronScheduleBuilder.cronSchedule(triggerCreateParam.getCronExpression());
} else if ("SIMPLE".equalsIgnoreCase(triggerCreateParam.getTriggerType())) {
if (triggerCreateParam.getRepeatInterval() == null) {
throw new IllegalArgumentException("簡單任務中,重複間隔不能爲空");
}
if (triggerCreateParam.getRepeatCount() == null) {
throw new IllegalArgumentException("簡單任務中,重複次數不能爲空");
}
int interval = triggerCreateParam.getRepeatInterval();
int count = triggerCreateParam.getRepeatCount();
if (count < 1) {
scheduleBuilder = SimpleScheduleBuilder.repeatSecondlyForever(interval);
} else {
scheduleBuilder = SimpleScheduleBuilder.repeatSecondlyForTotalCount(count, interval);
}
} else {
throw new IllegalArgumentException("不支持的觸發器類型:" + triggerCreateParam.getTriggerType());
}
Trigger trigger = triggerBuilder.withSchedule(scheduleBuilder).build();
quartzScheduler.scheduleJob(jobDetail, trigger);
}
從上面的創建方法,我們可以看到有個類名的檢查。Quartz的任務實際執行的邏輯代碼,都要繼承 org.quartz.Job, 實現execute方法,該方法就是定時任務觸發時,實際執行的代碼。下面是一個簡單的定時任務執行類:
@Component
public class DemoJob extends Job {
private static final Logger logger = LoggerFactory.getLogger(DemoJob.class);
@Override
public void safeExecute(JobExecutionContext context) {
// 通過該方法,可以獲取到任務定義時傳入的參數,實際對應 QRTZ_TRIGGERS.JOB_DATA
context.getJobDetail().getJobDataMap();
logger.info("-----------------測試Quartz任務--------------------");
// 設置執行結果
context.setResult("咕咕咕咕");
}
}
創建一個簡單任務
TriggerCreateParam createParam = new TriggerCreateParam();
createParam.setJobName("TEST");
createParam.setJobGroup("TEST");
createParam.setTriggerGroup("TEST");
createParam.setTriggerName("TEST");
createParam.setDescription("咕咕咕");
createParam.setTriggerType("SIMPLE");
createParam.setRepeatInterval(10);
createParam.setRepeatCount(5);
myQuartzService.createTrigger(createParam);
執行日誌
2020-06-04 18:11:42.344 INFO 16452 --- [eduler_Worker-1] com.netease.core.job.example.DemoJob : -----------------測試Quartz任務--------------------
2020-06-04 18:11:42.344 INFO 16452 --- [eduler_Worker-1] c.n.c.job.listener.JobRunningListener : Job DemoJobTest.DemoJobTest execution complete at 18:11:42 06/04/2020 and reports: 咕咕咕咕
2020-06-04 18:11:52.336 INFO 16452 --- [eduler_Worker-2] c.n.c.job.listener.JobRunningListener : Job DemoJobTest.DemoJobTest fired (by trigger DemoJobTest.DemoJobTest_trigger) at: 18:11:52 06/04/2020
2020-06-04 18:11:52.336 INFO 16452 --- [eduler_Worker-2] com.netease.core.job.example.DemoJob : -----------------測試Quartz任務--------------------
2020-06-04 18:11:52.336 INFO 16452 --- [eduler_Worker-2] c.n.c.job.listener.JobRunningListener : Job DemoJobTest.DemoJobTest execution complete at 18:11:52 06/04/2020 and reports: 咕咕咕咕
2020-06-04 18:12:02.333 INFO 16452 --- [eduler_Worker-3] c.n.c.job.listener.JobRunningListener : Job DemoJobTest.DemoJobTest fired (by trigger DemoJobTest.DemoJobTest_trigger) at: 18:12:02 06/04/2020
2020-06-04 18:12:02.333 INFO 16452 --- [eduler_Worker-3] com.netease.core.job.example.DemoJob : -----------------測試Quartz任務--------------------
2020-06-04 18:12:02.333 INFO 16452 --- [eduler_Worker-3] c.n.c.job.listener.JobRunningListener : Job DemoJobTest.DemoJobTest execution complete at 18:12:02 06/04/2020 and reports: 咕咕咕咕
2020-06-04 18:12:12.334 INFO 16452 --- [eduler_Worker-4] c.n.c.job.listener.JobRunningListener : Job DemoJobTest.DemoJobTest fired (by trigger DemoJobTest.DemoJobTest_trigger) at: 18:12:12 06/04/2020
2020-06-04 18:12:12.334 INFO 16452 --- [eduler_Worker-4] com.netease.core.job.example.DemoJob : -----------------測試Quartz任務--------------------
2020-06-04 18:12:12.334 INFO 16452 --- [eduler_Worker-4] c.n.c.job.listener.JobRunningListener : Job DemoJobTest.DemoJobTest execution complete at 18:12:12 06/04/2020 and reports: 咕咕咕咕