spring-boot-route(二十一)quartz實現動態定時任務

Java旅途發表於2020-10-21

Quartz是一個定時任務的排程框架,涉及到的主要概念有以下幾個:

Scheduler:排程器,所有的排程都由它控制,所有的任務都由它管理。

Job:任務,定義業務邏輯。

JobDetail:基於Job,進一步封裝。其中關聯一個Job,併為Job指定更詳細的資訊。

Trigger:觸發器,可以指定給某個任務,指定任務的觸發機制。

一 建立簡單任務

1.1 Quartz依賴

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

1.2 建立任務

任務建立需要實現Job介面,重寫execute(JobExecutionContext jobExecutionContext)方法,增加定時任務的業務邏輯,這裡我只是簡單的列印一下定時任務執行。

@Slf4j
public class SimpleJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        log.info("job execute---"+new Date());
    }
}

1.3 JobDetail增加屬性

這裡增加的屬性可以在Job實現類中獲取,來處理業務。

JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class)
                                // 任務標識,及任務分組
                                .withIdentity("job1", "group1")
                                // 連結呼叫,增加需要的引數
                                .usingJobData("name","Java旅途")
                                .usingJobData("age",18)
                                .build();

1.4 Trigger實現

Trigger分為兩種,SimpleTriggerCronTriggerSimpleTrigger是根據Quartz的一些api實現的簡單觸發行為。CronTrigger用的比較多,使用cron表示式進行觸發。這裡先用SimpleTrigger來實現。

SimpleTrigger simpleTrigger = TriggerBuilder.newTrigger()
                                            .withIdentity("trigger1", "group1")
                                            // 立即執行
                                            .startNow()
                                            // 10s後停止
                                            .endAt(new Date(System.currentTimeMillis()+10*1000))
                                            .withSchedule(
                                            SimpleScheduleBuilder.simpleSchedule()
                                            // 每秒執行一次
                                            .withIntervalInSeconds(1)
                                            // 一直執行
                                            .repeatForever()
                                            ).build();

1.5 啟動任務

@Autowired
private Scheduler scheduler;

scheduler.scheduleJob(jobDetail,simpleTrigger);

1.6 執行效果

啟動專案後,任務立即執行,每秒執行一次,10s後停止,執行效果圖如下:

二 動態操作定時任務

有時候除了已經開發好的定時任務外,還需要我們手動去建立任務並且控制任務的執行。

2.1 建立任務

@GetMapping("create")
public void createJob(String jobName,String jobGroup,String cron,String triggerName,String triggerGroup) throws SchedulerException {

    JobKey jobKey = new JobKey(jobName,jobGroup);
    // 如果存在這個任務,則刪除
    if(scheduler.checkExists(jobKey)) {
        scheduler.deleteJob(jobKey);
    }

    JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class)
        .withIdentity(jobKey)
        .build();

    CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cron);

    Trigger trigger = TriggerBuilder.newTrigger()
        .withIdentity(triggerName,triggerGroup)
        .withSchedule(cronScheduleBuilder).build();
    scheduler.scheduleJob(jobDetail,trigger);
}

2.2 暫停任務

@GetMapping("pause")
public void pauseJob(String jobName,String jobGroup) throws SchedulerException {

    JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
    JobDetail jobDetail = scheduler.getJobDetail(jobKey);
    if (jobDetail == null) {
        return;
    }
    scheduler.pauseJob(jobKey);
}

2.3 恢復暫停的任務

@GetMapping("remuse")
public void remuseJob(String jobName, String jobGroup) throws SchedulerException {
    JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
    JobDetail jobDetail = scheduler.getJobDetail(jobKey);
    if (jobDetail == null) {
        return;
    }
    scheduler.resumeJob(jobKey);
}

2.4 刪除定時任務

@GetMapping("remove")
public void removeJob(String jobName, String jobGroup,String triggerName,String triggerGroup) throws SchedulerException {

    TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroup);
    JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
    Trigger trigger =  scheduler.getTrigger(triggerKey);
    if (trigger == null) {
        return;
    }
    // 停止觸發器
    scheduler.pauseTrigger(triggerKey);
    // 移除觸發器
    scheduler.unscheduleJob(triggerKey);
    // 刪除任務
    scheduler.deleteJob(jobKey);
}

三 任務持久化

Quartz預設使用RAMJobStore儲存方式將任務儲存在記憶體中,除了這種方式還支援使用JDBC將任務儲存在資料庫,為了防止任務丟失,我們一般會將任務儲存在資料庫中。

這裡使用mysql進行儲存,在quartz的原始碼包中找到檔案tables_mysql_innodb.sql,然後在客戶端進行執行sql檔案。如果嫌原始碼包不好下載的話,我已經將sql檔案上傳至GitHub了,可以直接訪問github拉去表結構,資料表如下:

3.1 增加mysql和jdbc依賴

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.11</version>
</dependency>

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

3.2 指定使用jdbc儲存

quartz預設使用memory儲存,這裡修改成jdbc進行儲存,並配置jdbc的相關資訊

spring:
  quartz:
    job-store-type: jdbc
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/simple_fast
    username: root
    password: root

3.3 建立任務

啟動專案,呼叫create介面建立任務,然後資料表中就會新增任務相關的資料了。


本文示例程式碼已上傳至github,點個star支援一下!

Spring Boot系列教程目錄

spring-boot-route(一)Controller接收引數的幾種方式

spring-boot-route(二)讀取配置檔案的幾種方式

spring-boot-route(三)實現多檔案上傳

spring-boot-route(四)全域性異常處理

spring-boot-route(五)整合swagger生成介面文件

spring-boot-route(六)整合JApiDocs生成介面文件

spring-boot-route(七)整合jdbcTemplate運算元據庫

spring-boot-route(八)整合mybatis運算元據庫

spring-boot-route(九)整合JPA運算元據庫

spring-boot-route(十)多資料來源切換

spring-boot-route(十一)資料庫配置資訊加密

spring-boot-route(十二)整合redis做為快取

spring-boot-route(十三)整合RabbitMQ

spring-boot-route(十四)整合Kafka

spring-boot-route(十五)整合RocketMQ

spring-boot-route(十六)使用logback生產日誌檔案

spring-boot-route(十七)使用aop記錄操作日誌

spring-boot-route(十八)spring-boot-adtuator監控應用

spring-boot-route(十九)spring-boot-admin監控服務

spring-boot-route(二十)Spring Task實現簡單定時任務

spring-boot-route(二十一)quartz實現動態定時任務

spring-boot-route(二十二)實現郵件傳送功能

spring-boot-route(二十三)開發微信公眾號

這個系列的文章都是工作中頻繁用到的知識,學完這個系列,應付日常開發綽綽有餘。如果還想了解其他內容,掃面下方二維碼告訴我,我會進一步完善這個系列的文章!

相關文章