1. 程式人生 > 實用技巧 >springboot + quartz + mysql 實現持久化分散式排程

springboot + quartz + mysql 實現持久化分散式排程

springboot + quartz + mysql 實現持久化分散式排程

  1. 官方文件:http://www.quartz-scheduler.org/documentation/quartz-2.3.0/
  2. 中文文件:https://www.w3cschool.cn/quartz_doc/quartz_doc-2put2clm.html

1. 獲取 sql 指令碼檔案,建立資料庫

在官網下載好包後,在 quartz-2.3.0-SNAPSHOT\src\org\quartz\impl\jdbcjobstore 目錄下可以選擇適合自己的資料庫指令碼檔案
我使用的資料庫是mysql,因此我也將sql指令碼放到了本專案的 resources

目錄下

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(190) NOT NULL,
JOB_GROUP VARCHAR(190) 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(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
JOB_NAME VARCHAR(190) NOT NULL,
JOB_GROUP VARCHAR(190) 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(190) 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(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) 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(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) 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(190) NOT NULL,
    TRIGGER_GROUP VARCHAR(190) 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(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) 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(190) 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(190) 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(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
INSTANCE_NAME VARCHAR(190) 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(190) NULL,
JOB_GROUP VARCHAR(190) 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(190) NOT NULL,
LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
CHECKIN_INTERVAL BIGINT(13) NOT NULL,
PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
ENGINE=InnoDB;

CREATE TABLE QRTZ_LOCKS (
SCHED_NAME VARCHAR(120) NOT NULL,
LOCK_NAME VARCHAR(40) NOT NULL,
PRIMARY KEY (SCHED_NAME,LOCK_NAME))
ENGINE=InnoDB;

CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);

CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);

CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);

commit;

2. 建立springboot專案,匯入maven依賴包

        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.4</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

3. 在 resources 目錄下建立 quartz 的配置檔案 quartz.properties

#quartz叢集配置
# ===========================================================================
# Configure Main Scheduler Properties 排程器屬性
# ===========================================================================
#排程標識名 叢集中每一個例項都必須使用相同的名稱
org.quartz.scheduler.instanceName=DefaultQuartzScheduler
#ID設定為自動獲取 每一個必須不同
org.quartz.scheduler.instanceid=AUTO
#============================================================================
# Configure ThreadPool
#============================================================================
#執行緒池的實現類(一般使用SimpleThreadPool即可滿足幾乎所有使用者的需求)
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
#指定執行緒數,至少為1(無預設值)(一般設定為1-100直接的整數合適)
org.quartz.threadPool.threadCount=25
#設定執行緒的優先順序(最大為java.lang.Thread.MAX_PRIORITY 10,最小為Thread.MIN_PRIORITY 1,預設為5)
org.quartz.threadPool.threadPriority=5
#============================================================================
# Configure JobStore
#============================================================================
# 資訊儲存時間 預設值60秒
org.quartz.jobStore.misfireThreshold=60000
#資料儲存方式為資料庫持久化
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
#資料庫代理類,一般org.quartz.impl.jdbcjobstore.StdJDBCDelegate可以滿足大部分資料庫
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#JobDataMaps是否都為String型別
org.quartz.jobStore.useProperties=false
#資料庫別名 隨便取
org.quartz.jobStore.dataSource=myDS
#表的字首,預設QRTZ_
org.quartz.jobStore.tablePrefix=QRTZ_
#是否加入叢集
org.quartz.jobStore.isClustered=true
#排程例項失效的檢查時間間隔
org.quartz.jobStore.clusterCheckinInterval=20000
#============================================================================
# Configure Datasources
#============================================================================
#資料庫引擎
org.quartz.dataSource.myDS.driver=com.mysql.cj.jdbc.Driver
#資料庫連線
org.quartz.dataSource.myDS.URL=jdbc:mysql://localhost:3306/quartz?characterEncoding=utf8&allowMultiQueries=true&useSSL=false&autoReconnect=true&serverTimezone=UTC
#資料庫使用者
org.quartz.dataSource.myDS.user=root
#資料庫密碼
org.quartz.dataSource.myDS.password=root
#允許最大連線
org.quartz.dataSource.myDS.maxConnections=5
#驗證查詢sql,可以不設定
org.quartz.dataSource.myDS.validationQuery=select 0 from dual

4. 註冊Quartz任務工廠(TaskJobFactory)

@Component
public class TaskJobFactory extends AdaptableJobFactory {
    @Autowired
    AutowireCapableBeanFactory capableBeanFactory;

    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        //呼叫父類的方法
        Object jobInstance = super.createJobInstance(bundle);
        //進行注入
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}

5. 註冊排程工廠,以及生成排程例項

若要在該服務啟動時,就執行排程任務,需要將 factory.setAutoStartup(false); 改為 factory.setAutoStartup(true);

@Configuration
public class QuartzConfig {
    @Autowired
    DataSource dataSource;

    @Autowired
    TaskJobFactory jobFactory;

    @Bean(name = "SchedulerFactory")
    public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
        //獲取配置屬性
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
        //在quartz.properties中的屬性被讀取並注入後再初始化物件
        propertiesFactoryBean.afterPropertiesSet();
        //建立SchedulerFactoryBean
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        //將配置檔案中的資訊新增到排程工廠中
        //對應java應用程式中的 new StdSchedulerFactory(properties)
        factory.setQuartzProperties(propertiesFactoryBean.getObject());
        factory.setJobFactory(jobFactory);
        // 預設的自動執行排程,這裡設定為不自動執行排程,
        // 為了方便擴充套件叢集分散式排程任務,這個服務只配置排程,另外啟動一個或多個服務執行排程
        factory.setAutoStartup(false);
        return factory;
    }

    /*
     * 通過SchedulerFactoryBean獲取Scheduler的例項
     */
    @Bean(name = "scheduler")
    public Scheduler scheduler() throws IOException, SchedulerException {
        Scheduler scheduler = schedulerFactoryBean().getScheduler();
        return scheduler;
    }
}

6. Quartz服務層介面(QuartzService)

public interface QuartzService {
    /**
     * 新增任務可以傳引數
     *
     * @param clazz
     * @param jobName
     * @param groupName
     * @param cronExp
     * @param param
     */
    void addJob(Class clazz, String jobName, String groupName, String cronExp, Map<String, Object> param);

    /**
     * 暫停任務
     *
     * @param name
     * @param groupName
     */
    void pauseJob(String name, String groupName);

    /**
     * 恢復任務
     *
     * @param name
     * @param groupName
     */
    void resumeJob(String name, String groupName);

    /**
     * 更新任務
     *
     * @param name
     * @param groupName
     * @param cronExp
     * @param param
     */
    void updateJob(String name, String groupName, String cronExp, Map<String, Object> param);

    /**
     * 刪除任務
     *
     * @param name
     * @param groupName
     */
    void deleteJob(String name, String groupName);

    /**
     * 啟動所有任務
     */
    void startAllJobs();

    /**
     * 關閉所有任務
     */
    void shutdownAllJobs();
}

7. 任務排程服務介面實現類(QuartzServiceImpl)

@Service
public class QuartzServiceImpl implements QuartzService {

    @Autowired
    Scheduler scheduler;


    /**
     * 建立job,可傳參
     *
     * @param clazz     任務類
     * @param name      任務名稱
     * @param groupName 任務所在組名稱
     * @param cronExp   cron表示式
     * @param param     map形式引數
     */
    @Override
    public void addJob(Class clazz, String name, String groupName, String cronExp, Map<String, Object> param) {
        try {
            // 啟動排程器
//            scheduler.start();
            //構建job資訊
            //((Job) clazz.newInstance()).getClass()
            JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(name, groupName).build();
            //表示式排程構建器(即任務執行的時間)
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExp);
            //按新的cronExpression表示式構建一個新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(name, groupName).withSchedule(scheduleBuilder).build();
            //獲得JobDataMap,寫入資料
            if (param != null) {
                trigger.getJobDataMap().putAll(param);
            }
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 暫停job
     *
     * @param name      任務名稱
     * @param groupName 任務所在組名稱
     */
    @Override
    public void pauseJob(String name, String groupName) {
        try {
            scheduler.pauseJob(JobKey.jobKey(name, groupName));
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 恢復job
     *
     * @param name      任務名稱
     * @param groupName 任務所在組名稱
     */
    @Override
    public void resumeJob(String name, String groupName) {
        try {
            scheduler.resumeJob(JobKey.jobKey(name, groupName));
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * job 更新,更新頻率和引數
     *
     * @param name      任務名稱
     * @param groupName 任務所在組名稱
     * @param cronExp   cron表示式
     * @param param     引數
     */
    @Override
    public void updateJob(String name, String groupName, String cronExp, Map<String, Object> param) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(name, groupName);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            if (cronExp != null) {
                // 表示式排程構建器
                CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExp);
                // 按新的cronExpression表示式重新構建trigger
                trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
            }

            //修改map
            if (param != null) {
                trigger.getJobDataMap().putAll(param);
            }
            // 按新的trigger重新設定job執行
            scheduler.rescheduleJob(triggerKey, trigger);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * job 刪除
     * <p>
     * 同時刪除 排程中的觸發器 Trigger 和任務 job
     *
     * @param name      任務名稱
     * @param groupName 任務所在組名稱
     */
    @Override
    public void deleteJob(String name, String groupName) {
        try {
            scheduler.pauseTrigger(TriggerKey.triggerKey(name, groupName));
            scheduler.unscheduleJob(TriggerKey.triggerKey(name, groupName));
            scheduler.deleteJob(JobKey.jobKey(name, groupName));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 啟動所有定時任務
     */
    @Override
    public void startAllJobs() {
        try {
            scheduler.start();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 關閉所有定時任務
     */
    @Override
    public void shutdownAllJobs() {
        try {
            if (!scheduler.isShutdown()) {
                // scheduler生命週期結束,無法再 start() 啟動
                scheduler.shutdown();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

8. 需要執行的任務(OrderTimeOutJob )

public class OrderTimeOutJob implements Job {
    @Override
    public void execute(JobExecutionContext context) {
        //獲取任務名
        String taskName = context.getJobDetail().getKey().getName();
        String groupName=context.getJobDetail().getKey().getGroup();
        System.out.println(String.format("task--->%s,%s",taskName,groupName));
        //todo:處理執行任務時的業務程式碼
    }
}

9. 編寫介面類進行測試(JobController)

@RestController
public class JobController {

    @Autowired
    QuartzService service;

    /**
     * 新增新任務
     *
     * @return
     */
    @RequestMapping("/addJob")
    public Object addJob(@RequestParam String groupName, @RequestParam String jobName) {
        Map<String, Object> resultMap = new HashMap<>();
        //任務組名
//        String groupName = "order3";
        //任務名
//        String jobName = "20190724120322389224";
        //CRON表示式
        String cronExp = "* * * * * ? *";
        service.addJob(OrderTimeOutJob.class, jobName, groupName, cronExp, null);
        resultMap.put("groupName", groupName);
        resultMap.put("jobName", jobName);
        resultMap.put("cronExp", cronExp);
        return resultMap;
    }

    /**
     * 啟動排程
     *
     * @return
     */
    @RequestMapping("/startAllJobs")
    public String startAllJobs() {
        service.startAllJobs();
        return "true";
    }

    /**
     * 關閉排程
     *
     * @return
     */
    @RequestMapping("/shutdownAllJobs")
    public String shutdownAllJobs() {
        service.shutdownAllJobs();
        return "true";
    }

    /**
     * 暫停某個排程
     *
     * @param groupName
     * @param jobName
     * @return
     */
    @RequestMapping("/pauseJob")
    public String pauseJob(@RequestParam String groupName, @RequestParam String jobName) {
        service.pauseJob(jobName, groupName);
        return "true";
    }

    /**
     * 恢復排程某個暫停的任務
     *
     * @param groupName
     * @param jobName
     * @return
     */
    @RequestMapping("/resumeJob")
    public String resumeJob(@RequestParam String groupName, @RequestParam String jobName) {
        service.resumeJob(jobName, groupName);
        return "true";
    }

    /**
     * 刪除任務
     *
     * @return
     */
    @RequestMapping("/delJob")
    public Object delJob(@RequestParam String groupName, @RequestParam String jobName) {
        Map<String, Object> resultMap = new HashMap<>();
        //任務組名
        //任務名
        service.deleteJob(jobName, groupName);
        resultMap.put("groupName", groupName);
        resultMap.put("jobName", jobName);
        return resultMap;
    }
}

10. 最後新增配置檔案 application.yml,啟動專案

spring:
  application:
    name: quartz
  datasource:
    url: jdbc:mysql://localhost:3306/quartz?characterEncoding=utf8&allowMultiQueries=true&useSSL=false&autoReconnect=true&serverTimezone=UTC
    username: root
    password: root

總結

  1. 若需要隨著上面專案的啟動,就執行排程任務,需要將步驟5中 factory.setAutoStartup(false); 改為 factory.setAutoStartup(true);,或者直接刪除 factory.setAutoStartup(false);
  2. 為了保證排程的高可用,重新建立一個或多個新專案用來執行排程,新專案中只需要配置上面的 2~5 步驟即可
    ,第五步將 factory.setAutoStartup(false); 改為 factory.setAutoStartup(true);,或者直接刪除 factory.setAutoStartup(false);

程式碼倉庫地址:https://github.com/1612480331/quartz