springboot整合quartz定时任务

该篇博客介绍了如何在SpringBoot项目中集成Quartz,通过配置文件设置自动启动、集群模式等,并提供了数据库建表语句。同时,展示了创建定时任务的代码,以及如何实现任务的增删改查操作。内容涵盖Quartz的配置、数据库表结构、定时任务编写和管理接口。

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

quartz简介:查看Quartz简介
获取本文完整demo请访问:git地址
springboot整合quartz,实现:

1.引入maven依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

2.配置文件加入以下配置(在mysql,mybatis-plus等配置好的情况下,若没配置好,请下载完整demo):

#quartz
#自启动,false则不执行定时任务
spring.quartz.auto-startup=true
spring.quartz.job-store-type=jdbc
spring.quartz.properties.org.quartz.scheduler.instanceName=clusteredScheduler
spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO
spring.quartz.properties.org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
#持久化到数据库
spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# 打开集群配置
spring.quartz.properties.org.quartz.jobStore.isClustered=true
# 设置集群检查间隔100s
spring.quartz.properties.org.quartz.jobStore.clusterCheckinInterval=10000
spring.quartz.properties.org.quartz.jobStore.useProperties=false
spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
spring.quartz.properties.org.quartz.threadPool.threadCount=15
spring.quartz.properties.org.quartz.threadPool.threadPriority=5
spring.quartz.properties.org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true

3.数据库建表,语句如下

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);  
  

4.编写定时任务:注意需要实现Job接口并实现execute方法即可,需要定时任务相关数据可从JobExecutionContext中取,编写一个简单的定时打印指定字符串:

public class PrintWordTask implements Job {


    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
        JobDetail jobDetail = jobExecutionContext.getJobDetail();
        JobKey key = jobDetail.getKey();
        String name = key.getName();
        String group = key.getGroup();
        String jobKey = name + group;
        String printTime = new SimpleDateFormat("yy-MM-dd HH-mm-ss").format(new Date());
        System.out.println(jobKey+"PrintWordsJob start at:" + printTime + ", prints: Hello Job-" + new Random().nextInt(100));
    }
}

5.实现定时任务列表,新增,删除,修改,中断,恢复,立即执行等功能

public interface QrtzJobDetailsService extends IService<QrtzJobDetails> {
    List<QrtzTriggers> listQuartzEntity(QrtzJobDetails quartz, Integer pageNo, Integer pageSize) ;
    
    boolean save(QrtzJobDetails quartz) ;

    boolean deleteJob(QrtzJobDetails quartz);

    boolean pauseJob(QrtzJobDetails quartz);

    void resumeJob(QrtzJobDetails qrtzJobDetails);

    void updateJob(QrtzJobDetails qrtzJobDetails);

    void triggerJob(QrtzJobDetails qrtzJobDetails);
@Slf4j
@Service
public class QrtzJobDetailsServiceImpl extends ServiceImpl<QrtzJobDetailsMapper, QrtzJobDetails> implements QrtzJobDetailsService {

    @Autowired
    private Scheduler scheduler ;
    @Resource
    private QrtzJobDetailsMapper qrtzJobDetailsMapper;

    @Override
    public List<QrtzTriggers> listQuartzEntity(QrtzJobDetails quartz, Integer pageNo, Integer pageSize) {
        return qrtzJobDetailsMapper.listQuartzEntity(quartz);
    }

    /**
     * 保存定时任务
     * @param quartz
     * @return
     */
    @Override
    @Transactional
    public boolean save(QrtzJobDetails quartz) {
        Assert.notNull(quartz.getCronExpression(), "cron表达式不能为空");
        Assert.notNull(quartz.getJobClassName(),"定时任务代码位置不能为空");
        //jobName+jobGroup不能重复,可以理解为jobName+jobGroup作为任务的唯一标识
        String uuid = "testQuartz"+ UUID.randomUUID().toString();
            quartz.setJobName(uuid);
            quartz.setJobGroup(uuid);
        try {
            //如果是修改  展示旧的 任务
            if (quartz.getOldJobGroup() != null) {
                JobKey key = new JobKey(quartz.getOldJobName(), quartz.getOldJobGroup());
                scheduler.deleteJob(key);
            }
            HashMap<String, Integer> map = new HashMap<>();
            map.put("id", 123);
            //通过这个可往定时任务传参,用处不大
            JobDataMap jobDataMap = new JobDataMap(map);
            Class cls = Class.forName(quartz.getJobClassName());
            cls.newInstance();
            //构建job信息
            JobDetail job = JobBuilder.newJob(cls)
                    .withIdentity(quartz.getJobName(), quartz.getJobGroup())
                    .withDescription(quartz.getDescription())
                    .usingJobData(jobDataMap)
                    .build();
            // 触发时间点
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(quartz.getCronExpression());
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("trigger" + quartz.getJobName(), quartz.getJobGroup())
                    .withDescription(quartz.getDescription())
                    .startNow().withSchedule(cronScheduleBuilder).build();
            //交由Scheduler安排触发
            scheduler.scheduleJob(job, trigger);
            scheduler.start();
        } catch (Exception e) {
            log.error("定时任务新增失败:", e);
        }
        return true;
    }

    /**
     * 删除定时任务
     * @param quartz
     * @return
     */
    @Override
    @Transactional
    public boolean deleteJob(QrtzJobDetails quartz) {
        Assert.notNull(quartz.getJobName(), "jobName不能为空");
        Assert.notNull(quartz.getJobGroup(),"jobGroup不能为空");
        boolean res = true;
        try {
            String jobName = quartz.getJobName();
            String jobGroup = quartz.getJobGroup();
            JobKey jobKey = new JobKey(jobName, jobGroup);
            res = scheduler.deleteJob(jobKey);
        } catch (Exception e) {
            log.error("删除定时任务失败:", e);
        }
        return res;
    }

    /**
     * 暂停定时任务
     * @param quartz
     * @return
     */
    @Override
    public boolean pauseJob(QrtzJobDetails quartz) {
        Assert.notNull(quartz.getJobName(), "jobName不能为空");
        Assert.notNull(quartz.getJobGroup(),"jobGroup不能为空");
        boolean res = true;
        try {
            JobKey jobKey = new JobKey(quartz.getJobName(), quartz.getJobGroup());
            scheduler.pauseJob(jobKey);
        } catch (Exception e) {
            log.error("终止定时任务异常:", e);
        }
        return res;
    }

    /**
     * 恢复定时任务
     * @param quartz
     */
    @Override
    public void resumeJob(QrtzJobDetails quartz) {
        Assert.notNull(quartz.getJobName(), "jobName不能为空");
        Assert.notNull(quartz.getJobGroup(),"jobGroup不能为空");
        try {
            JobKey jobKey = new JobKey(quartz.getJobName(), quartz.getJobGroup());
            scheduler.resumeJob(jobKey);
        } catch (Exception e) {
            log.error("恢复定时任务异常:", e);
        }
    }


    /**
     * 更新定时任务;这里只更新description,jobClassName,cronExpression三个字段
     * @param quartz
     */
    @Override
    @Transactional
    public void updateJob(QrtzJobDetails quartz) {
        Assert.notNull(quartz.getJobName(), "jobName不能为空");
        Assert.notNull(quartz.getJobGroup(),"jobGroup不能为空");
        try {
            String jobName = quartz.getJobName();
            String jobGroup = quartz.getJobGroup();
            Assert.notNull(jobName, "jobName不能为空");
            Assert.notNull(jobGroup, "jobGroup不能为空");
            Assert.notNull(quartz.getCronExpression(), "cron表达式不能为空");
            QrtzTriggers qrtzTriggers = qrtzJobDetailsMapper.getTriggerByJobKey( jobName, jobGroup);
            Assert.notNull(qrtzTriggers, "trigger不存在,定时任务异常");
            String triggerName = qrtzTriggers.getTriggerName();
            String triggerGroup = qrtzTriggers.getTriggerGroup();
            TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroup);
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(quartz.getCronExpression());
            CronTrigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(triggerGroup).withSchedule(cronScheduleBuilder).withDescription(quartz.getDescription()).build();
            scheduler.rescheduleJob(triggerKey, trigger);
            QrtzJobDetails newQrtzJobDetails = new QrtzJobDetails();
            newQrtzJobDetails.setId(quartz.getId());
            newQrtzJobDetails.setDescription(quartz.getDescription());
            newQrtzJobDetails.setJobClassName(quartz.getJobClassName());
            QueryWrapper<QrtzJobDetails> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(QrtzJobDetails::getId, quartz.getId());
            super.update(newQrtzJobDetails, wrapper);
        } catch (Exception e) {
            log.error("修改定时任务异常:", e);
        }

    }

    @Override
    public void triggerJob(QrtzJobDetails quartz) {
        Assert.notNull(quartz.getJobName(), "jobName不能为空");
        Assert.notNull(quartz.getJobGroup(),"jobGroup不能为空");
        try{
            JobKey jobKey = new JobKey(quartz.getJobName(), quartz.getJobGroup());
            scheduler.triggerJob(jobKey);
        }catch (Exception e){
            log.error("触发定时任务失败:",e);
        }
    }

}

新增(每5妙执行一次打印任务):postMan截图
在这里插入图片描述
在这里插入图片描述

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值