SpringBoot系列記錄(九)————Springboot整合Quartz

1、Quartz核心概念

首先我們需要明白 Quartz 的幾個核心概念,這樣理解起 Quartz 的原理就會變得簡單了。

  1. Job 表示一個工作,要執行的具體內容。此接口中只有一個方法,如下:void execute(JobExecutionContext context) 
  2. JobDetail 表示一個具體的可執行的調度程序,Job 是這個可執行程調度程序所要執行的內容,另外 JobDetail 還包含了這個任務調度的方案和策略。
  3. Trigger 代表一個調度參數的配置,什麼時候去調。
  4. Scheduler 代表一個調度容器,一個調度容器中可以註冊多個 JobDetail 和 Trigger。當 Trigger 與 JobDetail 組合,就可以被 Scheduler 容器調度了

2、具體分析

2.1 Job其實由三部分組成:

  •       JobDetail: 用於描述這個Job是做什麼的
  •       一個實現Job接口的類:告訴Quartz具體幹什麼活的
  •      JobDataMap: 給 Job 提供參數用的
JobDetail jobDetail = newJob(TestJob.class)
                .withIdentity("job1","group2")
                .usingJobData("test","sparrow")
                .build();

可以看到我們在創建JobDetail的時候,將要執行的job的類名傳給了JobDetail,所以scheduler就知道了要執行何種類型的job。每次當scheduler執行job時,在調用其execute(…)方法之前會創建該類的一個新的實例;執行完畢,對該實例的引用就被丟棄了,實例會被垃圾回收;

這種執行策略帶來的一個後果是,job必須有一個無參的構造函數(當使用默認的JobFactory時);另一個後果是,在job類中,不應該定義有狀態的數據屬性,因爲在job的多次執行中,這些屬性的值不會保留,那這個時候JobDataMap就可以幹活了,JobDataMap中可以包含不限量的(序列化的)數據對象,在job實例執行的時候,可以使用其中的數據。

JobDataMap 除了像上面使用usingJobData 方式之外,還可以

 jobDetail.getJobDataMap().put("test","testOne");

2.2 常用的兩種Trigger

Trigger 就是觸發器的意思,用來指定什麼時間開始觸發,觸發多少次,每隔多久觸發一次。最常用SimpleTriggerCronTrigger這兩種。

2.2.1、SimpleTrigger

Trigger trigger = newTrigger().withIdentity("myTrigger","group1")
                .startNow()
                .withSchedule(simpleSchedule()
                        .withIntervalInSeconds(5)
                        .withRepeatCount(10))
                .build();

SimpleTrigger的屬性包括:開始時間、結束時間、重複次數以及重複的間隔;上面這段代碼的意思就是從現在開始,每隔5s執行一次,一共執行10次。

重複次數,可以是0、正整數,以及常量SimpleTrigger.REPEAT_INDEFINITELY。重複的間隔,必須是0,或者long型的正數,表示毫秒。注意,如果重複間隔爲0,trigger將會以重複次數併發執行(或者以scheduler可以處理的近似併發數)。

定義開始時間,比如下方代碼:5s後開始     對應的結束使用endAt

 Date startTime = DateBuilder.futureDate(5, DateBuilder.IntervalUnit.SECOND);
        Trigger trigger1 = newTrigger().withIdentity("myTrigger","group1")
                .startAt(startTime)
                .build();

2.2.2、CronTrigger

使用CronTrigger最主要的就是Cron表達式,關於表達式後面會專門寫一篇博文,這裏直接放個例子了,每天上午10點42觸發

trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(dailyAtHourAndMinute(10, 42))
    .forJob("myJob", "group1")
    .build();

或者

trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(cronSchedule("0 42 10 * * ?"))
    .forJob("myJob", "group1")
    .build();

3、Springboot整合Quartz

以上只是簡單地介紹了Quartz,好在整合過程中有個過度,更多內容可以查看Quartz相關資料

pom.xml

    <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.0</version>
        </dependency>

 業務代碼

public class TestJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        JobDetail jobDetail = jobExecutionContext.getJobDetail();
        String test = jobDetail.getJobDataMap().getString("test");
        System.out.println(test+new Date());
    }
}

測試類:

 @Test
    public void testThree() throws Exception{
        //創建調度器
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        //定義一個觸發器
        Trigger trigger = newTrigger().withIdentity("myTrigger","group1")
                .startNow()
                .withSchedule(simpleSchedule()
                        .withIntervalInSeconds(5)
                        .withRepeatCount(5))
                .build();
        //定義一個JobDetail
        JobDetail jobDetail = newJob(TestJob.class)
                .withIdentity("job1","group2")
                .usingJobData("test","sparrow")
                .build();
        //調度加入這個job
        scheduler.scheduleJob(jobDetail,trigger);
        //啓動
        scheduler.start();
        //等待任務執行完再關閉
        Thread.sleep(20000);
        scheduler.shutdown(true);
    }

執行結果:

 擴展:實際應用

以上只是測試了一下是否可用,下面來個實際應用的例子:

先創建一個任務類,具體的業務邏輯根據實際情況來,我這裏是系統給我發送一個郵件

public class DailyMailJob implements Job {

    Logger logger = LoggerFactory.getLogger(DailyMailJob.class);

    @Autowired
    IMailService mailService;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        String content = "花有重開之日,人無再少年,走好腳下的路,筆直看眼前";
        mailService.sendSimpleMail("[email protected]", Constant.DAILY_SUBJECT,content);
        logger.info("----------------郵件已發送----------------");
    }
}

再寫個任務調度配置類    這裏只是簡單舉個例子

@Configuration
public class SchedulerConfig {

    @Autowired
    Scheduler scheduler;

    @Bean
    public void startJob() throws SchedulerException {
        customJobOne(scheduler);
        //啓動
        scheduler.start();
    }

   private void customJobOne(Scheduler scheduler) throws SchedulerException {
       //創建調度器
       //Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
       //定義一個觸發器
       Trigger trigger = newTrigger().withIdentity("mailTriggerOne","mailGroup")
               .startNow()
               .withSchedule(cronSchedule("0 36 16 * * ?"))
               .build();
       //定義一個JobDetail
       JobDetail jobDetail = newJob(DailyMailJob.class)
               .withIdentity("mailJobOne","JobGroup")
               .build();
       //調度加入這個job
       scheduler.scheduleJob(jobDetail,trigger);
   }
}

 結果:

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章