SpringBoot - 集成Quartz框架之具体步骤(三)

写在前面

本文讲述在基于SpringBoot框架的项目中,如何一步一步的集成Quartz框架,项目使用的是PostgreSQL数据库。

具体步骤

1. 添加依赖
<!-- quartz -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
2. 编写配置

在resource目录下创建servicex-quartz.properties文件:

#============================================================================
# 1. 基本配置
#============================================================================

# 调度标识名, 集群中每一个实例都必须使用相同的名称
org.quartz.scheduler.instanceName = SERVICEX-SCHEDULER-INSTANCE-NAME
# ID设置为自动获取, 每一个实例不能相同
org.quartz.scheduler.instanceId = AUTO

#============================================================================
# 2. 调度器线程池配置
#============================================================================

# 线程池的实现类, 一般使用SimpleThreadPool即可满足需求
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
# 指定线程数无默认值, 至少为1
org.quartz.threadPool.threadCount = 10
# 设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1,默认为5)
org.quartz.threadPool.threadPriority = 5


#============================================================================
# 3. 作业存储配置
#============================================================================

# 数据保存方式为数据库持久化
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
# 数据库驱动
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
# 是否加入集群
org.quartz.jobStore.isClustered = true
# 检查集群节点状态的频率, 默认值是 15000(15)
org.quartz.jobStore.clusterCheckinInterval = 15000
org.quartz.jobStore.maxMisfiresToHandleAtATime = 1
org.quartz.jobStore.txIsolationLevelSerializable = true
# 设置调度引擎对触发器超时的忍耐时间 (单位毫秒)
org.quartz.jobStore.misfireThreshold = 12000
# 表的前缀,默认QRTZ_
org.quartz.jobStore.tablePrefix = QRTZ_
3. 建库建表

在官网中找到对于的SQL脚本:

-- Thanks to Patrick Lightbody for submitting this...
--
-- In your Quartz properties file, you'll need to set
-- org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
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_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_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        BOOL         NOT NULL,
  IS_NONCONCURRENT  BOOL         NOT NULL,
  IS_UPDATE_DATA    BOOL         NOT NULL,
  REQUESTS_RECOVERY BOOL         NOT NULL,
  JOB_DATA          BYTEA        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       NULL,
  PREV_FIRE_TIME BIGINT       NULL,
  PRIORITY       INTEGER      NULL,
  TRIGGER_STATE  VARCHAR(16)  NOT NULL,
  TRIGGER_TYPE   VARCHAR(8)   NOT NULL,
  START_TIME     BIGINT       NOT NULL,
  END_TIME       BIGINT       NULL,
  CALENDAR_NAME  VARCHAR(200) NULL,
  MISFIRE_INSTR  SMALLINT     NULL,
  JOB_DATA       BYTEA        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       NOT NULL,
  REPEAT_INTERVAL BIGINT       NOT NULL,
  TIMES_TRIGGERED BIGINT       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(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)
);

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   BOOL           NULL,
  BOOL_PROP_2   BOOL           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     BYTEA        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      BYTEA        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       NOT NULL,
  SCHED_TIME        BIGINT       NOT NULL,
  PRIORITY          INTEGER      NOT NULL,
  STATE             VARCHAR(16)  NOT NULL,
  JOB_NAME          VARCHAR(200) NULL,
  JOB_GROUP         VARCHAR(200) NULL,
  IS_NONCONCURRENT  BOOL         NULL,
  REQUESTS_RECOVERY BOOL         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       NOT NULL,
  CHECKIN_INTERVAL  BIGINT       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)
);

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;
4. 创建调度器工厂
@Configuration
public class SchedulerConfig {

    // 配置文件路径
    private static final String SERVICEX_QUARTZ_CONFIG_PATH = "/servicex-quartz.properties";

    // 控制器工厂类
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setDataSource(dataSource);
        factory.setQuartzProperties(quartzProperties());
        factory.setStartupDelay(1);
        factory.setApplicationContextSchedulerContextKey("SERVICEX-APPLICATION-CONTEXT-KEY");
        factory.setOverwriteExistingJobs(true);
        factory.setAutoStartup(true);
        return factory;
    }

    @Bean
    @ConditionalOnResource(resources = SERVICEX_QUARTZ_CONFIG_PATH)
    Properties quartzProperties() {
        try {
            PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
            propertiesFactoryBean.setLocation(new ClassPathResource(SERVICEX_QUARTZ_CONFIG_PATH));
            propertiesFactoryBean.afterPropertiesSet();
            Properties properties = propertiesFactoryBean.getObject();
            return properties;
        } catch (IOException e) {
            System.out.println("QUARTZ相关的配置文件不存在.");
            e.printStackTrace();
        }
        return null;
    }
}
5. 封装任务
/**
 * 抽象JOB的封装
 * JOB表示一个任务, 也就是执行的具体的内容, 一个JOB可以被多个TRIGGER关联, 但是一个TRIGGER只能关联一个JOB.
 * @author ROCKY
 * @createTime 2022年07月04日
 */

@Slf4j
public abstract class AbstractQuartzJob implements Job {

    // 线程本地变量
    private static ThreadLocal<Date> threadLocal = new ThreadLocal<>();

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        ServicexJob job = new ServicexJob();
        BeanUtils.copyProperties(context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES), job);
        try {
            before(context, job);
            if (job != null) {
                doExecute(context, job);
            }
            after(context, job, null);
        } catch (Exception e) {
            after(context, job, e);
            log.error("任务执行异常:", e);
        }
    }

    // 1. 执行前
    protected void before(JobExecutionContext context, ServicexJob job) {
        threadLocal.set(new Date());
    }

    // 2. 执行方法, 实际的子JOB重载该方法
    protected abstract void doExecute(JobExecutionContext context, ServicexJob job) throws Exception;

    // 3. 执行后
    protected void after(JobExecutionContext context, ServicexJob job, Exception e) {
        threadLocal.remove();
        // 质检完成后会做一些操作
        job.doSomeThings();
    }

}
6. 具体任务
/**
 * 不支持并发执行任务的JOB(禁止并发执行, 表示Quartz不能并发的执行同一个JOB的定义, 特指一个JOB类的多个实例)
 * @author ROCKY
 * @createTime 2022年07月04日
 */
@Slf4j
@DisallowConcurrentExecution
public class MyJobExecution extends AbstractQuartzJob {
    @Override
    protected void doExecute(JobExecutionContext context, ServicexJob job) throws Exception {
        // 真正的调用逻辑
        log.info("TO DO SOMETHING."+ job.getCronExpression() + "[" + job.getNextValidTime() + "]");
    }
}
7. 编写调度器服务
/**
 * 调度器服务
 * JobDetail:用于定义作业的实例
 * Trigger: 触发器, 执行给定作业计划的组件实例
 * Scheduler: 与调度程序交互的主要的API
 * CronScheduleBuilder:用于创建一个Scheduler的生成器
 * 何时触发, 通过Trigger来定义, 使用TriggerBuilder进行构建
 * 什么任务, 通过JobDetail来定义, 使用JobBuilder进行构建
 * 执行逻辑, 通过JOB中的doExecute方法的具体实现, 执行具体的内容
 *
 * @author ROCKY
 * @createTime 2022年07月04日
 */
public class ServicexScheduler {

    // 1. 创建/新增任务
    public static void register(Scheduler scheduler, ServicexJob job, Class<? extends Job> jobClass) throws SchedulerException {

        // 1. 构建任务信息
        String jobId = job.getJobId();
        String jobGroup = job.getJobGroup();
        // 2.1 构建JOB-DETAIL
        JobKey jobKey = getJobKey(jobId, jobGroup);
        TriggerKey triggerKey = getTriggerKey(jobId, jobGroup);
        JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobKey).build();
        // 2.2 设置参数
        jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job);

        // 3. 构建CRON调度器
        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
        try {
            cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 4. 构建触发器
        // .startAt(), 用于指定开始时间
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey)
                .startAt(job.getStartTime())
                .withSchedule(cronScheduleBuilder).build();


        // 5. 判断是否存在该定时任务
        if (scheduler.checkExists(jobKey)) {
            // 防止创建时存在数据问题(先移除再创建)
            scheduler.deleteJob(jobKey);
        }
        // 6. 根据JOB-DETAIL和建触发器创建定时任务
        scheduler.scheduleJob(jobDetail, trigger);

        // 7. 如果JOB的状态是暂停的/禁用的, 需要暂定该任务
        if (!job.getStatus().equals(ScheduleConstants.Status.ENABLED.getValue())) {
            scheduler.pauseJob(jobKey);
        }

    }

    public static void register(Scheduler scheduler, ServicexJob job) throws SchedulerException {
        register(scheduler, job, MyJobExecution.class);
    }

    // 2. 暂停任务
    public static int pause(Scheduler scheduler, ServicexJob job) throws SchedulerException {
        String jobId = job.getJobId();
        String jobGroup = job.getJobGroup();
        JobKey jobKey = getJobKey(jobId, jobGroup);
        if (StringUtils.isNotEmpty(jobId) && StringUtils.isNotEmpty(jobGroup) && scheduler.checkExists(jobKey)) {
            scheduler.pauseJob(jobKey);
            return 1;
        }
        return -1;
    }


    // 3. 恢复任务
    public static int resume(Scheduler scheduler, ServicexJob job) throws SchedulerException {
        String jobId = job.getJobId();
        String jobGroup = job.getJobGroup();
        JobKey jobKey = getJobKey(jobId, jobGroup);
        if (StringUtils.isNotEmpty(jobId) && StringUtils.isNotEmpty(jobGroup) && scheduler.checkExists(jobKey)) {
            scheduler.resumeJob(jobKey);
            return 1;
        }
        return -1;
    }

    // 4. 删除任务
    public static int delete(Scheduler scheduler, ServicexJob job) throws SchedulerException {
        String jobId = job.getJobId();
        String jobGroup = job.getJobGroup();
        JobKey jobKey = getJobKey(jobId, jobGroup);
        if (StringUtils.isNotEmpty(jobId) && StringUtils.isNotEmpty(jobGroup) && scheduler.checkExists(jobKey)) {
            scheduler.deleteJob(jobKey);
            return 1;
        }
        return -1;
    }

    // 5. 运行任务
    public static void run(Scheduler scheduler, ServicexJob job) throws SchedulerException {
        String jobId = job.getJobId();
        String jobGroup = job.getJobGroup();
        JobDataMap dataMap = new JobDataMap();
        dataMap.put(ScheduleConstants.TASK_PROPERTIES, job);
        scheduler.triggerJob(getJobKey(jobId, jobGroup), dataMap);
    }

    // 6. 更新任务
    public static void update(Scheduler scheduler, ServicexJob job) throws SchedulerException {
        String jobId = job.getJobId();
        String jobGroup = job.getJobGroup();
        JobKey jobKey = getJobKey(jobId, jobGroup);
        if (StringUtils.isNotEmpty(jobId) && StringUtils.isNotEmpty(jobGroup) && scheduler.checkExists(jobKey)) {
            // 移除
            scheduler.deleteJob(jobKey);
        }
        // 新建
        register(scheduler, job);
    }

    // 6. 更新任务
    public static void update(Scheduler scheduler, ServicexJob job, Class<? extends Job> jobClass) throws SchedulerException {
        String jobId = job.getJobId();
        String jobGroup = job.getJobGroup();
        JobKey jobKey = getJobKey(jobId, jobGroup);

        if (StringUtils.isNotEmpty(jobId) && StringUtils.isNotEmpty(jobGroup) && scheduler.checkExists(jobKey)) {
            // 移除
            scheduler.deleteJob(jobKey);
        }
        // 新建
        register(scheduler, job, jobClass);
    }


    // 获取任务的键
    private static JobKey getJobKey(String jobId, String jobGroup) {
        return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME_PREFIX + jobId, jobGroup);
    }

    // 获取任务的键
    private static JobKey getJobKey(String taskName, String jobId, String jobGroup) {
        String jobName = (StringUtils.isNotEmpty(taskName) ? taskName : ScheduleConstants.TASK_CLASS_NAME_PREFIX) + jobId;
        return JobKey.jobKey(jobName, jobGroup);
    }

    // 构建任务触发器
    private static TriggerKey getTriggerKey(String jobId, String jobGroup) {
        return TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME_PREFIX + jobId, jobGroup);
    }

    // 设置定时任务执行计划的失火策略
    private static CronScheduleBuilder handleCronScheduleMisfirePolicy(ServicexJob job, CronScheduleBuilder cb)
            throws Exception {
        switch (job.getMisfirePolicy()) {
            case ScheduleConstants.MISFIRE_DEFAULT:
                return cb;
            case ScheduleConstants.MISFIRE_IGNORE_MISFIRES:
                return cb.withMisfireHandlingInstructionIgnoreMisfires();
            case ScheduleConstants.MISFIRE_FIRE_AND_PROCEED:
                return cb.withMisfireHandlingInstructionFireAndProceed();
            case ScheduleConstants.MISFIRE_DO_NOTHING:
                return cb.withMisfireHandlingInstructionDoNothing();
            default:
                return null;
        }
    }
}
8. 注册任务

在服务启动时注册所有的任务:

@Service
@Slf4j
public class ServicexQuartzServiceImpl implements IServicexQuartzService {

    @Autowired
    private ServicexQuartzMapperservicexQuartzMapper;
    
    @Autowired
    private Scheduler scheduler;

    @PostConstruct
    public void init() throws SchedulerException {
        scheduler.clear();
        List<ServicexJob> jobs = new LambdaQueryChainWrapper<>(servicexQuartzMapper).eq(ServicexJob::getRunType, RunType.AUTO.getValue()).list();
        for (ServicexJob job : jobs) {
            ServicexScheduler.register(scheduler, job);
        }
    }
    ...
}

其他文章

SpringBoot - 集成Quartz框架之CRON表达式
SpringBoot - 集成Quartz框架之Quartz简介(一)
SpringBoot - 集成Quartz框架之常用配置(二)
SpringBoot - 集成Quartz框架之具体步骤(三)
SpringBoot - 集成Quartz框架之独立数据源(四)
SpringBoot - 集成Quartz框架之常见问题(五)
SpringBoot - 集成Quartz框架之@DisallowConcurrentExecution注解详解(六)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
SpringBoot 中实现定时任务可以使用 Quartz 框架Quartz 是一个开源的作业调度框架,可以用来创建简单或复杂的作业调度程序。 下面是使用 Quartz 实现定时任务的步骤: 1. 添加 Quartz 的依赖 在 pom.xml 文件中添加以下依赖: ```xml <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.0</version> </dependency> ``` 2. 创建 Job 类 创建一个实现 org.quartz.Job 接口的 Job 类。Job 接口只有一个方法 execute(JobExecutionContext context),该方法会在作业执行时被调用。 ```java public class MyJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { // 作业要执行的任务 } } ``` 3. 创建 Trigger Trigger 是定义作业调度时间的组件。可以创建多个 Trigger 对象,每个对象对应一个时间表达式。 ```java Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("triggerName", "groupName") .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")) .build(); ``` 上面的代码创建了一个 Trigger 对象,它的名称是 triggerName,所属的组是 groupName。它使用了一个 Cron 表达式,表示每隔 5 秒执行一次作业。 4. 创建 Scheduler Scheduler 是 Quartz 的核心组件,用于管理和调度作业和触发器。创建一个 Scheduler 对象,然后将 Job 和 Trigger 注册到 Scheduler 中。 ```java SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); JobDetail jobDetail = JobBuilder.newJob(MyJob.class) .withIdentity("jobName", "groupName") .build(); scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); ``` 上面的代码创建了一个 Scheduler 对象,并使用 JobBuilder 和 TriggerBuilder 创建了一个 JobDetail 对象和一个 Trigger 对象。然后将 JobDetail 和 Trigger 注册到 Scheduler 中,并启动 Scheduler。 完整的代码示例: ```java public class MyJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { // 作业要执行的任务 } } public class QuartzConfig { @Bean public JobDetail jobDetail() { return JobBuilder.newJob(MyJob.class) .withIdentity("jobName", "groupName") .build(); } @Bean public Trigger trigger() { return TriggerBuilder.newTrigger() .withIdentity("triggerName", "groupName") .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")) .build(); } @Bean public Scheduler scheduler() throws SchedulerException { SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); scheduler.scheduleJob(jobDetail(), trigger()); scheduler.start(); return scheduler; } } ``` 在上面的代码中,我们使用了 Spring 的注解 @Bean 来注册 JobDetail、Trigger 和 Scheduler。注意要捕获 SchedulerException 异常。 这样就完成了通过集成 Quartz 来实现 SpringBoot 定时任务的步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cloneme01

谢谢您的支持与鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值