1. 程式人生 > >基於Quartz的定時任務專案解析

基於Quartz的定時任務專案解析

準備寫一下quartz的使用流程、注意事項和原理,畢竟用了很久了,不總結就沒有提高。

用兩天時間建立一個quartz的專案,並根據專案做一下總結,並上傳專案原始碼供大家參考。

quartz的官網地址:http://www.quartz-scheduler.org/

API地址:http://www.quartz-scheduler.org/api/2.2.1/index.html

關於Quartz的介紹 和詳解可以看我的上一篇轉載的部落格,裡面介紹的非常詳細也非常清楚。https://mp.csdn.net/postedit/85157905

我們這篇就只講專案,專案上傳地址:https://github.com/tiedungao/quartz

專案的程式碼結構如下:

使用了:Spring Boot+mySql,相應的介面已經實現並通過了單元測試。本來想把前段配置和管理頁面也寫出來的,發現憑藉自己的前端知識去寫,畫出來的好醜,哈哈,希望前端好的同學能在github上完善完善。

我們下面簡單看一下截至當前時間的程式碼:

主要看service的程式碼。

package com.spring.quartz.service.impl;

import com.spring.quartz.service.QuartzService;
import com.spring.quartz.utils.SchedulerUtils;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

/**
 * @Author: 高鐵墩
 * @Description:
 * @Date: Create in 17:50 2018/12/23
 */
@Service
public class QuartzServiceImpl implements QuartzService {
    private static final Logger log = LoggerFactory.getLogger(QuartzServiceImpl.class);

    //預設任務組名稱
    public static final String DEFAULT_JOB_GROUP_NAME = "defaultJobGroup";
    //預設觸發器組名稱
    public static final String DEFAULT_TRIGGER_GROUP_NAME = "defaultTriggerGroup";

    private static Scheduler scheduler = SchedulerUtils.getScheduler();

    public void addJob(String jobName, Class<? extends Job> cls, String cronExpression){
        //定義JobDetail
        JobDetail jobDetail = newJob(cls).requestRecovery(true)
                .withIdentity(jobName,DEFAULT_JOB_GROUP_NAME)
                .build();
        //定義Trigger
        Trigger cronTrigger = newTrigger().withIdentity(jobName+"Trigger",DEFAULT_TRIGGER_GROUP_NAME)
                .startNow()
                .withSchedule(cronSchedule(cronExpression)
                        .withMisfireHandlingInstructionFireAndProceed())
                .forJob(jobDetail)
                .build();

        try {
            //根據jobDetail和cronTrigger建立任務
            scheduler.scheduleJob(jobDetail,cronTrigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.info("執行方法-addJob-時發生異常,異常資訊為:"+e.getMessage());
        }

    }

    public void addJobAndData(String jobName,Class<? extends Job> cls,String cronExpression, JobDataMap jobDataMap){

        //定義JobDetail
        JobDetail jobDetail = newJob(cls).requestRecovery(true)
                .usingJobData(jobDataMap)
                .withIdentity(jobName,DEFAULT_JOB_GROUP_NAME)
                .build();

        //定義Trigger
        Trigger cronTrigger = newTrigger().withIdentity(jobName+"Trigger",DEFAULT_TRIGGER_GROUP_NAME)
                .startNow()
                .withSchedule(cronSchedule(cronExpression)
                .withMisfireHandlingInstructionFireAndProceed())
                .forJob(jobDetail)
                .build();

        Scheduler scheduler = SchedulerUtils.getScheduler();

        try {
            scheduler.scheduleJob(jobDetail,cronTrigger);
        } catch (SchedulerException e) {
            log.info("執行方法-addJobAndData-時發生異常,異常資訊為:"+e.getMessage());
            e.printStackTrace();
        }
    }

    public void pauseJob(String jobName,String triggerGroupName) throws RuntimeException {
        try {
            if(null == triggerGroupName)
                scheduler.pauseTrigger(new TriggerKey(jobName+"Trigger",DEFAULT_TRIGGER_GROUP_NAME));
            else
                scheduler.pauseTrigger(new TriggerKey(jobName+"Trigger",triggerGroupName));
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.info("執行方法-pauseJob-時發生異常,異常資訊為:"+e.getMessage());
            throw new RuntimeException("在呼叫方法-pauseJob-停止任務"+jobName+"時發生異常,異常資訊為:"+e.getMessage());
        }
    }

    public void resumeJob(String jobName,String triggerGroupName){
        try {
            if(null == triggerGroupName)
                scheduler.resumeTrigger(new TriggerKey(jobName+"Trigger",DEFAULT_TRIGGER_GROUP_NAME));
            else
                scheduler.resumeTrigger(new TriggerKey(jobName+"Trigger",triggerGroupName));
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.info("執行方法-resumeJob-時發生異常,異常資訊為:"+e.getMessage());
            throw new RuntimeException("在呼叫方法-resumeJob-恢復任務"+jobName+"時發生異常,異常資訊為:"+e.getMessage());
        }
    }

    public void deleteJob(String jobName,String jobGroupName){
        try{
            if(null == jobGroupName)
                scheduler.deleteJob(JobKey.jobKey(jobName,DEFAULT_JOB_GROUP_NAME));
            else
                scheduler.deleteJob(JobKey.jobKey(jobName,jobGroupName));
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.info("執行方法deleteJob時發生異常,異常資訊為:"+e.getMessage());
            throw new RuntimeException("在呼叫方法-deleteJob-刪除任務"+jobName+"時發生異常,異常資訊為:"+e.getMessage());
        }
    }

    public void startJobs(){
        try {
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.info("執行方法-startJobs-時發生異常,異常資訊為:"+e.getMessage());
            throw new RuntimeException("在呼叫方法-startJobs-啟動任務時發生異常,異常資訊為:"+e.getMessage());
        }
    }

    public void shutdownJobs(){
        try {
            scheduler.shutdown();
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.info("執行方法-shutdownJobs-時發生異常,異常資訊為:"+e.getMessage());
            throw new RuntimeException("在呼叫方法-shutdownJobs-停止任務時發生異常,異常資訊為:"+e.getMessage());
        }
    }

}

專案裡有建表語句,可以根據自己的資料庫型別去執行相應的指令碼。

程式碼非常簡單,這裡不做解釋了,工程裡有單元測試類,修改一下資料庫連線配置就可以運行了,跑一跑就明白大致流程了。

在建立多個Job後,可以驗證工程的叢集部署,是可以達到負載均衡的,

當然有不明白的地方在下面留言也可以,這個專案很簡單,也有很多需要補充的地方,希望有感興趣的同學一起添磚添瓦。