不安分的黑娃
踏踏实实,坚持学习,慢慢就懂了~

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 集成

待续...

posted on 2021-12-27 19:11  不安分的黑娃  阅读(1074)  评论(0编辑  收藏  举报