spring整合quartz(持久化数据库)
一、spring整合quartz
Quartz是一个开源的任务调度框架。基于定时、定期的策略来执行任务是它的核心功能。
Quartz有3个核心要素: 调度器(Scheduler)、 任务(Job)、 触发器(Trigger)。只要定义了Job(任务),Trigger(触发器)和Scheduler(调度器),即可实现一个定时调度能力。其中 Scheduler是Quartz中的核心,Scheduler负责管理Quartz应用运行时环境, Scheduler不是靠自己完成所有的工作,是根据 Trigger的触发标准,调用 Job中的任务执行逻辑,来完成完整的定时任务调度。
注意:一个 Job可以对应多个 Trigger,但一个 Trigger只能对应一个 Job。
背景需求
最近在做一个项目,项目中有一个需求,规定一个生效时间,使用定时任务将该对象即时生效和失效
然后查看了quartz资料后发现,quartz提供了两种存储的基本方式:
类型 | 优点 | 缺点 |
---|---|---|
RAMJobStore | 存储在内存里,配置简单,运行速度快 | 当程序停止时,调度信息会丢失。 可以存储的 JobDetail和 Trigger 有数量限制 |
JobStoreTX | 存储在数据库里面,当程序中断时,调度信息不会丢失 支持事务,支持集群。 再次启动时,会恢复因程序关闭,重启 而错过的任务。 |
运行速度较慢, 具体与连接数据库的速度有关 |
1、添加依赖
在pom中添加依赖
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
2、添加注解
主启动类上需要加上注解@EnableScheduling
@EnableScheduling
@SpringBootApplication
public class QuartzApplication {
public static void main(String[] args) {
SpringApplication.run(QuartzApplication.class,args);
}
}
3、创建QuartzUtils工具类
@Component
@Slf4j
public class QuartzUtils {
private static String JOB_GROUP_NAME = "DEFAULT_JOB_GROUP_NAME";
private static String TRIGGER_GROUP_NAME = "DEFAULT_TRIGGER_GROUP_NAME";
@Autowired
private Scheduler scheduler;
//addSimpleJob简略版无额外参数
public boolean addSimpleJob(String jobName, Integer interval, TimeUnit timeUnit, Class<? extends Job> jobClass) {
return addSimpleJob(jobName, JOB_GROUP_NAME, jobName, TRIGGER_GROUP_NAME, interval, timeUnit, null, jobClass);
}
//addSimpleJob简略版有额外参数
public boolean addSimpleJob(String jobName, Integer interval, TimeUnit timeUnit, Map<String, Object> extraParam, Class<? extends Job> jobClass) {
return addSimpleJob(jobName, JOB_GROUP_NAME, jobName, TRIGGER_GROUP_NAME, interval, timeUnit, extraParam, jobClass);
}
//addCronJob简略版无额外参数
public boolean addCronJob(String jobName, String cronExpression, Class<? extends Job> jobClass) {
return addCronJob(jobName, JOB_GROUP_NAME, jobName, TRIGGER_GROUP_NAME, cronExpression, null, jobClass);
}
//addCronJob简略版有额外参数
public boolean addCronJob(String jobName, String cronExpression, Map<String, Object> extraParam, Class<? extends Job> jobClass) {
return addCronJob(jobName, JOB_GROUP_NAME, jobName, TRIGGER_GROUP_NAME, cronExpression, extraParam, jobClass);
}
//modifySimpleJobTime简略版
public boolean modifySimpleJobTime(String triggerName, Integer interval, TimeUnit timeUnit) {
return modifySimpleJobTime(triggerName, TRIGGER_GROUP_NAME, interval, timeUnit);
}
//modifyCronJobTime简略版
public boolean modifyCronJobTime(String triggerName, String cronExpression) {
return modifyCronJobTime(triggerName, TRIGGER_GROUP_NAME, cronExpression);
}
//removeJob简略版
public boolean removeJob(String jobName) {
return removeJob(jobName, JOB_GROUP_NAME, jobName, TRIGGER_GROUP_NAME);
}
/**
* @Title addSimpleJob
* @Description: 添加简单定时任务
* @params: [jobName, jobGroup, triggerName, triggerGroupInteger, interval, timeUnit, JobClass]
* @return: boolean
* @throws:
* @author: caiwei
* @date: 2019/5/5 21:08
*/
public boolean addSimpleJob(String jobName, String jobGroup, String triggerName, String triggerGroup, Integer interval, TimeUnit timeUnit, Map<String, Object> extraParam, Class<? extends Job> JobClass) {
try {
JobDetail jobDetail = JobBuilder
.newJob(JobClass)
.withIdentity(jobName, jobGroup)
.build();
if (extraParam != null) {
jobDetail.getJobDataMap().putAll(extraParam);
}
SimpleTrigger simpleTrigger = TriggerBuilder
.newTrigger()
.withIdentity(triggerName, triggerGroup)
.withSchedule(getSimpleScheduleBuilder(interval, timeUnit))
.startNow()
.build();
scheduler.scheduleJob(jobDetail, simpleTrigger);
} catch (SchedulerException e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* @Title addCronJob
* @Description: 添加cron定时任务
* @params: [jobName, jobGroup, triggerName, triggerGroup, cronExpression, JobClass]
* @return: boolean
* @throws:
* @author: caiwei
* @date: 2019/5/5 21:11
*/
public boolean addCronJob(String jobName, String jobGroup, String triggerName, String triggerGroup, String cronExpression, Map<String, Object> extraParam, Class<? extends Job> JobClass) {
try {
JobDetail jobDetail = JobBuilder
.newJob(JobClass)
.withIdentity(jobName, jobGroup)
.build();
if (extraParam != null) {
jobDetail.getJobDataMap().putAll(extraParam);
}
CronTrigger cronTrigger = TriggerBuilder
.newTrigger()
.withIdentity(triggerName, triggerGroup)
.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))
.build();
scheduler.scheduleJob(jobDetail, cronTrigger);
} catch (SchedulerException e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* @Title modifySimpleJobTime
* @Description: 修改simple任务的时间的触发时间
* @params: [triggerName, triggerGroup, interval, timeUnit]
* @return: boolean
* @throws:
* @author: caiwei
* @date: 2019/5/5 21:39
*/
public boolean modifySimpleJobTime(String triggerName, String triggerGroup, Integer interval, TimeUnit timeUnit) {
try {
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroup);
SimpleTrigger oldTrigger = (SimpleTrigger) scheduler.getTrigger(triggerKey);
if (oldTrigger == null) {
log.error("未找到相关任务");
return false;
}
//unit:milliseconds
Long oldInterval = oldTrigger.getRepeatInterval();
if (!oldInterval.equals(getMilliseconds(interval, timeUnit))) {
SimpleTrigger simpleTrigger = TriggerBuilder
.newTrigger()
.withIdentity(triggerName, triggerGroup)
.withSchedule(getSimpleScheduleBuilder(interval, timeUnit))
.startNow()
.build();
scheduler.rescheduleJob(triggerKey, simpleTrigger);
}
} catch (SchedulerException e) {
e.printStackTrace();
log.error("修改简单定时任务间隔时间失败");
return false;
}
return true;
}
/**
* @Title modifyCronJob
* @Description: 修改cron任务的时间的触发时间
* @params: [triggerName, triggerGroup, cronExpression]
* @return: boolean
* @throws:
* @author: caiwei
* @date: 2019/5/5 21:42
*/
public boolean modifyCronJobTime(String triggerName, String triggerGroup, String cronExpression) {
try {
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroup);
CronTrigger oldTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (oldTrigger == null) {
log.error("未找到相关任务");
return false;
}
String oldCronExpression = oldTrigger.getCronExpression();
if (!oldCronExpression.equalsIgnoreCase(cronExpression)) {
CronTrigger cronTrigger = TriggerBuilder
.newTrigger()
.withIdentity(triggerName, triggerGroup)
.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))
.build();
scheduler.rescheduleJob(triggerKey, cronTrigger);
}
} catch (SchedulerException e) {
e.printStackTrace();
log.error("修改cron定时任务时间失败");
}
return true;
}
/**
* @Title removeJob
* @Description: 删除指定定时任务
* @params: [jobName, jobGroup, triggerName, triggerGroup]
* @return: boolean
* @throws:
* @author: caiwei
* @date: 2019/5/5 21:44
*/
public boolean removeJob(String jobName, String jobGroup, String triggerName, String triggerGroup) {
try {
scheduler.unscheduleJob(TriggerKey.triggerKey(triggerName, triggerGroup));
scheduler.deleteJob(JobKey.jobKey(jobName, jobGroup));
} catch (SchedulerException e) {
e.printStackTrace();
log.error("删除定时任务失败");
return false;
}
return true;
}
private SimpleScheduleBuilder getSimpleScheduleBuilder(Integer interval, TimeUnit timeUnit) {
switch (timeUnit) {
case SECONDS:
return SimpleScheduleBuilder.repeatSecondlyForever(interval);
case MINUTES:
return SimpleScheduleBuilder.repeatMinutelyForever(interval);
case HOURS:
return SimpleScheduleBuilder.repeatHourlyForever(interval);
default:
log.error("设置的时间间隔超出范围");
return null;
}
}
private Long getMilliseconds(Integer interval, TimeUnit timeUnit) {
switch (timeUnit) {
case SECONDS:
return (long) (1000 * interval);
case MINUTES:
return (long) (60 * 1000 * interval);
case HOURS:
return (long) (60 * 60 * 1000 * interval);
default:
log.error("间隔时间转换错误");
return null;
}
}
}
4、创建CronUtils工具类
因为我们的需求是精确到某个日期,所以直接将某个日期转换为cron表达式即可
@Slf4j
public class CronUtils {
/***
*
* @param date
* @param dateFormat : yyyy-MM-dd HH:mm:ss
* @return
*/
public static String formatDateByPattern(Date date, String dateFormat) {
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
String formatTimeStr = null;
if (date != null) {
formatTimeStr = sdf.format(date);
}
return formatTimeStr;
}
/***
* convert Date to cron ,eg. "21 25 17 07 01 ? 2020"
*
* @param date : 时间点
* @return
*/
public static String createCronExpression(Date date) {
String dateFormat = "ss mm HH dd MM ? yyyy";
return formatDateByPattern(date, dateFormat);
}
}
5、创建定时job
这里如果我们直接使用依赖注入的方式,这个job会报错。
原因是:Job是由quartz实例化出来的,不受Spring的管理,所以就导致注入失败。
解决:在方法中(如例子中的queryTraderNo方法)添加以下代码,自动注入成员变量实现类
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
@Slf4j
public class NoticeJob implements Job {
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Autowired
NoticeService noticeService;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
log.info("定时任务执行了");
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
// 业务逻辑
// ...
}
}
6、业务逻辑调用
可以直接通过工具类调用创建定时任务
quartzUtils.addCronJob(noticeEntity.getId()+"_start",startCron,dataMap, NoticeJob.class);
二、quartz数据持久化数据库
为什么要持久化
以前写demo,都不是持久化到数据里,直接存在内存里,当程序突然中断,或者后台突然挂了,内存溢出,都会导致定时任务的丢失,当项目重新启动后,也无之前的定时任务信息。所以我们可以使用数据库来持久化定时任务,这样项目重启后也会即时执行任务。
建表语句
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))
ENGINE=INNODB;
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))
ENGINE=INNODB;
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))
ENGINE=INNODB;
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(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(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))
ENGINE=INNODB;
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),
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(200) 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(200) 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(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))
ENGINE=INNODB;
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))
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;
1、添加配置文件
添加quartz配置信息以及数据库相关信息
#使用自己的配置文件
org.quartz.jobStore.useProperties:true
#默认或是自己改名字都行
org.quartz.scheduler.instanceName: DefaultQuartzScheduler
#如果使用集群,instanceId必须唯一,设置成AUTO
org.quartz.scheduler.instanceId = AUTO
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.dataSource = quartzTest
org.quartz.dataSource.quartzTest.driver = com.mysql.cj.jdbc.Driver
org.quartz.dataSource.quartzTest.URL = jdbc:mysql://39.102.52.254:3306/quartz_test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
org.quartz.dataSource.quartzTest.user = root
org.quartz.dataSource.quartzTest.password = yanwei12312
org.quartz.dataSource.quartzTest.maxConnections = 5
2、添加核心配置类
这其中我们把2个类的初始化移到了IOC中,因为之前Quartz的实例化是自己去控制的,为什么要这么做后面会有讲到。
一个是SchedulerFactoryBean类,这个类其实就是之前xml配置中的SchedulerFactoryBean。
@Configuration
public class QuartzConfiguration {
@Autowired
private JobFactory jobFactory;
@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setJobFactory(jobFactory);
// 用于quartz集群,QuartzScheduler 启动时更新己存在的Job
schedulerFactoryBean.setOverwriteExistingJobs(true);
//延长启动
schedulerFactoryBean.setStartupDelay(1);
//设置加载的配置文件
schedulerFactoryBean.setConfigLocation(new ClassPathResource("/application.properties"));
return schedulerFactoryBean;
}
@Bean
public Scheduler scheduler() {
return schedulerFactoryBean().getScheduler();
}
}
3、添加JobFactory类
这个类的作用就是讲Job的实例化交给IOC去进行。
其实问题在于:
Job对象的实例化过程是在Quartz中进行的,注入的实体类是在Spring容器当中的 所以在job中无法注入Srping容器的实体类。
解决方案:将Job Bean也纳入到Spring容器的管理之中,Spring容器自然能够为Job Bean自动装配好所需的依赖。
官方解释:https://www.quartz-scheduler.org/api/2.2.1/org/quartz/spi/JobFactory.html
翻译:JobFactory负责生成Job类的实例。
JobFactory 有2个实现类:AdaptableJobFactory 和 SimpleJobFactory。
- 自定义的工厂类 JobFactory 继承 AdaptableJobFactory 。
- 通过调用父类 AdaptableJobFactory 的方法createJobInstance来实现对Job的实例化。
- 在Job实例化完以后,再调用自身方法为创建好的Job实例进行属性自动装配并将其纳入到Spring容器的管理之中。(通过AutowireCapableBeanFactory纳入)。
@Component
public class JobFactory extends AdaptableJobFactory {
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
@Override
protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
// 调用父类的方法
Object jobInstance = super.createJobInstance(bundle);
// 进行注入
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
测试数据库持久化成功
至此,job 已经被我们成功持久化到数据库。我们来回顾下整体的一个流程。
pom文件添加对应的依赖。
mysql数据库对应表的初始化。
配置对应的properties
将原来quartz控制的类的实例化交给spirng IOC控制。(对应的是核心QuartzConfiguration类和JobFactory类)
业务逻辑层对job进行控制。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/90988.html