springboot は、quartz の永続タスクをデータベースに統合します

Quartz 関連の依存関係を追加する

		<dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
            <!-- <version>2.3.0</version> -->
        </dependency>
        <!--定时任务需要依赖context模块-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>

mysqlテーブル作成ステートメント

/*
Navicat MySQL Data Transfer
Target Server Type    : MYSQL
Target Server Version : 50725
File Encoding         : 65001
Date: 2019-06-29 15:40:40
*/
 
SET FOREIGN_KEY_CHECKS=0;
 
-- ----------------------------
-- Table structure for QRTZ_BLOB_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_BLOB_TRIGGERS`;
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,
  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
  KEY `SCHED_NAME` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
  CONSTRAINT `QRTZ_BLOB_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
-- ----------------------------
-- Table structure for QRTZ_CALENDARS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_CALENDARS`;
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 DEFAULT CHARSET=utf8;
 
-- ----------------------------
-- Table structure for QRTZ_CRON_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_CRON_TRIGGERS`;
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) DEFAULT NULL,
  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
  CONSTRAINT `QRTZ_CRON_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
-- ----------------------------
-- Table structure for QRTZ_FIRED_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_FIRED_TRIGGERS`;
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` int(11) NOT NULL,
  `STATE` varchar(16) NOT NULL,
  `JOB_NAME` varchar(200) DEFAULT NULL,
  `JOB_GROUP` varchar(200) DEFAULT NULL,
  `IS_NONCONCURRENT` varchar(1) DEFAULT NULL,
  `REQUESTS_RECOVERY` varchar(1) DEFAULT NULL,
  PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`),
  KEY `IDX_QRTZ_FT_TRIG_INST_NAME` (`SCHED_NAME`,`INSTANCE_NAME`),
  KEY `IDX_QRTZ_FT_INST_JOB_REQ_RCVRY` (`SCHED_NAME`,`INSTANCE_NAME`,`REQUESTS_RECOVERY`),
  KEY `IDX_QRTZ_FT_J_G` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
  KEY `IDX_QRTZ_FT_JG` (`SCHED_NAME`,`JOB_GROUP`),
  KEY `IDX_QRTZ_FT_T_G` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
  KEY `IDX_QRTZ_FT_TG` (`SCHED_NAME`,`TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
-- ----------------------------
-- Table structure for QRTZ_JOB_DETAILS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_JOB_DETAILS`;
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) DEFAULT 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,
  PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
  KEY `IDX_QRTZ_J_REQ_RECOVERY` (`SCHED_NAME`,`REQUESTS_RECOVERY`),
  KEY `IDX_QRTZ_J_GRP` (`SCHED_NAME`,`JOB_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
-- ----------------------------
-- Table structure for QRTZ_LOCKS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_LOCKS`;
CREATE TABLE `QRTZ_LOCKS` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `LOCK_NAME` varchar(40) NOT NULL,
  PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
-- ----------------------------
-- Table structure for QRTZ_PAUSED_TRIGGER_GRPS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_PAUSED_TRIGGER_GRPS`;
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 DEFAULT CHARSET=utf8;
 
-- ----------------------------
-- Table structure for QRTZ_SCHEDULER_STATE
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_SCHEDULER_STATE`;
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 DEFAULT CHARSET=utf8;
 
-- ----------------------------
-- Table structure for QRTZ_SIMPLE_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_SIMPLE_TRIGGERS`;
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`),
  CONSTRAINT `QRTZ_SIMPLE_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
-- ----------------------------
-- Table structure for QRTZ_SIMPROP_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_SIMPROP_TRIGGERS`;
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) DEFAULT NULL,
  `STR_PROP_2` varchar(512) DEFAULT NULL,
  `STR_PROP_3` varchar(512) DEFAULT NULL,
  `INT_PROP_1` int(11) DEFAULT NULL,
  `INT_PROP_2` int(11) DEFAULT NULL,
  `LONG_PROP_1` bigint(20) DEFAULT NULL,
  `LONG_PROP_2` bigint(20) DEFAULT NULL,
  `DEC_PROP_1` decimal(13,4) DEFAULT NULL,
  `DEC_PROP_2` decimal(13,4) DEFAULT NULL,
  `BOOL_PROP_1` varchar(1) DEFAULT NULL,
  `BOOL_PROP_2` varchar(1) DEFAULT NULL,
  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
  CONSTRAINT `QRTZ_SIMPROP_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
-- ----------------------------
-- Table structure for QRTZ_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_TRIGGERS`;
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) DEFAULT NULL,
  `NEXT_FIRE_TIME` bigint(13) DEFAULT NULL,
  `PREV_FIRE_TIME` bigint(13) DEFAULT NULL,
  `PRIORITY` int(11) DEFAULT NULL,
  `TRIGGER_STATE` varchar(16) NOT NULL,
  `TRIGGER_TYPE` varchar(8) NOT NULL,
  `START_TIME` bigint(13) NOT NULL,
  `END_TIME` bigint(13) DEFAULT NULL,
  `CALENDAR_NAME` varchar(200) DEFAULT NULL,
  `MISFIRE_INSTR` smallint(2) DEFAULT NULL,
  `JOB_DATA` blob,
  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
  KEY `IDX_QRTZ_T_J` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
  KEY `IDX_QRTZ_T_JG` (`SCHED_NAME`,`JOB_GROUP`),
  KEY `IDX_QRTZ_T_C` (`SCHED_NAME`,`CALENDAR_NAME`),
  KEY `IDX_QRTZ_T_G` (`SCHED_NAME`,`TRIGGER_GROUP`),
  KEY `IDX_QRTZ_T_STATE` (`SCHED_NAME`,`TRIGGER_STATE`),
  KEY `IDX_QRTZ_T_N_STATE` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
  KEY `IDX_QRTZ_T_N_G_STATE` (`SCHED_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
  KEY `IDX_QRTZ_T_NEXT_FIRE_TIME` (`SCHED_NAME`,`NEXT_FIRE_TIME`),
  KEY `IDX_QRTZ_T_NFT_ST` (`SCHED_NAME`,`TRIGGER_STATE`,`NEXT_FIRE_TIME`),
  KEY `IDX_QRTZ_T_NFT_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`),
  KEY `IDX_QRTZ_T_NFT_ST_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_STATE`),
  KEY `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
  CONSTRAINT `QRTZ_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

私が実装したのはタスクをデータベースに永続化することなので、フレームワーク自体のquartz.propertiesファイルをオーバーライドする必要があります

#使用自己的配置文件
org.quartz.jobStore.useProperties:false
#默认或是自己改名字都行
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
#存储方式使用JobStoreTX,也就是数据库
org.quartz.jobStore.class:org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#是否使用集群(如果项目只部署到 一台服务器,就不用了)
org.quartz.jobStore.isClustered=false
org.quartz.jobStore.clusterCheckinInterval=20000
org.quartz.jobStore.tablePrefix=qrtz_
org.quartz.jobStore.dataSource=myDS

(注: データベースの構成を構成クラス QuartzConfiguration にロードしました)
起動プロジェクトは、コンソールの情報から、データの永続化モードが正常に有効になっているかどうかを確認できます。

10:44:39.576  INFO org.quartz.impl.jdbcjobstore.JobStoreTX  : JobStoreTX initialized.
10:44:39.578  INFO org.quartz.core.QuartzScheduler          : Scheduler meta-data: Quartz Scheduler (v2.3.0) 'schedulerFactoryBean' with instanceId 'NON_CLUSTERED'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
  Using job-store 'org.quartz.impl.jdbcjobstore.JobStoreTX' - which supports persistence. and is not clustered.

10:44:39.578  INFO org.quartz.impl.StdSchedulerFactory      : Quartz scheduler 'schedulerFactoryBean' initialized from an externally provided properties instance.
10:44:39.578  INFO org.quartz.impl.StdSchedulerFactory      : Quartz scheduler version: 2.3.0
10:44:39.579  INFO org.quartz.core.QuartzScheduler          : JobFactory set to: com.ywsoftware.oa.task.quartz.config.JobFactory@5486ee92
10:44:39.638  INFO c.m.v.c.i.AbstractPoolBackedDataSource   : Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 1bqooz6aa1hbh2ue1dtk02|3f06ebe0, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.cj.jdbc.Driver, extensions -> {
    
    }, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 1bqooz6aa1hbh2ue1dtk02|3f06ebe0, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://172.16.10.244:3306/rc_dev_test_data?characterEncoding=utf8&serverTimezone=GMT%2B8&allowMultiQueries=true&useSSL=false, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 5, maxStatements -> 0, maxStatementsPerConnection -> 120, minPoolSize -> 1, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {
    
    user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {
    
    }, usesTraditionalReflectiveProxies -> false ]


この問題は、主にいくつかの主要な構成クラスによって
解決されます。 1. いくつかのビジネス クラスをジョブ クラスに注入する必要がありますが、ジョブ クラスは Spring によって管理される Bean ではないため、管理のためにジョブ クラスを Spring に渡す必要があります。次の構成
2. 環境に応じたタイミングのタスク構成、異なるデータベース
構成 1 を区別します。

package com.ywsoftware.oa.task.quartz.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceConfig {
    
    
    private String url;
    private String username;
    private String password;
}

(通常環境に合わせて設定している設定ファイルからデータベースの設定を読み込むためです)

構成 2

package com.ywsoftware.oa.task.quartz.config;

import org.quartz.Scheduler;
import org.quartz.spi.JobFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 描述 : quartz 配置信息
 */
@Configuration
public class QuartzConfiguration {
    
    
    @Autowired
    private JobFactory jobFactory;
    @Autowired
    private DataSourceConfig dataSourceConfig;

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() {
    
    
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        schedulerFactoryBean.setJobFactory(jobFactory);
        // 用于quartz集群,QuartzScheduler 启动时更新己存在的Job
        schedulerFactoryBean.setOverwriteExistingJobs(true);
        schedulerFactoryBean.setStartupDelay(1);
        Map<String, Object> quartzMap = new HashMap<>();
        quartzMap.put("org.quartz.dataSource.myDS.URL", dataSourceConfig.getUrl());
        quartzMap.put("org.quartz.dataSource.myDS.user", dataSourceConfig.getUsername());
        quartzMap.put("org.quartz.dataSource.myDS.password", dataSourceConfig.getPassword());
        quartzMap.put("org.quartz.dataSource.myDS.driver", "com.mysql.cj.jdbc.Driver");
        quartzMap.put("org.quartz.dataSource.myDS.maxConnections", "5");
        Properties quartzProperties = new Properties();
        quartzProperties.putAll(quartzMap);
        schedulerFactoryBean.setConfigLocation(new ClassPathResource("quartz.properties"));
        schedulerFactoryBean.setQuartzProperties(quartzProperties);
        return schedulerFactoryBean;
    }

    @Bean
    public Scheduler scheduler() {
    
    
        return schedulerFactoryBean().getScheduler();
    }
}

注: 実際に開発環境を使用する場合、prod、gray、dev、および異なる環境の異なるライブラリなど、多くの人が開発環境を区別する必要があると思います。そのため、設定を手動で読み込む必要があります。データベースを区別するには、次を使用します。さまざまな環境構成で

		quartzMap.put("org.quartz.dataSource.myDS.URL", dataSourceConfig.getUrl());
        quartzMap.put("org.quartz.dataSource.myDS.user", dataSourceConfig.getUsername());
        quartzMap.put("org.quartz.dataSource.myDS.password", dataSourceConfig.getPassword());
        quartzMap.put("org.quartz.dataSource.myDS.driver", "com.mysql.cj.jdbc.Driver");
        quartzMap.put("org.quartz.dataSource.myDS.maxConnections", "5");
        Properties quartzProperties = new Properties();
        quartzProperties.putAll(quartzMap);
        schedulerFactoryBean.setConfigLocation(new ClassPathResource("quartz.properties"));
        schedulerFactoryBean.setQuartzProperties(quartzProperties);

構成 3

package com.ywsoftware.oa.task.quartz.config;

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;

/**
 * 描述:
 */
@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;
    }
}

業務執行方法

package com.ywsoftware.oa.task.quartz.job;

import com.ywsoftware.oa.task.quartz.mapper.JobRuHistoryMapper;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
@DisallowConcurrentExecution
public class CustomDataJob extends QuartzJobBean {
    
      
    @Autowired
    private JobRuHistoryMapper jobRuHistoryMapper;

    @Override
    protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {
    
    
      // 实现自己的业务方法
    }
}
(注:@DisallowConcurrentExecution 禁止并发执行多个相同定义的JobDetail,可以不加,看你得任务执行时间和周期)

タスクの追加、削除、変更

package com.ywsoftware.oa.task.quartz.service;

import com.ywsoftware.oa.data.core.schema.JobDesign;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.util.List;
import java.util.Map;

public interface QuartzService {
    
    

    /**
     * 增加一个job
     *
     * @param jobClass     任务实现类
     * @param jobName      任务名称
     * @param jobGroupName 任务组名
     * @param jobTime      时间表达式 (这是每隔多少秒为一次任务)
     * @param jobTimes     运行的次数 (<0:表示不限次数)
     * @param jobData      参数
     */
    void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, int jobTime,
                int jobTimes, Map jobData);

    /**
     * 增加一个job
     *
     * @param jobClass     任务实现类
     */
    void addJob(Class<? extends QuartzJobBean> jobClass, JobDesign jobDesign);

    /**
     * 修改 一个job的 时间表达式
     * @param jobName 任务名称
     * @param jobGroupName 任务组名
     * @param jobTime 任务执行时间
     */
    void updateJob(String jobName, String jobGroupName, String jobTime);

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

    /**
     * 暂停一个job
     * @param jobName 任务名称
     * @param jobGroupName 任务组名
     */
    void pauseJob(String jobName, String jobGroupName);

    /**
     * 恢复一个job
     *
     * @param jobName 任务名称
     * @param jobGroupName 任务组名
     */
    void resumeJob(String jobName, String jobGroupName);

    /**
     * 立即执行一个job
     *
     * @param jobName 任务名称
     * @param jobGroupName 任务组名
     */
    void runAJobNow(String jobName, String jobGroupName);

    /**
     * 获取所有计划中的任务列表
     *
     * @return
     */
    List<Map<String, Object>> queryAllJob();

    /**
     * 获取所有正在运行的job
     *
     * @return
     */
    List<Map<String, Object>> queryRunJob();

    List<Map<String, Object>> queryJobByJobName(String jobName, String GroupName);

}

package com.ywsoftware.oa.task.quartz.service;

import com.ywsoftware.oa.data.core.schema.JobDesign;
import com.ywsoftware.oa.task.util.CronUtil;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
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 javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
public class QuartzServiceImpl implements QuartzService {
    
    
    private static final String GROUP_NAME = "redcat";

    @Autowired
    private Scheduler scheduler;

    @PostConstruct
    public void startScheduler() {
    
    
        try {
    
    
            scheduler.start();
        } catch (SchedulerException scheduler) {
    
    
            scheduler.printStackTrace();
        }
    }

    /**
     * 增加一个job
     *
     * @param jobClass     任务实现类
     * @param jobName      任务名称
     * @param jobGroupName 任务组名
     * @param jobTime      时间表达式 (这是每隔多少秒为一次任务)
     * @param jobTimes     运行的次数 (<0:表示不限次数)
     * @param jobData      参数
     */
    @Override
    public void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, int jobTime,
                       int jobTimes, Map jobData) {
    
    
        try {
    
    
            // 任务名称和组构成任务key
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName)
                    .build();
            // 设置job参数
            if (jobData != null && jobData.size() > 0) {
    
    
                jobDetail.getJobDataMap().putAll(jobData);
            }
            // 使用simpleTrigger规则
            Trigger trigger = null;
            if (jobTimes < 0) {
    
    
                trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
                        .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1).withIntervalInSeconds(jobTime))
                        .startNow().build();
            } else {
    
    
                trigger = TriggerBuilder
                        .newTrigger().withIdentity(jobName, jobGroupName).withSchedule(SimpleScheduleBuilder
                                .repeatSecondlyForever(1).withIntervalInSeconds(jobTime).withRepeatCount(jobTimes))
                        .startNow().build();
            }
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException scheduler) {
    
    
            scheduler.printStackTrace();
        }
    }

    /**
     * 增加一个job
     *
     * @param jobClass     任务实现类
     */
    @Override
    public void addJob(Class<? extends QuartzJobBean> jobClass, JobDesign jobDesign) {
    
    
        try {
    
    
            String jobName = jobDesign.getJobId().replaceAll("-", "");
            String jobTimeCron = CronUtil.getCornByTime(jobDesign.getStartTime(), jobDesign.getCycle(),
                    Integer.valueOf(jobDesign.getTimeInterval() == null ? "1" : jobDesign.getTimeInterval()));
            // 创建jobDetail实例,绑定Job实现类
            // 指明job的名称,所在组的名称,以及绑定job类
            // 任务名称和组构成任务key
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, GROUP_NAME)
                    .build();
            // 设置job参数
            jobDetail.getJobDataMap().putAll(jobDesign.getJobDataMap());
            // 定义调度触发规则
            // 使用cornTrigger规则
            // 触发器key
            // 触发器key
            Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, GROUP_NAME)
                    .startAt(jobDesign.getStartTime())
                    .withSchedule(CronScheduleBuilder.cronSchedule(jobTimeCron).withMisfireHandlingInstructionDoNothing()).build();
            // 把作业和触发器注册到任务调度中
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException scheduler) {
    
    
            scheduler.printStackTrace();
        }
    }

    /**
     * 修改 一个job的 时间表达式
     *
     * @param jobName 任务名称
     * @param jobGroupName 任务组名
     * @param jobTime 任务执行时间
     */
    @Override
    public void updateJob(String jobName, String jobGroupName, String jobTime) {
    
    
        try {
    
    
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
                    .withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).build();
            // 重启触发器
            scheduler.rescheduleJob(triggerKey, trigger);
        } catch (SchedulerException scheduler) {
    
    
            scheduler.printStackTrace();
        }
    }

    /**
     * 删除任务一个job
     *
     * @param jobName      任务名称
     * @param jobGroupName 任务组名
     */
    @Override
    public void deleteJob(String jobName, String jobGroupName) {
    
    
        try {
    
    
            scheduler.deleteJob(new JobKey(jobName, jobGroupName));
        } catch (SchedulerException scheduler) {
    
    
            scheduler.printStackTrace();
        }
    }

    /**
     * 暂停一个job
     *
     * @param jobName 任务名称
     * @param jobGroupName 任务组名
     */
    @Override
    public void pauseJob(String jobName, String jobGroupName) {
    
    
        try {
    
    
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            scheduler.pauseJob(jobKey);
        } catch (SchedulerException scheduler) {
    
    
            scheduler.printStackTrace();
        }
    }

    /**
     * 恢复一个job
     *
     * @param jobName 任务名称
     * @param jobGroupName 任务组名
     */
    @Override
    public void resumeJob(String jobName, String jobGroupName) {
    
    
        try {
    
    
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            scheduler.resumeJob(jobKey);
        } catch (SchedulerException scheduler) {
    
    
            scheduler.printStackTrace();
        }
    }

    /**
     * 立即执行一个job
     *
     * @param jobName 任务名称
     * @param jobGroupName 任务组名
     */
    @Override
    public void runAJobNow(String jobName, String jobGroupName) {
    
    
        try {
    
    
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            scheduler.triggerJob(jobKey);
        } catch (SchedulerException scheduler) {
    
    
            scheduler.printStackTrace();
        }
    }

    /**
     * 获取所有计划中的任务列表
     *
     * @return
     */
    @Override
    public List<Map<String, Object>> queryAllJob() {
    
    
        List<Map<String, Object>> jobList = null;
        try {
    
    
            GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
            Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
            jobList = new ArrayList<Map<String, Object>>();
            for (JobKey jobKey : jobKeys) {
    
    
                List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                for (Trigger trigger : triggers) {
    
    
                    Map<String, Object> map = new HashMap<>();
                    map.put("jobName", jobKey.getName());
                    map.put("jobGroupName", jobKey.getGroup());
                    map.put("description", "触发器:" + trigger.getKey());
                    Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                    map.put("jobStatus", triggerState.name());
                    if (trigger instanceof CronTrigger) {
    
    
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        String cronExpression = cronTrigger.getCronExpression();
                        map.put("jobTime", cronExpression);
                    }
                    jobList.add(map);
                }
            }
        } catch (SchedulerException scheduler) {
    
    
            scheduler.printStackTrace();
        }
        return jobList;
    }

    /**
     * 获取所有正在运行的job
     *
     * @return
     */
    @Override
    public List<Map<String, Object>> queryRunJob() {
    
    
        List<Map<String, Object>> jobList = null;
        try {
    
    
            List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
            jobList = new ArrayList<Map<String, Object>>(executingJobs.size());
            for (JobExecutionContext executingJob : executingJobs) {
    
    
                Map<String, Object> map = new HashMap<String, Object>();
                JobDetail jobDetail = executingJob.getJobDetail();
                JobKey jobKey = jobDetail.getKey();
                Trigger trigger = executingJob.getTrigger();
                map.put("jobName", jobKey.getName());
                map.put("jobGroupName", jobKey.getGroup());
                map.put("description", "触发器:" + trigger.getKey());
                Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                map.put("jobStatus", triggerState.name());
                if (trigger instanceof CronTrigger) {
    
    
                    CronTrigger cronTrigger = (CronTrigger) trigger;
                    String cronExpression = cronTrigger.getCronExpression();
                    map.put("jobTime", cronExpression);
                }
                jobList.add(map);
            }
        } catch (SchedulerException scheduler) {
    
    
            scheduler.printStackTrace();
        }
        return jobList;
    }

    @Override
    public List<Map<String, Object>> queryJobByJobName(String jobName, String GroupName) {
    
    
        JobKey jobKey = new JobKey(jobName, GroupName);
        List<Map<String, Object>> jobList = new ArrayList<>();
        try {
    
    
            List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
            for (Trigger trigger : triggers) {
    
    
                Map<String, Object> map = new HashMap<>();
                map.put("jobName", jobKey.getName());
                map.put("jobGroupName", jobKey.getGroup());
                map.put("description", "触发器:" + trigger.getKey());
                Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                map.put("jobStatus", triggerState.name());
                if (trigger instanceof CronTrigger) {
    
    
                    CronTrigger cronTrigger = (CronTrigger) trigger;
                    String cronExpression = cronTrigger.getCronExpression();
                    map.put("jobTime", cronExpression);
                }
                jobList.add(map);
            }
        } catch (SchedulerException scheduler) {
    
    
            scheduler.printStackTrace();
        }
        return jobList;
    }

}

トウモロコシ式を生成する方法については、誰もがまだ頭の痛い問題を抱えていると思います。笑、私も同じです。同僚が提供した util をあげましょう。

package com.ywsoftware.oa.task.util;

import com.ywsoftware.oa.exceptions.InvalidParameterAppException;
import com.ywsoftware.oa.infrastructure.utils.DateHelper;

import java.util.Date;

// Cron生成工具
public class CronUtil {
    
    
    public static String getCornByTime(Date startAt, String timeType, Integer time) {
    
    
        String resultCorn;
        // 定时开始的分钟数
        String startAtMinute = DateHelper.ONLY_MINUTE_FORMAT.format(startAt);
        // 定时开始的小时数
        String startAtHour = DateHelper.ONLY_HOUR_FORMAT.format(startAt);
        // 定时开始的日数
        String startAtDay = DateHelper.ONLY_DAY_FORMAT.format(startAt);
        // 定时开始的月数
        String startAtMonth = DateHelper.ONLY_MONTH_FORMAT.format(startAt);
        // 定时开始的年数
        String startAtYear = DateHelper.ONLY_YEAR_FORMAT.format(startAt);
        // 年 月 日 周 时 分 秒
        switch (timeType) {
    
    
            // 当前时间类型位的/前的数字不能写死,应该用*,比如时间单位是每秒时,就秒位就是*/秒数,时间单位是每日时,就日位就是*/日数
            // 0/10 * * * * ? *  表示从0s开始,每10秒执行一次
            case "sec":
                if (time >= 60) {
    
    
                    throw new InvalidParameterAppException("秒数最大值59秒");
                }
                resultCorn = "*/" + String.valueOf(time) + " * * * * ? *";
                break;
            // 0 5/9 * * * ? *  表示从5分钟开始,每9分钟执行一次
            case "min":
                if (time >= 60) {
    
    
                    throw new InvalidParameterAppException("分钟数最大值59分钟");
                }
                resultCorn = "0 " + "*/" + String.valueOf(time) + " * * * ? *";
                break;
            // 0 0 */2 * * ? * 表示从现在开始,每2个小时执行一次
            case "hour":
                if (time >= 24) {
    
    
                    throw new InvalidParameterAppException("小时数最大值23小时");
                }
                resultCorn = "0 " + startAtMinute + " */" + String.valueOf(time) + " * * ? *";
                break;

            // 0/10 * * * * ? *  表示从0s开始,每10秒执行一次
            case "week":
                // TODO 每多少周执行一次定时任务  基本无用,而且开发难度偏大,目前支持的是每周的周几运行定时任务
                // 经理说可以不实现
                resultCorn = "";
                break;
            // 0 0 0 */1 * ? *  表示每1天执行一次
            case "day":
                if (time < 1 || time > 31) {
    
    
                    throw new InvalidParameterAppException("天数最小1天,最大31天");
                }
                resultCorn = "0 " + startAtMinute + " " + startAtHour + " */" + String.valueOf(time) + " * ? *";
                break;
            // 0 0 0 0 1/3 ?   表示从1月开始,每个3月执行一次
            case "month":
                if (time > 12) {
    
    
                    throw new InvalidParameterAppException("月数最大值12月");
                }
                resultCorn = "0 " + startAtMinute + " " + startAtHour + " " + startAtDay + " */" + String.valueOf(time) + " ?";
                break;
            case "year":
                resultCorn = "0 " + startAtMinute + " " + startAtHour + " " + startAtDay + " " + startAtMonth + " ?"
                        + " */" + String.valueOf(time);
                break;
            case "onetime":
                resultCorn = "0 " + startAtMinute + " " + startAtHour + " " + startAtDay + " " + startAtMonth + " ?"
                        + " " + startAtYear;
                break;
            default:
                resultCorn = "";
                break;
        }
        return resultCorn;
    }
}

おすすめ

転載: blog.csdn.net/weixin_42303757/article/details/106800733