Quartz 使用記錄


Quartz 使用記錄

官網

https://www.quartz-scheduler.org/

參考文檔

什么是 Quartz?

官方描述:

Quartz is a richly featured, open source job scheduling library that can be integrated within virtually any Java application - from the smallest stand-alone application to the largest e-commerce system. Quartz can be used to create simple or complex schedules for executing tens, hundreds, or even tens-of-thousands of jobs; jobs whose tasks are defined as standard Java components that may execute virtually anything you may program them to do. The Quartz Scheduler includes many enterprise-class features, such as support for JTA transactions and clustering.

翻譯:
Quartz 是一個有豐富特性,開源任務調度庫,能和任意(從單個小應用到大型系統.) Java 應用集成.Quartz 用於創建簡單或者混合 調度器用於執行數以千計的任務.Quartz Scheduler 包含了很多企業級特性,例如支持 JTA.

單例使用

1.下載 Jar 包

下載地址 :https://www.quartz-scheduler.org/downloads/

或者 引入pom 依賴:

<dependency>
	<groupId>org.quartz-scheduler</groupId>
	<artifactId>quartz</artifactId>
	<version>2.3.0</version>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-api</artifactId>
	<version>1.7.32</version>
</dependency>
<!-- 日志簡單實現 -->
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-simple</artifactId>
	<version>1.7.32</version>
	<scope>compile</scope>
</dependency>

2. 將解壓后lib文件夾下的 quartz-2.3.0-SNAPSHOT.jar 放於 Java 工程中

需下載 slf4j-simple.jar 包,否則使用SLF4j打印日志會報錯:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

3. 配置 quartz.properties

在 classpath 添加 quartz.properties 文件,添加配置信息:

# 調度器名字
org.quartz.scheduler.instanceName = black-scheduler
# 線程池大小
org.quartz.threadPool.threadCount = 3
# 任務存儲方式(RAMJobStore : 內存存儲)
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

更詳細配置參見 https://www.quartz-scheduler.org/documentation/quartz-2.3.0/configuration

4.編寫HelloJob.java任務類

package org.black.demo.quartz;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloJob implements Job{
	
	private static final Logger LOGGER =  LoggerFactory.getLogger(HelloJob.class);
	
	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		LOGGER.info("任務明細:{}", context.getJobDetail());
		LOGGER.info("激活的實例ID{}",context.getFireInstanceId());
		Date d =context.getFireTime();
		SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		LOGGER.info("調度器:{}",context.getScheduler());
		LOGGER.info("調度器激活時間:{}",f.format(context.getScheduledFireTime()));
		if(context.getPreviousFireTime() != null) {
			LOGGER.info("上次調用時間:{}",f.format(context.getPreviousFireTime()));
		}
		LOGGER.info("下次調用時間:{}",f.format(context.getNextFireTime()));
		LOGGER.info("觸發器:{}",context.getTrigger());
		LOGGER.info("觸發時間:{}", f.format(d));
		LOGGER.info("job 實例:{}", context.getJobInstance());
		LOGGER.info("job 運行時長:{}s", context.getJobRunTime());
		LOGGER.info("Job 設置的返回結果:{}",context.getResult());
		LOGGER.info("MergedJobDataMap:{}", context.getMergedJobDataMap());
		// 
//		LOGGER.info("恢復任務時對應的觸發器key:{}",context.getRecoveringTriggerKey());
		LOGGER.info("重復激活次數:{}",context.getRefireCount());

		LocalDateTime date = LocalDateTime.now();
		String curDateTime = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
		LOGGER.info("時間:{},當前線程:{} - 執行 HelloJob 任務",curDateTime,Thread.currentThread().getName() );
	}
}

5.編寫 QuartzScheduleDemo 測試類

package org.black.demo.quartz;

import java.util.Date;

import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Quartz 示例
 * 
 * @author lihw
 * @date 2021-12-27 17:48:011
 */
public class QuartzScheduleDemo {

	private static final Logger LOGGER =  LoggerFactory.getLogger(QuartzScheduleDemo.class);

	public static void main(String[] args) {
		try {
			// 從工廠類獲取調度器示例
			Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
			// 啟動調度器
			scheduler.start();

			// 定義一個Job 綁定到 HelloJob.class
			JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();

			// 定義一個觸發器,每 4s 執行一次任務
			Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow()
					.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(4).repeatForever())
					.build();

			// 調度器調度任務
			Date date = scheduler.scheduleJob(job, trigger);
			LOGGER.info("Quartz 調度器啟動時間:{}",date);
			// 調用shutdown()方法關閉調度器,否則任務一直在運行
//			scheduler.shutdown();

		} catch (SchedulerException e) {
			e.printStackTrace();
		}
	}
}

6.測試

測試結果:

[main] INFO org.quartz.impl.StdSchedulerFactory - Using default implementation for ThreadExecutor
[main] INFO org.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
[main] INFO org.quartz.core.QuartzScheduler - Quartz Scheduler v.2.3.0 created.
[main] INFO org.quartz.simpl.RAMJobStore - RAMJobStore initialized.
[main] INFO org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.3.0) 'black-schedule' with instanceId 'NON_CLUSTERED'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 3 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.

[main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'black-schedule' initialized from default resource file in Quartz package: 'quartz.properties'
[main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.3.0
[main] INFO org.quartz.core.QuartzScheduler - Scheduler black-schedule_$_NON_CLUSTERED started.
[main] INFO org.black.demo.quartz.QuartzScheduleDemo - Quartz 調度器啟動時間:Tue Dec 28 11:51:03 CST 2021
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 任務明細:JobDetail 'group1.job1':  jobClass: 'org.black.demo.quartz.HelloJob concurrentExectionDisallowed: false persistJobDataAfterExecution: false isDurable: false requestsRecovers: false
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 激活的實例ID1640663463495
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 調度器:org.quartz.impl.StdScheduler@4a5fecdf
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 調度器激活時間:2021-12-28 11:51:03
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 下次調用時間:2021-12-28 11:51:07
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 觸發器:Trigger 'group1.trigger1':  triggerClass: 'org.quartz.impl.triggers.SimpleTriggerImpl calendar: 'null' misfireInstruction: 0 nextFireTime: Tue Dec 28 11:51:07 CST 2021
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 觸發時間:2021-12-28 11:51:03
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - job 實例:org.black.demo.quartz.HelloJob@4dab129f
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - job 運行時長:-1s
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - Job 設置的返回結果:null
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - MergedJobDataMap:org.quartz.JobDataMap@0
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 重復激活次數:0
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 時間:2021-12-28 11:51:03,當前線程:black-schedule_Worker-1 - 執行 HelloJob 任務
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 任務明細:JobDetail 'group1.job1':  jobClass: 'org.black.demo.quartz.HelloJob concurrentExectionDisallowed: false persistJobDataAfterExecution: false isDurable: false requestsRecovers: false
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 激活的實例ID1640663463496
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 調度器:org.quartz.impl.StdScheduler@4a5fecdf
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 調度器激活時間:2021-12-28 11:51:07
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 上次調用時間:2021-12-28 11:51:03
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 下次調用時間:2021-12-28 11:51:11
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 觸發器:Trigger 'group1.trigger1':  triggerClass: 'org.quartz.impl.triggers.SimpleTriggerImpl calendar: 'null' misfireInstruction: 0 nextFireTime: Tue Dec 28 11:51:11 CST 2021
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 觸發時間:2021-12-28 11:51:07
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - job 實例:org.black.demo.quartz.HelloJob@5a318665
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - job 運行時長:-1s
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - Job 設置的返回結果:null
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - MergedJobDataMap:org.quartz.JobDataMap@0
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 重復激活次數:0
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 時間:2021-12-28 11:51:07,當前線程:black-schedule_Worker-2 - 執行 HelloJob 任務

Cron 表達式觸發器

package org.black.demo.quartz;

import java.util.Date;

import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Quartz 示例
 * 
 * @author lihw
 * @date 2021-12-27 17:48:011
 */
public class QuartzScheduleCronTriggerDemo {

	private static final Logger LOGGER =  LoggerFactory.getLogger(QuartzScheduleCronTriggerDemo.class);

	public static void main(String[] args) {
		try {
			// 從工廠類獲取調度器示例
			Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
			// 啟動調度器
			scheduler.start();

			// 定義一個Job 綁定到 HelloJob.class
			JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();

			// 定義一個觸發器,每 10s 執行一次任務
			Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow()
					// cron 表達式: 秒 分 時 日 月 周 年
					.withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ? *"))
					.build();

			// 調度器調度任務
			Date date = scheduler.scheduleJob(job, trigger);
			LOGGER.info("Quartz 調度器啟動時間:{}",date);
			// 調用shutdown()方法關閉調度器,否則任務一直在運行
//			scheduler.shutdown();

		} catch (SchedulerException e) {
			e.printStackTrace();
		}
	}
}

withSchedule 方法可以設置不同的觸發器類型.CronScheduleBuilder 繼承自 ScheduleBuilder,ScheduleBuilder 的子類一共有4個,也就是可以設置 4中類型的觸發器.

Calendar 觸發器

package org.black.demo.quartz;

import java.util.Date;

import org.quartz.CalendarIntervalScheduleBuilder;
import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Quartz Calendar 觸發器示例
 * 
 * @author lihw
 * @date 2021-12-27 17:48:011
 */
public class QuartzScheduleCalendarTriggerDemo {

	private static final Logger LOGGER =  LoggerFactory.getLogger(QuartzScheduleCalendarTriggerDemo.class);

	public static void main(String[] args) {
		try {
			// 從工廠類獲取調度器示例
			Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
			// 啟動調度器
			scheduler.start();

			// 定義一個Job 綁定到 HelloJob.class
			JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();

			// 定義一個觸發器,每 10s 執行一次任務
			Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow()
					.withSchedule(CalendarIntervalScheduleBuilder.calendarIntervalSchedule().withIntervalInSeconds(10))
					.build();
		
			// 調度器調度任務
			Date date = scheduler.scheduleJob(job, trigger);
			LOGGER.info("Quartz 調度器啟動時間:{}",date);
			// 調用shutdown()方法關閉調度器,否則任務一直在運行
//			scheduler.shutdown();

		} catch (SchedulerException e) {
			e.printStackTrace();
		}
	}
}

Daily Time 觸發器

package org.black.demo.quartz;

import java.util.Date;

import org.quartz.DailyTimeIntervalScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TimeOfDay;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Quartz daily time 觸發器示例
 * 
 * @author lihw
 * @date 2021-12-27 17:48:011
 */
public class QuartzScheduleDailyTimeTriggerDemo {

	private static final Logger LOGGER = LoggerFactory.getLogger(QuartzScheduleDailyTimeTriggerDemo.class);

	public static void main(String[] args) {
		try {
			// 從工廠類獲取調度器示例
			Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
			// 啟動調度器
			scheduler.start();

			// 定義一個Job 綁定到 HelloJob.class
			JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();

			// 定義一個觸發器,每 10s 執行一次任務,到 11點27分停止觸發
			Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow()
					.withSchedule(DailyTimeIntervalScheduleBuilder.dailyTimeIntervalSchedule().withIntervalInSeconds(10)
							.endingDailyAt(TimeOfDay.hourAndMinuteOfDay(11, 27)))
					.build();
			// 調度器調度任務
			Date date = scheduler.scheduleJob(job, trigger);
			LOGGER.info("Quartz 調度器啟動時間:{}", date);
			// 調用shutdown()方法關閉調度器,否則任務一直在運行
//			scheduler.shutdown();
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
	}
}


JDBC JobStore

上邊的示例都是存儲在內存中,這里展示了如何存儲在數據庫中.

1. 執行建表語句

數據庫初始化腳本在quartz-2.3.0.jar的/org/quartz/impl/jdbcjobstore/包下.我這里使用的是mysql 數據庫,選擇tables_mysql_innodb.sql 腳本執行.腳本內容如下:


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(190) NOT NULL,
JOB_GROUP VARCHAR(190) 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))
ENGINE=InnoDB;

CREATE TABLE QRTZ_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
JOB_NAME VARCHAR(190) NOT NULL,
JOB_GROUP VARCHAR(190) 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(190) 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))
ENGINE=InnoDB;

CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) 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))
ENGINE=InnoDB;

CREATE TABLE QRTZ_CRON_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
CRON_EXPRESSION VARCHAR(120) 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))
ENGINE=InnoDB;

CREATE TABLE QRTZ_SIMPROP_TRIGGERS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(190) NOT NULL,
    TRIGGER_GROUP VARCHAR(190) 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))
ENGINE=InnoDB;

CREATE TABLE QRTZ_BLOB_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
BLOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;

CREATE TABLE QRTZ_CALENDARS (
SCHED_NAME VARCHAR(120) NOT NULL,
CALENDAR_NAME VARCHAR(190) NOT NULL,
CALENDAR BLOB NOT NULL,
PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
ENGINE=InnoDB;

CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;

CREATE TABLE QRTZ_FIRED_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
ENTRY_ID VARCHAR(95) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
INSTANCE_NAME VARCHAR(190) 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(190) NULL,
JOB_GROUP VARCHAR(190) NULL,
IS_NONCONCURRENT VARCHAR(1) NULL,
REQUESTS_RECOVERY VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,ENTRY_ID))
ENGINE=InnoDB;

CREATE TABLE QRTZ_SCHEDULER_STATE (
SCHED_NAME VARCHAR(120) NOT NULL,
INSTANCE_NAME VARCHAR(190) NOT NULL,
LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
CHECKIN_INTERVAL BIGINT(13) NOT NULL,
PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
ENGINE=InnoDB;

CREATE TABLE QRTZ_LOCKS (
SCHED_NAME VARCHAR(120) NOT NULL,
LOCK_NAME VARCHAR(40) NOT NULL,
PRIMARY KEY (SCHED_NAME,LOCK_NAME))
ENGINE=InnoDB;

CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);

CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);

CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);

commit;

2.引入 mysql 驅動包

		<!-- mysql 驅動包 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.27</version>
		</dependency>

3.配置 quartz-jdbc.properties

## Quartz 配置信息

# 調度器名字
org.quartz.scheduler.instanceName = black-schedule
# 線程池大小
org.quartz.threadPool.threadCount = 3
# ====================================================================================== #
# 任務存儲方式選擇 JDBC存儲(對應sql在 org.quartz.impl.jdbcjobstore.Constants 常量類中)
# JDBC 存儲有兩個實現 JobStoreCMT 和 JobStoreXT ,其中:
#   JobStoreCMT:使用JTA容器管理事務,自己並不處理事務提交和回滾
#   JobStoreTX: 通過 JDBC 自己管理事務提交和回滾,適合單體應用.
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
# 數據庫驅動委派類(必須配置)
#   org.quartz.impl.jdbcjobstore.StdJDBCDelegate (for fully JDBC-compliant drivers)
#   org.quartz.impl.jdbcjobstore.MSSQLDelegate (for Microsoft SQL Server, and Sybase)
#   org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
#   org.quartz.impl.jdbcjobstore.WebLogicDelegate (for WebLogic drivers)
#   org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
#   org.quartz.impl.jdbcjobstore.oracle.WebLogicOracleDelegate (for Oracle drivers used within Weblogic)
#   org.quartz.impl.jdbcjobstore.oracle.weblogic.WebLogicOracleDelegate (for Oracle drivers used within Weblogic)
#   org.quartz.impl.jdbcjobstore.CloudscapeDelegate
#   org.quartz.impl.jdbcjobstore.DB2v6Delegate
#   org.quartz.impl.jdbcjobstore.DB2v7Delegate
#   org.quartz.impl.jdbcjobstore.DB2v8Delegate
#   org.quartz.impl.jdbcjobstore.HSQLDBDelegate
#   org.quartz.impl.jdbcjobstore.PointbaseDelegate
#   org.quartz.impl.jdbcjobstore.SybaseDelegate
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# 數據源配置(必須配置)  blackQuartz 是數據源名字
org.quartz.jobStore.dataSource = blackQuartz
# Quartz 表前綴
org.quartz.jobStore.tablePrefix=QRTZ_
# 指示 JobDataMaps 中的所有數據都是 String 類型,這樣不用序列化存儲到 BLOB 列中
org.quartz.jobStore.useProperties=false
# 多長時間認定 觸發器錯過了下次觸發時間,默認 60000 毫秒
org.quartz.jobStore.misfireThreshold=60000
# 開啟集群特性
org.quartz.jobStore.isClustered=false
# 集群檢查頻率間隔,默認15000毫秒
org.quartz.jobStore.clusterCheckinInterval=15000
# 一次性處理未觸發的觸發器最大數量,默認 20
org.quartz.jobStore.maxMisfiresToHandleAtATime=20
# 不允許  setAutoCommit(false)  true-不允許,false-允許
org.quartz.jobStore.dontSetAutoCommitFalse=false
# 加鎖查詢 LOCKS 表的一行數據,{0}是表前綴(tablePrefix),{1}是調度器名字
org.quartz.jobStore.selectWithLockSQL="SELECT * FROM {0}LOCKS WHERE SCHED_NAME = {1} AND LOCK_NAME = ? FOR UPDATE"
# 設置事務隔離級別為串行 true-設置,false-不設置
org.quartz.jobStore.txIsolationLevelSerializable=false
# 如果 org.quartz.scheduler.batchTriggerAcquisitionMaxCount >1 那么此屬性必須設置為 true
org.quartz.jobStore.acquireTriggersWithinLock=false
# 鎖處理類,用於生產 Semaphore 實例在 job store data 上進行鎖控制
#org.quartz.jobStore.lockHandler.class=null

# 管道分隔的屬性集合 在初始化階段傳給DriverDelegate使用,格式:"settingName=settingValue|otherSettingName=otherSettingValue|..."
#org.quartz.jobStore.driverDelegateInitString=
# ====================================================================================== #

# ====================================================================================== #
#   數據源名字為blackQuartz的 數據源配置(數據庫初始化腳本在quartz-2.3.0.jar的/org/quartz/impl/jdbcjobstore/包下)
# ====================================================================================== #
org.quartz.dataSource.blackQuartz.driver = com.mysql.cj.jdbc.Driver
org.quartz.dataSource.blackQuartz.URL = jdbc:mysql://localhost:3306/black?characterEncoding=UTF8&connectTimeout=6000&socketTimeout=6000&connectionTimeZone=Asia/Shanghai
org.quartz.dataSource.blackQuartz.user = black
org.quartz.dataSource.blackQuartz.password = Black@123
org.quartz.dataSource.blackQuartz.maxConnections = 5
org.quartz.dataSource.blackQuartz.validationQuery=select 0 

4.編寫測試類

package org.black.demo.quartz;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloJob implements Job{
	
	private static final Logger LOGGER =  LoggerFactory.getLogger(HelloJob.class);
	
	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		LOGGER.info("任務明細:{}", context.getJobDetail());
		LOGGER.info("激活的實例ID{}",context.getFireInstanceId());
		Date d =context.getFireTime();
		SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		LOGGER.info("調度器:{}",context.getScheduler());
		LOGGER.info("調度器激活時間:{}",f.format(context.getScheduledFireTime()));
		if(context.getPreviousFireTime() != null) {
			LOGGER.info("上次調用時間:{}",f.format(context.getPreviousFireTime()));
		}
		LOGGER.info("下次調用時間:{}",f.format(context.getNextFireTime()));
		LOGGER.info("觸發器:{}",context.getTrigger());
		LOGGER.info("觸發時間:{}", f.format(d));
		LOGGER.info("job 實例:{}", context.getJobInstance());
		LOGGER.info("job 運行時長:{}s", context.getJobRunTime());
		LOGGER.info("Job 設置的返回結果:{}",context.getResult());
		LOGGER.info("MergedJobDataMap:{}", context.getMergedJobDataMap());
		// 
//		LOGGER.info("恢復任務時對應的觸發器key:{}",context.getRecoveringTriggerKey());
		LOGGER.info("重復激活次數:{}",context.getRefireCount());

		LocalDateTime date = LocalDateTime.now();
		String curDateTime = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
		LOGGER.info("時間:{},當前線程:{} - 執行 HelloJob 任務",curDateTime,Thread.currentThread().getName() );
	}
}

package org.black.demo.quartz;

import java.util.Date;

import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Quartz 示例
 * 
 * @author lihw
 * @date 2021-12-27 17:48:011
 */
public class QuartzScheduleJDBCDemo {

	private static final Logger LOGGER =  LoggerFactory.getLogger(QuartzScheduleJDBCDemo.class);

	public static void main(String[] args) {
		try {
			// 從工廠類獲取調度器示例
			StdSchedulerFactory factory = new StdSchedulerFactory();
			// 指定加載quartz-jdbc.properties配置
			factory.initialize("quartz-jdbc.properties");
			Scheduler scheduler = factory.getScheduler();
			// 啟動調度器
			scheduler.start();

			// 定義一個Job 綁定到 HelloJob.class
			JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();

			// 定義一個觸發器,每 4s 執行一次任務
			Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow()
					.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(4).repeatForever())
					.build();

			// 調度器調度任務
			Date date = scheduler.scheduleJob(job, trigger);
			LOGGER.info("Quartz 調度器啟動時間:{}",date);
			// 調用shutdown()方法關閉調度器,否則任務一直在運行
//			scheduler.shutdown();

		} catch (SchedulerException e) {
			e.printStackTrace();
		}
	}
}

5. 測試

控制台輸出:

[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 時間:2021-12-28 11:46:05,當前線程:black-schedule_Worker-1 - 執行 HelloJob 任務
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 任務明細:JobDetail 'group1.job1':  jobClass: 'org.black.demo.quartz.HelloJob concurrentExectionDisallowed: false persistJobDataAfterExecution: false isDurable: false requestsRecovers: false
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 激活的實例IDNON_CLUSTERED1640663163286
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 調度器:org.quartz.impl.StdScheduler@480a4a2d
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 調度器激活時間:2021-12-28 11:46:09
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 上次調用時間:2021-12-28 11:46:05
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 下次調用時間:2021-12-28 11:46:13
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 觸發器:Trigger 'group1.trigger1':  triggerClass: 'org.quartz.impl.triggers.SimpleTriggerImpl calendar: 'null' misfireInstruction: 0 nextFireTime: Tue Dec 28 11:46:13 CST 2021
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 觸發時間:2021-12-28 11:46:09
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - job 實例:org.black.demo.quartz.HelloJob@f8b8a7d
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - job 運行時長:-1s
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - Job 設置的返回結果:null
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - MergedJobDataMap:org.quartz.JobDataMap@0
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 重復激活次數:0
[black-schedule_Worker-2] INFO org.black.demo.quartz.HelloJob - 時間:2021-12-28 11:46:09,當前線程:black-schedule_Worker-2 - 執行 HelloJob 任務
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 任務明細:JobDetail 'group1.job1':  jobClass: 'org.black.demo.quartz.HelloJob concurrentExectionDisallowed: false persistJobDataAfterExecution: false isDurable: false requestsRecovers: false
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 激活的實例IDNON_CLUSTERED1640663163287
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 調度器:org.quartz.impl.StdScheduler@480a4a2d
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 調度器激活時間:2021-12-28 11:46:13
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 上次調用時間:2021-12-28 11:46:09
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 下次調用時間:2021-12-28 11:46:17
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 觸發器:Trigger 'group1.trigger1':  triggerClass: 'org.quartz.impl.triggers.SimpleTriggerImpl calendar: 'null' misfireInstruction: 0 nextFireTime: Tue Dec 28 11:46:17 CST 2021
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 觸發時間:2021-12-28 11:46:13
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - job 實例:org.black.demo.quartz.HelloJob@7a800c47
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - job 運行時長:-1s
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - Job 設置的返回結果:null
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - MergedJobDataMap:org.quartz.JobDataMap@0
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 重復激活次數:0
[black-schedule_Worker-3] INFO org.black.demo.quartz.HelloJob - 時間:2021-12-28 11:46:13,當前線程:black-schedule_Worker-3 - 執行 HelloJob 任務
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 任務明細:JobDetail 'group1.job1':  jobClass: 'org.black.demo.quartz.HelloJob concurrentExectionDisallowed: false persistJobDataAfterExecution: false isDurable: false requestsRecovers: false
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 激活的實例IDNON_CLUSTERED1640663163288
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 調度器:org.quartz.impl.StdScheduler@480a4a2d
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 調度器激活時間:2021-12-28 11:46:17
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 上次調用時間:2021-12-28 11:46:13
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 下次調用時間:2021-12-28 11:46:21
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 觸發器:Trigger 'group1.trigger1':  triggerClass: 'org.quartz.impl.triggers.SimpleTriggerImpl calendar: 'null' misfireInstruction: 0 nextFireTime: Tue Dec 28 11:46:21 CST 2021
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 觸發時間:2021-12-28 11:46:17
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - job 實例:org.black.demo.quartz.HelloJob@1053e9f7
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - job 運行時長:-1s
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - Job 設置的返回結果:null
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - MergedJobDataMap:org.quartz.JobDataMap@0
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 重復激活次數:0
[black-schedule_Worker-1] INFO org.black.demo.quartz.HelloJob - 時間:2021-12-28 11:46:17,當前線程:black-schedule_Worker-1 - 執行 HelloJob 任務

執行以下sql查詢 表數據:

select * from QRTZ_JOB_DETAILS;
select * from QRTZ_FIRED_TRIGGERS;
select * from QRTZ_PAUSED_TRIGGER_GRPS;
select * from QRTZ_SCHEDULER_STATE;
select * from QRTZ_LOCKS;
select * from QRTZ_SIMPLE_TRIGGERS;
select * from QRTZ_SIMPROP_TRIGGERS;
select * from QRTZ_CRON_TRIGGERS;
select * from QRTZ_BLOB_TRIGGERS;
select * from QRTZ_TRIGGERS;
select * from QRTZ_JOB_DETAILS;
select * from QRTZ_CALENDARS;

image

SpringBoot 集成

待續...


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM