一、什么是Quartz
Quartz是OpenSymphony開源組織在Job scheduling領域又一個開源項目,它可以與J2EE與J2SE應用程序相結合也可以單獨使用。Quartz可以用來創(chuàng)建簡單或為運行十個,百個,甚至是好幾萬個Jobs這樣復雜的程序。Jobs可以做成標準的Java組件或 EJBs。
這個是百度百科給的解釋, 好像解釋的也不是很清楚;
Quartz是對定時器的封裝, 里面用他可以實現(xiàn)各種需求的定時任務, 因為他有強大的cron表達式; 并且可以對定時任務進行持久化;
二、整合Quartz
1.創(chuàng)建springboot項目,
這里要求會用springboot項目, 如果還不會,可以百度下,也可以去B站找相關教學視頻;
2.添加Quartz依賴
<!--springboot-quartz-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<!--Quartz 使用的連接池 這里Quartz在持久化任務時使用該jar-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
3.編寫配置類
package cn.cooplan.quartz;
import org.quartz.Scheduler;
import org.quartz.ee.servlet.QuartzInitializerListener;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import java.io.IOException;
import java.util.Properties;
/**
* Qartz配置, 搭配quartz.properties文件自定義配置, 該處目的使定時任務持久化
*/
@Configuration
public class SchedulerConfig {
/**
* 讀取quartz.properties 文件
* 將值初始化
* @return
*/
@Bean
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}
/**
* 將配置文件的數(shù)據(jù)加載到SchedulerFactoryBean中
* @return
* @throws IOException
*/
@Bean
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setQuartzProperties(quartzProperties());
return schedulerFactoryBean;
}
/**
* 初始化監(jiān)聽器
* @return
*/
@Bean
public QuartzInitializerListener executorListener(){
return new QuartzInitializerListener();
}
/**
* 獲得Scheduler 對象
* @return
* @throws IOException
*/
@Bean
public Scheduler scheduler() throws IOException {
return schedulerFactoryBean().getScheduler();
}
}
4.編寫quartz.properties配置文件
# 實例化ThreadPool時,使用的線程類為SimpleThreadPool
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
# threadCount和threadPriority將以setter的形式注入ThreadPool實例
# 并發(fā)個數(shù)
org.quartz.threadPool.threadCount = 5
# 優(yōu)先級
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
org.quartz.jobStore.misfireThreshold = 5000
#持久化使用的類
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
#數(shù)據(jù)庫中表的前綴
org.quartz.jobStore.tablePrefix = QRTZ_
#數(shù)據(jù)源命名
org.quartz.jobStore.dataSource = qzDS
#qzDS 數(shù)據(jù)源
org.quartz.dataSource.qzDS.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.qzDS.URL = jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=UTF-8
org.quartz.dataSource.qzDS.user = root
org.quartz.dataSource.qzDS.password = root
org.quartz.dataSource.qzDS.maxConnections = 10
5.創(chuàng)建Quartz持久化數(shù)據(jù)的表
這些都是固定的表, 復制粘貼就好了,以下sql適用于Mysql數(shù)據(jù)庫;
其他數(shù)據(jù)庫sql, 請從Quartz的jar包:org/quartz/impl/jdbcjobstore路徑下尋找sql文件
1.qrtz_blob_triggers : 以Blob 類型存儲的觸發(fā)器。
2.qrtz_calendars:存放日歷信息, quartz可配置一個日歷來指定一個時間范圍。
3.qrtz_cron_triggers:存放cron類型的觸發(fā)器。
4.qrtz_fired_triggers:存放已觸發(fā)的觸發(fā)器。
5.qrtz_job_details:存放一個jobDetail信息。
6.qrtz_job_listeners:job監(jiān)聽器。
7.qrtz_locks: 存儲程序的悲觀鎖的信息(假如使用了悲觀鎖)。
8.qrtz_paused_trigger_graps:存放暫停掉的觸發(fā)器。
9.qrtz_scheduler_state:調(diào)度器狀態(tài)。
10.qrtz_simple_triggers:簡單觸發(fā)器的信息。
11.qrtz_trigger_listeners:觸發(fā)器監(jiān)聽器。
12.qrtz_triggers:觸發(fā)器的基本信息。
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;
6.先了解下cron表達式
cron表達式生成器
這里先了解下, 下面就直接貼dome代碼了
cron表達式是一共有7位, 最簡單的例如: * * * * * * * (每秒執(zhí)行一次) 每個中間用空格隔開, 每個依次代表著: 秒 分 時 天 月 周 年 ->
{秒數(shù)} {分鐘} {小時} {日期} {月份} {星期} {年份(可為空)}
cron表達式.jpg
表達式舉例
"0 0 12 * * ?" 每天中午12點觸發(fā)
"0 15 10 ? * *" 每天上午10:15觸發(fā)
"0 15 10 * * ?" 每天上午10:15觸發(fā)
"0 15 10 * * ? *" 每天上午10:15觸發(fā)
"0 15 10 * * ? 2005" 2005年的每天上午10:15觸發(fā)
"0 * 14 * * ?" 在每天下午2點到下午2:59期間的每1分鐘觸發(fā)
"0 0/5 14 * * ?" 在每天下午2點到下午2:55期間的每5分鐘觸發(fā)
"0 0/5 14,18 * * ?" 在每天下午2點到2:55期間和下午6點到6:55期間的每5分鐘觸發(fā)
"0 0-5 14 * * ?" 在每天下午2點到下午2:05期間的每1分鐘觸發(fā)
"0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44觸發(fā)
"0 15 10 ? * MON-FRI" 周一至周五的上午10:15觸發(fā)
"0 15 10 15 * ?" 每月15日上午10:15觸發(fā)
"0 15 10 L * ?" 每月最后一日的上午10:15觸發(fā)
"0 15 10 ? * 6L" 每月的最后一個星期五上午10:15觸發(fā)
"0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一個星期五上午10:15觸發(fā)
"0 15 10 ? * 6#3" 每月的第三個星期五上午10:15觸發(fā)
7.一個簡單的定時器例子
a).編寫job實現(xiàn)類
Job實現(xiàn)類, 就是定時任務的主要邏輯編輯區(qū)
package cn.cooplan.quartz.job;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 簡單的執(zhí)行任務, 打印時間和你好
* 實現(xiàn)接口Job 從寫方法execute
* 該方法就是你定時器執(zhí)行任務的邏輯
*/
public class HiJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String nowTime = simpleDateFormat.format(new Date());
//這里為了演示, 只進行打印
System.out.println(nowTime + ":你好");
}
}
b).創(chuàng)建定時任務-->創(chuàng)建JobDetail, Trigger, Scheduler
Quartz的三大核心JobDetail, Trigger, Scheduler
JobDetail: 主要加載定時邏輯實現(xiàn)的類
Trigger: 主要制定定時任務執(zhí)行的規(guī)則
Scheduler:用來創(chuàng)建定時任務, 調(diào)度任務. 任務的增刪改都是由他完成;
package cn.cooplan.quartz.scheduler;
import cn.cooplan.quartz.job.HiJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.util.Date;
/**
* 使用cron表達式來控制任務
* 3秒后 每秒執(zhí)行一次
*/
public class CronScheduler {
public static void cronScheduler() throws SchedulerException {
/*
* JobBuilder.newJob(HiJob.class) --> 創(chuàng)建執(zhí)行的job實現(xiàn)類
* withIdentity("j1", "1") 創(chuàng)建該JobDetail 的名字和所在分組 第一個參數(shù)是名字, 第二個參數(shù) 分組
* build()創(chuàng)建對象
*/
JobDetail build = JobBuilder.newJob(HiJob.class).withIdentity("j1", "1").build();
Date date = new Date();
long startTime = date.getTime() + 3000;
/*
* TriggerBuilder.newTrigger() 創(chuàng)建一個Trigger
* startAt(new Date(startTime)) 執(zhí)行時間, 3秒后執(zhí)行
* withIdentity("t1", "1") Trigger所在的名字和分組,
* 第一個參數(shù)是名字, 第二個參數(shù) 分組,因為和job是倆個對象, 名字 分組可以跟job重復
* withSchedule(CronScheduleBuilder.cronSchedule("* * * * * ?")) cron表達式初始化, 每秒執(zhí)行一次
* build()創(chuàng)建對象
*/
CronTrigger c = TriggerBuilder.newTrigger()
.startAt(new Date(startTime))
.withIdentity("t1", "1")
.withSchedule(CronScheduleBuilder.cronSchedule("* * * * * ?"))
.build();
//創(chuàng)建SchedulerFactory對象 注意是new的是StdSchedulerFactory Std開頭
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
//獲得Scheduler
Scheduler scheduler = schedulerFactory.getScheduler();
//設置調(diào)度 的job 和trigger
scheduler.scheduleJob(build, c);
//開啟調(diào)度
scheduler.start();
}
}

8.數(shù)據(jù)庫的表用了哪些?

qrtz_cron_triggers :放置啟動過CronTrigger的參數(shù)
qrtz_fired_triggers :存放已觸發(fā)的觸發(fā)器, 每執(zhí)行一次更新一次 FIRED_TIME, SCHED_TIME字段
qrtz_job_details :存放一個jobDetail信息
qrtz_triggers :觸發(fā)器的基本信息
