SpringBoot集成Quartz实现定时任务

news2024/11/15 8:33:51

文章目录

  • Quartz简介
  • pom依赖
  • 内存方式存储
  • Quartz简介
  • pom依赖
  • 内存方式存储
  • 数据库方式存储
  • 分布式任务支持

Quartz简介

Quartz的快速入门见:
Quartz官方文档_w3cschool

Quartz 存储方式有两种:MEMORY 和 JDBC。默认是内存形式维护任务信息,服务重启了任务就重新开始执行;而JDBC形式就是能够把任务信息持久化到数据库,虽然服务重启了,但根据数据库中的记录,任务还能继续执行。

pom依赖

    <!--springboot项目集成quartz依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-quartz</artifactId>
    </dependency>

内存方式存储

  1. 新建工程,pom增加quartz依赖

  2. 新建一个Job类,继承QuartzJobBean,实现抽象类中的方法,方法中实现该定时任务需要执行的逻辑。

比如我新建一个PrintTipJob,每次执行时在控制台输出hello world!

package com.example.demo.job;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

public class PrintTipJob extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        LocalTime time = LocalTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
        System.out.println("time:" + time.format(formatter) + "  hello world!");
    }
}
  1. 封装一个用于增加,更新,删除job的service层

    • Job 表示一个工作,要执行的具体内容。此接口中只有一个方法:void execute(JobExecutionContext context)
    • JobDetail 表示一个具体的可执行的调度程序,Job 是这个可执行程调度程序所要执行的内容,另外JobDetail 还包含了这个任务调度的方案和策略。
    • Trigger 代表一个调度参数的配置,什么时候去调。
    • Scheduler 代表一个调度容器,一个调度容器中可以注册多个 JobDetail 和 Trigger。当 Trigger 与 JobDetail 组合,就可以被 Scheduler 容器调度了。

service的接口

package com.example.demo.service;

import org.springframework.scheduling.quartz.QuartzJobBean;

public interface QuartzJobService {

   /**
    * 添加一个任务
    * @param job
    * @param jobName
    * @param jobGroupName
    * @param jobCronTime
    */
   void addJob(Class<? extends QuartzJobBean> job, String jobName, String jobGroupName, String jobCronTime);

   /**
    * 更新任务的执行cron
    * @param job
    * @param jobGroupName
    * @param jobCronTime
    */
   void updateJob(String job, String jobGroupName, String jobCronTime);

   /**
    * 是否存在某个job
    * @param job
    * @param jobGroupName
    * @return
    */
   boolean existJob(String job, String jobGroupName);

   /**
    * 删除任务一个job
    *
    * @param jobName      任务名称
    * @param jobGroupName 任务组名
    */
   void deleteJob(String jobName, String jobGroupName);
}

service实现类

package com.example.demo.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.example.demo.service.QuartzJobService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Service;

import java.util.Set;

@Slf4j
@Service
public class QuartzJobServiceImpl implements QuartzJobService {

    @Autowired
    private Scheduler scheduler;

    @Override
    public void addJob(Class<? extends QuartzJobBean> job, String jobName, String jobGroupName, String jobCronTime) {
        JobDetail jobDetail = JobBuilder.newJob(job)
                .withIdentity(jobName, jobGroupName)
                .withDescription(jobCronTime)
                .build();

        Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
                .startAt(DateBuilder.futureDate(1, DateBuilder.IntervalUnit.SECOND))
                .withSchedule(CronScheduleBuilder.cronSchedule(jobCronTime)).startNow().build();

        try {
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (Exception e) {
            log.error("e:{}", e.getMessage());
        }
    }

    @Override
    public void updateJob(String job, String jobGroupName, String jobCronTime) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(job, jobGroupName);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            if (ObjectUtil.isNotNull(trigger)) {
                trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
                        .withSchedule(CronScheduleBuilder.cronSchedule(jobCronTime)).build();
            } else {
                trigger = TriggerBuilder.newTrigger().withIdentity(job, jobGroupName)
                        .startAt(DateBuilder.futureDate(1, DateBuilder.IntervalUnit.SECOND))
                        .withSchedule(CronScheduleBuilder.cronSchedule(jobCronTime)).startNow().build();
            }

            scheduler.rescheduleJob(triggerKey, trigger);
        } catch (SchedulerException e) {
            log.error("e:{}", e.getMessage());
        }
    }

    @Override
    public boolean existJob(String job, String jobGroupName) {
        try {
            if (StringUtils.isAnyBlank(job, jobGroupName)) {
                return false;
            }
            GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
            Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
            if (CollectionUtils.isNotEmpty(jobKeys)) {
                for (JobKey jobKey : jobKeys) {
                    if (jobKey.getName().equals(job) && jobKey.getGroup().equals(jobGroupName)) {
                        return true;
                    }
                }
            }
        } catch (Exception e) {
            log.error("e:{}", e.getMessage());
        }
        return false;
    }

    @Override
    public void deleteJob(String jobName, String jobGroupName) {
        try {
            scheduler.deleteJob(new JobKey(jobName, jobGroupName));
        } catch (Exception e) {
            log.error("e:{}", e.getMessage());
        }
    }
}

  1. 创建定时任务监听类,实现ApplicationListener接口,服务一启动时,就增加或更新job

增加PrintTipJob类,cron表达式0/5 * * * * ? ,每5s执行一次

给出一个cron表达式在线生成器小工具的链接:Cron在线表达式生成器

package com.example.demo.listener;

import com.example.demo.job.PrintTipJob;
import com.example.demo.service.QuartzJobService;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component
public class ApplicationStartQuartzJobListener implements ApplicationListener<ContextRefreshedEvent> {

    @Resource
    private QuartzJobService quartzJobService;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (quartzJobService.existJob("PrintTipJob", "test")) {
            quartzJobService.updateJob("PrintTipJob", "test", "0/5 * * * * ? ");
        } else {
            quartzJobService.addJob(PrintTipJob.class, "PrintTipJob", "test", "0/5 * * * * ? ");
        }
    }
}

  1. 启动工程,可以看到控制台每隔5s会打印

图1SpringBoot集成Quartz实现定时任务

Quartz简介

Quartz的快速入门见:
Quartz官方文档_w3cschool

Quartz 存储方式有两种:MEMORY 和 JDBC。默认是内存形式维护任务信息,服务重启了任务就重新开始执行;而JDBC形式就是能够把任务信息持久化到数据库,虽然服务重启了,但根据数据库中的记录,任务还能继续执行。

pom依赖

    <!--springboot项目集成quartz依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-quartz</artifactId>
    </dependency>

内存方式存储

  1. 新建工程,pom增加quartz依赖

  2. 新建一个Job类,继承QuartzJobBean,实现抽象类中的方法,方法中实现该定时任务需要执行的逻辑。

比如我新建一个PrintTipJob,每次执行时在控制台输出hello world!

package com.example.demo.job;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

public class PrintTipJob extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        LocalTime time = LocalTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
        System.out.println("time:" + time.format(formatter) + "  hello world!");
    }
}
  1. 封装一个用于增加,更新,删除job的service层

    • Job 表示一个工作,要执行的具体内容。此接口中只有一个方法:void execute(JobExecutionContext context)
    • JobDetail 表示一个具体的可执行的调度程序,Job 是这个可执行程调度程序所要执行的内容,另外JobDetail 还包含了这个任务调度的方案和策略。
    • Trigger 代表一个调度参数的配置,什么时候去调。
    • Scheduler 代表一个调度容器,一个调度容器中可以注册多个 JobDetail 和 Trigger。当 Trigger 与 JobDetail 组合,就可以被 Scheduler 容器调度了。

service的接口

package com.example.demo.service;

import org.springframework.scheduling.quartz.QuartzJobBean;

public interface QuartzJobService {

   /**
    * 添加一个任务
    * @param job
    * @param jobName
    * @param jobGroupName
    * @param jobCronTime
    */
   void addJob(Class<? extends QuartzJobBean> job, String jobName, String jobGroupName, String jobCronTime);

   /**
    * 更新任务的执行cron
    * @param job
    * @param jobGroupName
    * @param jobCronTime
    */
   void updateJob(String job, String jobGroupName, String jobCronTime);

   /**
    * 是否存在某个job
    * @param job
    * @param jobGroupName
    * @return
    */
   boolean existJob(String job, String jobGroupName);

   /**
    * 删除任务一个job
    *
    * @param jobName      任务名称
    * @param jobGroupName 任务组名
    */
   void deleteJob(String jobName, String jobGroupName);
}

service实现类

package com.example.demo.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.example.demo.service.QuartzJobService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Service;

import java.util.Set;

@Slf4j
@Service
public class QuartzJobServiceImpl implements QuartzJobService {

    @Autowired
    private Scheduler scheduler;

    @Override
    public void addJob(Class<? extends QuartzJobBean> job, String jobName, String jobGroupName, String jobCronTime) {
        JobDetail jobDetail = JobBuilder.newJob(job)
                .withIdentity(jobName, jobGroupName)
                .withDescription(jobCronTime)
                .build();

        Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
                .startAt(DateBuilder.futureDate(1, DateBuilder.IntervalUnit.SECOND))
                .withSchedule(CronScheduleBuilder.cronSchedule(jobCronTime)).startNow().build();

        try {
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (Exception e) {
            log.error("e:{}", e.getMessage());
        }
    }

    @Override
    public void updateJob(String job, String jobGroupName, String jobCronTime) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(job, jobGroupName);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            if (ObjectUtil.isNotNull(trigger)) {
                trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
                        .withSchedule(CronScheduleBuilder.cronSchedule(jobCronTime)).build();
            } else {
                trigger = TriggerBuilder.newTrigger().withIdentity(job, jobGroupName)
                        .startAt(DateBuilder.futureDate(1, DateBuilder.IntervalUnit.SECOND))
                        .withSchedule(CronScheduleBuilder.cronSchedule(jobCronTime)).startNow().build();
            }

            scheduler.rescheduleJob(triggerKey, trigger);
        } catch (SchedulerException e) {
            log.error("e:{}", e.getMessage());
        }
    }

    @Override
    public boolean existJob(String job, String jobGroupName) {
        try {
            if (StringUtils.isAnyBlank(job, jobGroupName)) {
                return false;
            }
            GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
            Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
            if (CollectionUtils.isNotEmpty(jobKeys)) {
                for (JobKey jobKey : jobKeys) {
                    if (jobKey.getName().equals(job) && jobKey.getGroup().equals(jobGroupName)) {
                        return true;
                    }
                }
            }
        } catch (Exception e) {
            log.error("e:{}", e.getMessage());
        }
        return false;
    }

    @Override
    public void deleteJob(String jobName, String jobGroupName) {
        try {
            scheduler.deleteJob(new JobKey(jobName, jobGroupName));
        } catch (Exception e) {
            log.error("e:{}", e.getMessage());
        }
    }
}

  1. 创建定时任务监听类,实现ApplicationListener接口,服务一启动时,就增加或更新job

增加PrintTipJob类,cron表达式0/5 * * * * ? ,每5s执行一次

给出一个cron表达式在线生成器小工具的链接:Cron在线表达式生成器

package com.example.demo.listener;

import com.example.demo.job.PrintTipJob;
import com.example.demo.service.QuartzJobService;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component
public class ApplicationStartQuartzJobListener implements ApplicationListener<ContextRefreshedEvent> {

    @Resource
    private QuartzJobService quartzJobService;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (quartzJobService.existJob("PrintTipJob", "test")) {
            quartzJobService.updateJob("PrintTipJob", "test", "0/5 * * * * ? ");
        } else {
            quartzJobService.addJob(PrintTipJob.class, "PrintTipJob", "test", "0/5 * * * * ? ");
        }
    }
}

  1. 启动工程,可以看到控制台每隔5s会打印

在这里插入图片描述

数据库方式存储

  1. pom需要引入quartz的依赖,同时还要引入数据库的依赖
<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5.4</version>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
  1. 添加 Quartz 配置信息

在application.properties文件中加入相关配置。

# 将 Quartz 持久化方式修改为 jdbc
spring.quartz.job-store-type=jdbc
# 实例名称(默认为quartzScheduler)
spring.quartz.properties.org.quartz.scheduler.instanceName=test_scheduler
# 实例节点 ID 自动生成
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.dataSource=quartz_jobs
spring.quartz.properties.org.quartz.dataSource.quartz_jobs.driver=com.mysql.cj.jdbc.Driver
spring.quartz.properties.org.quartz.dataSource.quartz_jobs.URL=jdbc:mysql://localhost:3306/quartz_jobs?useUnicode=true&characterEncoding=utf8
spring.quartz.properties.org.quartz.dataSource.quartz_jobs.user=root
spring.quartz.properties.org.quartz.dataSource.quartz_jobs.password=
  1. 添加quartz使用到的库表

下载 Quartz 发布包,下载完成后,解压缩进入 quartz-2.2.3/docs/dbTables 目录,找到匹配数据库的 SQL 文件。

下载地址:
https://www.quartz-scheduler.org/downloads/files/quartz-2.2.3-distribution.tar.gz

使用的是mysql的脚本:tables_mysql.sql,或者使用如下脚本

#
# Quartz seems to work best with the driver mm.mysql-2.0.7-bin.jar
#
# PLEASE consider using mysql with innodb tables to avoid locking issues
#
# In your Quartz properties file, you'll need to set 
# org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#

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;

此处执行sql时还遇到了另外一个问题,有些表创建时一直报错:Index column size too large. The maximum column size is 767 bytes.解决方式参考链接:MySQL 建索引时遇到 Specified key was too long; max key length is 767 bytes

  1. 启动服务
    代码无需修改,启动服务,可以看到定时任务正常执行,每隔5s有打印。
    数据库相关的表中,也有了数据。
    在这里插入图片描述

分布式任务支持

可以开启集群配置,让定时任务支持分布式任务,本人未实验过,从其他文章中看到补充在这里。

在 application.properties 文件中,加入 Quartz 集群的配置信息:

# 开启集群,多个 Quartz 实例使用同一组数据库表
spring.quartz.properties.org.quartz.jobStore.isClustered=true

注意 Quartz 使用同一组数据库表作集群时,只需要配置相同的 instanceName 实例名称就可以,例如本次都用 test_scheduler.

 spring.quartz.properties.org.quartz.scheduler.instanceName=test_scheduler

参考文章:
玩转 Spring Boot 集成篇(定时任务框架Quartz)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1081022.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

企业需要ERP系统的八大理由,最后一个尤其重要

许多企业仍在质疑自己是否真的需要**ERP系统**。日常事务已经非常繁重&#xff0c;如果再加上寻找和实施一个新系统的挑战&#xff0c;那就更麻烦了。 公司业务在不断发展&#xff0c;出现了一些增长&#xff0c;订单也在不断增加&#xff0c;扭亏为盈&#xff0c;总体来说还算…

PostGIS310升级334

环境&#xff1a; centos7 postgis3.1.0alpha1 postgis3.3.4 如果您运行的是 PostGIS 3 或更高版本&#xff0c;则应升级到已安装的具有PostGIS_Extensions_Upgrade功能的最新版本。 SELECT postgis_extensions_upgrade(); 之前测试过从320升级334&#xff0c;直接执行路径…

巧用指标平台DataIndex,五步法轻松实现指标管理

开发部门在做指标加工的全流程中&#xff0c;是否经常出现如下问题&#xff1a; 业务部门看指标数据的时候&#xff0c;看到两个名称相似的指标&#xff0c;不清楚两个指标的差异性&#xff0c;来咨询开发部门指标计算口径&#xff0c;开发部门配合业务部门翻找代码&#xff…

RT-Thread HWTIMER设备(学习)

定时器简介 硬件定时器一般有2种工作模式&#xff0c;定时器模式和计数器模式。不管是工作在哪一种模式&#xff0c;实质都是通过内部计数器模块对脉冲信号进行计数&#xff0c;下面是定时器的一些重要概念。 计数器模式&#xff1a;对外部输入引脚的外部脉冲信号计数。定时器…

c语言:通讯录管理系统(文件版本)

前言&#xff1a;在大多数高校内&#xff0c;都是通过设计一个通讯录管理系统来作为c语言课程设计&#xff0c;通过一个具体的系统设计将我们学习过的结构体和函数等知识糅合起来&#xff0c;可以很好的锻炼学生的编程思维&#xff0c;本文旨在为通讯录管理系统的设计提供思路和…

智能电表线路单回路双回路的区别

随着科技的发展和能源管理的需求&#xff0c;智能电表已经成为电力系统中不可或缺的一部分。智能电表可以通过数据通信网络将用电信息实时传输到电力公司&#xff0c;为电力公司提供更精确、实时的用电数据&#xff0c;同时也可以为用户提供更加智能化的用电服务。 在智能电表…

局域网上IP多播与IP单播关于MAC地址的区别

IP单播进行到局域网上的时候&#xff1a; 网际层使用IP地址进行寻址&#xff0c;各路由器收到IP数据报后&#xff0c;根据其首部中的目的IP地址的网络号部分&#xff0c;基于路由表进行查表转发。 查表转发的结果可指明IP数据报的下一跳路由器的IP地址&#xff0c;但无法指明…

pid-limit参数实验

fork炸弹命令 :(){ :|:& };: 可以看到&#xff0c;如果docker没有限制&#xff0c;会遭到fork炸弹恶意 参考 https://www.cyberciti.biz/faq/understanding-bash-fork-bomb/

146616-66-2,胺反应性染料BDP FL NHS Ester,聚乙二醇单烯丙基醚

产品概览&#xff1a;Amine reactive bright&#xff0c;一种光稳定性佳的绿色荧光染料&#xff0c;以发挥独特的分子发光性能。此乃改进型的FAM&#xff08;荧光素&#xff09;荧光染料接班人——BDP FL NHS ester&#xff0c;在488nm通道中绽放色彩。这种胺反应性染料&#x…

信息系统项目管理师第四版学习笔记——项目绩效域

干系人绩效域 干系人绩效域涉及与干系人相关的活动和职能。在项目整个生命周期过程中&#xff0c;有效执行本绩效域可以实现的预期目标主要包含&#xff1a;①与干系人建立高效的工作关系&#xff1b;②干系人认同项目目标&#xff1b;③支持项目的干系人提高了满意度&#xf…

在原有的vue(react)项目中引入electron打包成桌面应用(全网最新!)

基于原有的项目中使用electron打包成桌面应用 首先了解electron是什么? 软件简介 Electron 是一个使用 JavaScript、HTML 和 CSS 构建跨平台的桌面应用程序。它基于 Node.js 和 Chromium,被 Atom 编辑器和许多其他应用程序使用。 Electron 兼容 Mac、Windows 和 Linux,可以…

SpringMVC源码分析(二)启动过程之RequestMappingHandlerMapping分析

a、http请求中的url是如何与对应Handler的即Controller对应method映射的&#xff1f; 在上篇中提到在SpringMVC中&#xff0c;初始化9大内置组件的时候其中有一个组件就是HandlerMapping&#xff0c;在初始化HandlerMapping的时候会加载代码中所有标注了Controller和RequestMap…

视频目标分割数据集分享

MOSE: A New Dataset for Video Object Segmentation in Complex Scenes MOSE 是一个新的视频目标分割数据集&#xff0c;旨在解决复杂环境下的目标跟踪和分割。MOSE 包含 2,149 个视频片段和来自 36 个类别的 5,200 个物体&#xff0c;以及 431,725 个高质量物体分割掩码。MOS…

ubuntu安装依赖包时显示需要先安装其所需要的各种安装包)apt-get源有问题

最近在崭新的ubuntu上安装g以及一些其他的依赖与工具时遇到以下报错情况&#xff1a; 依赖环环相扣&#xff0c;手动无法解决。 总结&#xff1a; 出现需要很多依赖项的情况是因为软件源中没有可用的依赖项或者依赖项版本不正确。 其实在Ubuntu系统中&#xff0c;使用sudo…

Java程序设计实验4 | 面向对象(下)

*本文是博主对Java各种实验的再整理与详解&#xff0c;除了代码部分和解析部分&#xff0c;一些题目还增加了拓展部分&#xff08;⭐&#xff09;。拓展部分不是实验报告中原有的内容&#xff0c;而是博主本人自己的补充&#xff0c;以方便大家额外学习、参考。 &#xff08;没…

AI如何帮助Salesforce从业者找工作?

在当今竞争激烈的就业市场中&#xff0c;找到满意的工作是一项艰巨的任务。成千上万的候选人竞争一个岗位&#xff0c;你需要利用一切优势从求职大军中脱颖而出。 这就是AI的用武之地&#xff0c;特别是像ChatGPT这样的人工智能工具&#xff0c;可以成为你的秘密武器。本篇文章…

2.1、如何在FlinkSQL中读取写出到Kafka

目录 1、环境设置 方式1&#xff1a;在Maven工程中添加pom依赖 方式2&#xff1a;在 sql-client.sh 中添加 jar包依赖 2、读取Kafka 2.1 创建 kafka表 2.2 读取 kafka消息体&#xff08;Value&#xff09; 使用 format json 解析json格式的消息 使用 format csv 解析…

力扣第98题 验证二叉搜索树 c++ 与上一篇文章相似

题目 98. 验证二叉搜索树 中等 相关标签 树 深度优先搜索 二叉搜索树 二叉树 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当…

淘宝天猫商品历史价格API接口

获取淘宝商品历史价格接口的步骤如下&#xff1a; 注册淘宝开放平台&#xff1a;首先在淘宝开放平台上注册一个账号&#xff0c;并进行登录。创建应用&#xff1a;在淘宝开放平台上创建一个应用&#xff0c;并获取该应用的App Key和App Secret&#xff0c;用于后续的接口调用。…

Python“梦寻”淘宝天猫店铺所有数据接口,淘宝店铺所有商品数据API接口,淘宝API接口申请指南(含代码示例)

获取淘宝店铺所有商品数据的接口可以通过淘宝开放平台获取。 具体操作步骤如下&#xff1a; 在淘宝开放平台注册成为开发者&#xff0c;并创建一个应用&#xff0c;获取到所需的 App Key 和 App Secret 等信息。使用获取到的 App Key 和 App Secret&#xff0c;进行签名和认证…