天天看點

springboot內建quartz(一)基礎概念

springboot內建quartz

一,quartz基本概念

1.Job

Job,JobDetail,JobBuilder,JobExecutionContext

Job?

job英文單詞的意思就是工作,意味着你需要排程器具體要做的事情,job是一個工作任務排程的接口,具體要被排程的任務要實作該接口,重寫該接口定義的execute方法(具體任務)編寫任務的業務邏輯。

job執行個體在Quartz中的生命周期:每次排程器執行job時,他在調用execute方法前都會建立一個job執行個體,調用方法完成後,關聯的job執行個體被釋放,然後垃圾回收。(即每次job的構造方法都會被執行)

jobDetail?

通過傳入job類型,JobBuilder會産生jobDetail執行個體,jobDetail存儲着該類型的job的一些執行個體資訊,排程器需要借助jobDetail來添加job執行個體

重要資訊:

  • name:任務名稱
  • group:任務組名稱(會有預設組名)
  • jobDataMap
JobExecutionContext?

排程器在調用一個job的execute方法時,會将JobExecutionContext傳遞給該方法,job通過該JobExecutionContext對象可以通路到Quartz運作時候得環境和job本身的明細資料(job帶有的資訊)

JobBuilder?

jobDetail生成器

補充

  • @DisallowConcurrentExecution:相同的jobDetail不能并發執行,不同的jobDetail可以并發執行,
  • @PersistJobDataAfterExecution:将該注解加在job類上,告訴Quartz在成功執行了job類的execute方法後(沒有發生任何異常),更新JobDetail中JobDataMap的資料,使得該job(即JobDetail)在下一次執行的時候,JobDataMap中是更新後的資料,而不是更新前的舊資料

示例:

//由job類生産jobDetail
        JobDetail jobDetail = newJob(TestJob.class) //産生Job執行個體,job資訊存儲在jobDetail中
                .usingJobData("key1","val1")//通過jobDataMap為job執行個體增加屬性,然後再傳遞到排程器中去
                .usingJobData("key2","val2")
                .withIdentity("helloTask","task1")
                .build();//由jobBuilder生成jobDetail      

2.Trigger

觸發器

相關屬性

  • jobKey屬性:當trigger觸發時被執行的job的身份;
  • startTime屬性:設定trigger第一次觸發的時間;該屬性的值是java.util.Date類型,表示某個指定的時間點
  • endTime屬性:表示trigger失效的時間點。
  • 優先級(priority)如果你的trigger很多(或者Quartz線程池的工作線程太少),Quartz可能沒有足夠的資源同時觸發所有的trigger;這種情況下,你可能希望控制哪些trigger優先使用Quartz的工作線程,要達到該目的,可以在trigger上設定priority屬性。比如,你有N個trigger需要同時觸發,但隻有Z個工作線程,優先級最高的Z個trigger會被首先觸發。如果沒有為trigger設定優先級,trigger使用預設優先級,值為5;priority屬性的值可以是任意整數,正數、負數都可以。注意:隻有同時觸發的trigger之間才會比較優先級。10:59觸發的trigger總是在11:00觸發的trigger之前執行。如果trigger是可恢複的,在恢複後再排程時,優先級與原trigger是一樣的。

常用的觸發器

SimpleTrigger

SimpleTrigger可以滿足的排程需求是:在具體的時間點執行一次,或者在具體的時間點執行,并且以指定的間隔重複執行若幹次。

示例:

//SimpleTrigger
        SimpleTrigger simpleTrigger = (SimpleTrigger) newTrigger()
                .withIdentity("trigger1","group1")//觸發器辨別
                .startAt(startTime)//開始觸發時間
                .forJob("helloTask","task1")//綁定的任務組
                .withSchedule(simpleSchedule()//排程設定
                    .withRepeatCount(10)//重複次數
                    .withIntervalInMilliseconds(10))//執行頻率
                .endAt(endTime)//結束時間
                .build();      
CronTrigger

CronTrigger通常比Simple Trigger更有用,如果您需要基于月曆的概念而不是按照SimpleTrigger的精确指定間隔進行重新啟動的作業啟動計劃。使用CronTrigger,您可以指定号時間表,例如“每周五中午”或“每個工作日和上午9:30”,甚至“每周一至周五上午9:00至10點之間每5分鐘”和1月份的星期五“。

即使如此,和SimpleTrigger一樣,CronTrigger有一個startTime,它指定何時生效,以及一個(可選的)endTime,用于指定何時停止計劃。

CronTrigger重點就是cron表達式,類似于spring自帶的定時器中的cron表達式

可以參考這個:​​​spring自帶定時器​​

示例:

//CronTrigger
        CronTrigger cronTrigger = (CronTrigger) newTrigger()
                .withIdentity("trigger2","group2")//觸發器辨別
                .startAt(startTime)//開始觸發時間
                .forJob("helloTask1","task2")//綁定的任務組
                .withSchedule(cronSchedule("0 42 10 * * ?")//cron表達式 --- 每天10點42分執行
                        .withMisfireHandlingInstructionFireAndProceed())//錯過觸發 -- 一般是智能模式
                .endAt(endTime)//結束時間
                .build();      

3.Scheduler

配置好任務器和觸發器就可以開始排程了

排程器工廠(SchedulerFactory)

所有的排程器示例都需要經過SchedulerFactory建立,而SchedulerFactory是根據quartz.properties檔案定義的屬性來建立和初始化Quartz Scheduler

org.quartz.scheduler.instanceName: DefaultQuartzScheduler
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false

org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true

org.quartz.jobStore.misfireThreshold: 60000

org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore      

示例:

//擷取排程工廠
        SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
        //從工廠中擷取排程器
        Scheduler sched = schedFact.getScheduler();
        //開始排程
        sched.start();
        //挂起
        //sched.standby();
        //關閉任務排程
        //1.等待目前任務執行完畢在關閉任務排程
        //sched.shutdown(true);
        //2.直接關閉任務排程
        //sched.shutdown(false);
        //傳入排程任務和任務觸發器
        sched.scheduleJob(jobDetail,simpleTrigger);      

監聽器

1.任務監聽器

/**
 * @Description:    任務監聽器
 * @Author:         Kevin
 * @CreateDate:     2019/5/8 2:37
 * @UpdateUser:     Kevin
 * @UpdateDate:     2019/5/8 2:37
 * @UpdateRemark:   修改内容
 * @Version: 1.0
 */
public class TestJobListener implements JobListener {

    /**
     * 擷取監聽器名
     * @return
     */
    @Override
    public String getName() {
        return null;
    }

    /**
     * 執行任務前調用
     * @param jobExecutionContext
     */
    @Override
    public void jobToBeExecuted(JobExecutionContext jobExecutionContext) {

    }

    /**
     * 執行任務前,但是該任務被拒絕執行時調用
     * @param jobExecutionContext
     */
    @Override
    public void jobExecutionVetoed(JobExecutionContext jobExecutionContext) {

    }

    /**
     * 執行任務後調用
     * @param jobExecutionContext
     * @param e
     */
    @Override
    public void jobWasExecuted(JobExecutionContext jobExecutionContext, JobExecutionException e) {

    }
}      
//全局任務監聽配置
        sched.getListenerManager().addJobListener(new TestJobListener(), EverythingMatcher.allJobs());
        //局部任務監聽配置
        sched.getListenerManager().addJobListener(new TestJobListener(), KeyMatcher.keyEquals(new JobKey("helloTask","task1")));      

完整代碼:

public static void test(Date startTime,Date endTime) throws SchedulerException {
        //由job類生産jobDetail
        JobDetail jobDetail = newJob(TestJob.class) //産生Job執行個體,job資訊存儲在jobDetail中
                .usingJobData("key1","val1")//通過jobDataMap為job執行個體增加屬性,然後再傳遞到排程器中去
                .usingJobData("key2","val2")
                .withIdentity("helloTask","task1")
                .build();//由jobBuilder生成jobDetail

        //SimpleTrigger
        SimpleTrigger simpleTrigger = (SimpleTrigger) newTrigger()
                .withIdentity("trigger1","group1")//觸發器辨別
                .startAt(startTime)//開始觸發時間
                .forJob("helloTask","task1")//綁定的任務組
                .withSchedule(simpleSchedule()//排程設定
                    .withRepeatCount(10)//重複次數
                    .withIntervalInMilliseconds(10))//執行頻率
                .endAt(endTime)//結束時間
                .build();

        //CronTrigger
        CronTrigger cronTrigger = (CronTrigger) newTrigger()
                .withIdentity("trigger2","group2")//觸發器辨別
                .startAt(startTime)//開始觸發時間
                .forJob("helloTask1","task2")//綁定的任務組
                .withSchedule(cronSchedule("0 42 10 * * ?")//cron表達式 --- 每天10點42分執行
                        .withMisfireHandlingInstructionFireAndProceed())//錯過觸發 -- 一般是智能模式
                .endAt(endTime)//結束時間
                .build();

        //擷取排程工廠
        SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
        //從工廠中擷取排程器
        Scheduler sched = schedFact.getScheduler();
        //開始排程
        sched.start();
        //挂起
        //sched.standby();
        //關閉任務排程
        //1.等待目前任務執行完畢在關閉任務排程
        //sched.shutdown(true);
        //2.直接關閉任務排程
        //sched.shutdown(false);
        //傳入排程任務和任務觸發器
        sched.scheduleJob(jobDetail,simpleTrigger);

        //全局任務監聽配置
        sched.getListenerManager().addJobListener(new TestJobListener(), EverythingMatcher.allJobs());
        //局部任務監聽配置
        sched.getListenerManager().addJobListener(new TestJobListener(), KeyMatcher.keyEquals(new JobKey("helloTask","task1")));
    }