spring整合quartz(持久化数据库)

本文介绍了如何在Spring项目中整合Quartz框架,并实现任务调度的持久化,以避免程序中断导致的任务丢失。涉及添加依赖、配置文件、核心配置及JobFactory的定制,确保任务在数据库中存储和恢复。
摘要由CSDN通过智能技术生成

一、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。

  1. 自定义的工厂类 JobFactory 继承 AdaptableJobFactory 。
  2. 通过调用父类 AdaptableJobFactory 的方法createJobInstance来实现对Job的实例化。
  3. 在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进行控制。

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值