1. 程式人生 > >SpringBoot2.1 - Quartz自動化配置整合 yml方式配置免配置類和properties

SpringBoot2.1 - Quartz自動化配置整合 yml方式配置免配置類和properties

首先非常感謝原作者恆宇少年 ,寫了一遍好文章。找了很多文章終於找到比較有用有價值的高質量博文。

原貼地址:https://www.jianshu.com/p/056281e057b3

 

以下引用原文章。

在新版本的SpringBoot2.0釋出後,急迫嚐鮮的我將相關的專案已經更換為最新版本,在SpringBoot原始碼GitHub看到更新日誌,表明了針對Quartz新版本進行了 AutoConfiguration自動化配置,省去了很多繁瑣的配置。

官網更新日誌

Auto-configuration support is now include for the

Quartz Scheduler. We’ve also added a new spring-boot-starter-quartz starter POM.
You can use in-memory JobStores, or a full JDBC-based store. All JobDetail, Calendar and Trigger beans from your Spring application context will be automatically registered with the Scheduler.
For more details read the new
"Quartz Scheduler" section
of the reference documentation.

SpringBoot2.0版本集成了Quartz2.3.0官網最新版本。

本章目標

使用SpringBoot2.0新特性完成Quartz自動化配置。

SpringBoot 企業級核心技術學習專題


專題 專題名稱 專題描述
001 Spring Boot 核心技術 講解SpringBoot一些企業級層面的核心元件
002 Spring Boot 核心技術章節原始碼
Spring Boot 核心技術簡書每一篇文章碼雲對應原始碼
003 Spring Cloud 核心技術 對Spring Cloud核心技術全面講解
004 Spring Cloud 核心技術章節原始碼 Spring Cloud 核心技術簡書每一篇文章對應原始碼
005 QueryDSL 核心技術 全面講解QueryDSL核心技術以及基於SpringBoot整合SpringDataJPA
006 SpringDataJPA 核心技術 全面講解SpringDataJPA核心技術
007 SpringBoot核心技術學習目錄 SpringBoot系統的學習目錄,敬請關注點贊!!!

構建專案

在前面章節第四十章:基於SpringBoot & Quartz完成定時任務分散式多節點負載持久化內我們已經通過新增配置的方式完成整合,為了本章的方便直接複製之前的專案,在基礎上進行修改。
開啟pom.xml配置檔案,SpringBoot為我們提供了對應的依賴,我們將之前的quartz相關依賴刪除,替換為spring-boot-starter-quartz,如下所示:

<!--quartz相關依賴-->
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>${quartz.version}</version>
</dependency>
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz-jobs</artifactId>
    <version>${quartz.version}</version>
</dependency>
>>>>替換為:>>>>
<!--quartz依賴-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
......

刪除QuartzConfiguration配置類

在之前章節我們使用QuartzConfiguration配置類來完成了Quartz需要的一系列配置,如:JobFactorySchedulerFactoryBean等,在我們新增spring-boot-starter-quartz依賴後就不需要主動宣告工廠類,因為spring-boot-starter-quartz已經為我們自動化配置好了。

自動化配置原始碼

我們找到IdeaExternal Libraries並且展開spring-boot-autoconfigure-2.0.0.RELEASE.jar,找到org.springframework.boot.autoconfigure.quartz,該目錄就是SpringBoot為我們提供的Quartz自動化配置原始碼實現,在該目錄下有如下所示幾個類:

  • AutowireCapableBeanJobFactory
    該類替代了我們之前在QuartzConfiguration配置類的AutowiringSpringBeanJobFactory內部類實現,主要作用是我們自定義的QuartzJobBean子類被Spring IOC進行託管,可以在定時任務類內使用注入任意被Spring IOC託管的類。
  • JobStoreType
    該類是一個列舉型別,定義了對應application.ymlapplication.properties檔案內spring.quartz.job-store-type配置,其目的是配置quartz任務的資料儲存方式,分別為:MEMORY(記憶體方式:預設)、JDBC(資料庫方式)。
  • QuartzAutoConfiguration
    該類是自動配置的主類,內部配置了SchedulerFactoryBean以及JdbcStoreTypeConfiguration,使用QuartzProperties作為屬性自動化配置條件。
  • QuartzDataSourceInitializer
    該類主要用於資料來源初始化後的一些操作,根據不同平臺型別的資料庫進行選擇不同的資料庫指令碼。
  • QuartzProperties
    該類對應了spring.quartzapplication.ymlapplication.properties檔案內開頭的相關配置。
  • SchedulerFactoryBeanCustomizer
    這是一個介面,我們實現該介面後並且將實現類使用Spring IOC託管,可以完成SchedulerFactoryBean的個性化設定,這裡的設定完全可以對SchedulerFactoryBean做出全部的設定變更。

spring.quartz配置

看到QuartzAutoConfiguration類原始碼,我們知道了,想要使用自動化配置,需要滿足QuartzProperties屬性配置類的初始化,所以我們需要再application.ymlapplication.properties配置檔案內新增對應的配置資訊,如下所示:

spring:
  quartz:
    #相關屬性配置
    properties:
      org:
        quartz:
          scheduler:
            instanceName: clusteredScheduler
            instanceId: AUTO
          jobStore:
            class: org.quartz.impl.jdbcjobstore.JobStoreTX
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
            tablePrefix: QRTZ_
            isClustered: true
            clusterCheckinInterval: 10000
            useProperties: false
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool
            threadCount: 10
            threadPriority: 5
            threadsInheritContextClassLoaderOfInitializingThread: true
    #資料庫方式
    job-store-type: jdbc
    #初始化表結構
    #jdbc:
      #initialize-schema: never
  • spring.quartz.properties
    該配置其實代替了之前的quartz.properties,我們把之前quartz.properties配置檔案內的所有配置轉換成YUML風格,對應的新增在該配置下即可,在QuartzAutoConfiguration類內,會自動呼叫SchedulerFactoryBeansetQuartzProperties方法,把spring.quartz.properties內的所有配置進行設定。
@Bean
@ConditionalOnMissingBean
public SchedulerFactoryBean quartzScheduler() {
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        schedulerFactoryBean.setJobFactory(new AutowireCapableBeanJobFactory(this.applicationContext.getAutowireCapableBeanFactory()));
        // 如果配置了spring.quartz.properties
        if (!this.properties.getProperties().isEmpty()) {
        //  將所有properties設定到QuartzProperties
            schedulerFactoryBean.setQuartzProperties(this.asProperties(this.properties.getProperties()));
        }
......省略部分程式碼
  • spring.quartz.job-store-type
    設定quartz任務的資料持久化方式,預設是記憶體方式,我們這裡沿用之前的方式,配置JDBC以使用資料庫方式持久化任務。
  • spring.quartz.jdbc.initialize-schema

該配置目前版本沒有生效,根據官網文件檢視,其目的是自動將quartz需要的資料表通過配置方式進行初始化。

測試

  1. 啟動專案
  2. 開啟瀏覽器訪問http://localhost:8083/good/save?name=abcd&unit=斤&price=12.5進行新增定時任務
  3. 檢視控制檯輸出
 22:55:18.812  INFO 17161 --- [           main] c.hengyu.chapter39.Chapter47Application  : 【【【【【【定時任務分散式節點 - quartz-cluster-node-second 已啟動】】】】】】
2018-03-06 22:55:20.772  INFO 17161 --- [uartzScheduler]] o.s.s.quartz.SchedulerFactoryBean        : Starting Quartz Scheduler now, after delay of 2 seconds
2018-03-06 22:55:20.793  INFO 17161 --- [uartzScheduler]] org.quartz.core.QuartzScheduler          : Scheduler quartzScheduler_$_yuqiyudeMacBook-Pro.local1520348117910 started.
2018-03-06 22:56:20.103  INFO 17161 --- [nio-8083-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2018-03-06 22:56:20.103  INFO 17161 --- [nio-8083-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2018-03-06 22:56:20.121  INFO 17161 --- [nio-8083-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 18 ms
Hibernate: select next_val as id_val from hibernate_sequence for update
Hibernate: update hibernate_sequence set next_val= ? where next_val=?
Hibernate: insert into basic_good_info (bgi_name, bgi_price, bgi_unit, bgi_id) values (?, ?, ?, ?)
2018-03-06 22:56:20.268 TRACE 17161 --- [nio-8083-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [abcd]
2018-03-06 22:56:20.269 TRACE 17161 --- [nio-8083-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [NUMERIC] - [12.5]
2018-03-06 22:56:20.269 TRACE 17161 --- [nio-8083-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [3] as [VARCHAR] - [斤]
2018-03-06 22:56:20.269 TRACE 17161 --- [nio-8083-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [4] as [BIGINT] - [1]
2018-03-06 22:56:47.253  INFO 17161 --- [eduler_Worker-1] c.h.c.timers.GoodStockCheckTimer         : 分散式節點quartz-cluster-node-second,執行庫存檢查定時任務,執行時間:Tue Mar 06 22:56:47 CST 2018
2018-03-06 22:57:00.012  INFO 17161 --- [eduler_Worker-2] c.h.c.timers.GoodStockCheckTimer         : 分散式節點quartz-cluster-node-second,執行庫存檢查定時任務,執行時間:Tue Mar 06 22:57:00 CST 2018
2018-03-06 22:57:20.207  INFO 17161 --- [eduler_Worker-3] c.hengyu.chapter39.timers.GoodAddTimer   : 分散式節點quartz-cluster-node-second,商品新增完成後執行任務,任務時間:Tue Mar 06 22:57:20 CST 2018
2018-03-06 22:57:30.013  INFO 17161 --- [eduler_Worker-4] c.h.c.timers.GoodStockCheckTimer         : 分散式節點quartz-cluster-node-second,執行庫存檢查定時任務,執行時間:Tue Mar 06 22:57:30 CST 2018
2018-03-06 22:58:00.014  INFO 17161 --- [eduler_Worker-5] c.h.c.timers.GoodStockCheckTimer         : 分散式節點quartz-cluster-node-second,執行庫存檢查定時任務,執行時間:Tue Mar 06 22:58:00 CST 2018

根據控制檯內容,可以看到我們的定時任務已經正常的開始執行,當然我們如果開啟多個節點同樣可以實現任務自動漂移的效果。

總結

綜上所述我們已經完成了SpringBoot2.0整合Quartz,我們只需要新增依賴、新增配置即可,別的不需要做任何程式碼編寫。



作者:恆宇少年
連結:https://www.jianshu.com/p/056281e057b3
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。

 

 

我來說說我自己的背景

springboot 2.1.0版本 

同樣也是集成了quartz的2.3.0版本

 

 

我的yml配置

 

    這裡我已經是通過了持久化的測試,在2.0往後的quartz的整合中,是不需要讓你去再配datasourse的。之前看了幾篇文章,各種在properties中配自定義的datasourse,然後配置驅動什麼的。按照那種方式的配置應該也是在spring boot1.5中的做法。

    我這裡把jobStore和job-store-type註釋掉的原因是因為,我在開發環境下我是希望我每次重新啟動專案的時候job都可以在執行的時候重新的執行第一次,因為我是要每兩個小時獲取微信的AccessToken的場景下面,如果是持久化到資料庫的話

    比如定時7200秒執行一次,現在時間是中午12點,他就會在你這個啟動的時間去執行一次,然後下次的執行時間是下午2點。在12-2點的時間內不管你專案怎麼啟動 他都不會重複的去執行,他只認2點鐘這個時間點執行。

     再比如你是在開發中1點50分的時候關閉了程式,沒有啟動,而你在2點零1分的時候啟動了專案,那麼你啟動這個專案的時候也是不會幫你去執行任務的,因為他只認2點鐘的時候,2點的時候你程式沒有啟動,所以他不會幫你重新的回過頭,對於任務來說那麼下次的執行時間就是下午4點鐘。你要想任務式執行的那麼你就要保持服務是開啟的。

 所以我在開發環境下面把持久化到資料庫的配置先登出掉,儲存在記憶體中,這樣每次專案啟動的時候都能保證任務執行一次。適合專案在初始化的時候就需要執行任務的場景。

 

因為原作者對配置的東西講的已經比較詳細了,我就不過多說了,我最後會貼上sql語句,只要是配置好了你的datasourse不需要再quartz中再次配置了,就可以自動成功持久化資料庫了。

我就在貼出一下 需要用到和我一樣需求的在專案初始化的時候就開始執行的一種方式。

  • 方式一:使用cron表示式來建立任務。(不建議在開發環境中使用)
package com.atao.zowei.job;

import com.atao.zowei.util.QuartzManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class InitializationJobManage {
//    @Autowired
//    QuartzManager quartzManager;

    /**
     * 持久化在資料庫的時候用cron表示式的話,jobName是不能重複的,在正式伺服器環境下可以使用這種方式,在開發環境下建議使用simpleSchedule
     */
//    @Bean
//    public void Initialization(){
//        quartzManager.addJob(WeiXinAccessTokenJob.class.getName(),WeiXinAccessTokenJob.class,"0 0 0/2 * * ? ");
//    }

}

 

下面貼上我修改過的封裝好的適合springboot使用的 quartz的工具類

在工具類中使用作者的方法自動注入了Scheduler排程器。可以實現任務的增加,修改,停止,移除。

package com.atao.zowei.util;

import java.util.Map;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 定時任務管理類
 *
 * @author ataopro
 * @editdate 2018-11-30
 */
@Component
public class QuartzManager {
    /**
     * 注入任務排程器
     */
    @Autowired
    private Scheduler sched;
    private static String JOB_GROUP_NAME = "ATAO_JOBGROUP";                    //任務組
    private static String TRIGGER_GROUP_NAME = "ATAO_TRIGGERGROUP";            //觸發器組

    /**
     * 新增一個定時任務,使用預設的任務組名,觸發器名,觸發器組名
     *
     * @param jobName 任務名
     * @param cls     任務
     * @param time    時間設定,參考quartz說明文件
     */
    public void addJob(String jobName, Class<? extends Job> cls, String time) {
        try {
            JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(jobName, JOB_GROUP_NAME).build();    //用於描敘Job實現類及其他的一些靜態資訊,構建一個作業例項
            CronTrigger trigger = TriggerBuilder
                    .newTrigger()                                                                        //建立一個新的TriggerBuilder來規範一個觸發器
                    .withIdentity(jobName, TRIGGER_GROUP_NAME)                                            //給觸發器起一個名字和組名
                    .withSchedule(CronScheduleBuilder.cronSchedule(time))
                    .build();
            sched.scheduleJob(jobDetail, trigger);
            if (!sched.isShutdown()) {
                sched.start();      // 啟動
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 新增一個定時任務,使用預設的任務組名,觸發器名,觸發器組名  (帶引數)
     *
     * @param jobName 任務名
     * @param cls     任務
     * @param time    時間設定,參考quartz說明文件
     */
    public void addJob(String jobName, Class<? extends Job> cls, String time, Map<String, Object> parameter) {
        try {
            JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(jobName, JOB_GROUP_NAME).build();    //用於描敘Job實現類及其他的一些靜態資訊,構建一個作業例項
            jobDetail.getJobDataMap().put("parameterList", parameter);                                    //傳引數
            CronTrigger trigger = TriggerBuilder
                    .newTrigger()                                                                        //建立一個新的TriggerBuilder來規範一個觸發器
                    .withIdentity(jobName, TRIGGER_GROUP_NAME)                                            //給觸發器起一個名字和組名
                    .withSchedule(CronScheduleBuilder.cronSchedule(time))
                    .build();
            sched.scheduleJob(jobDetail, trigger);
            if (!sched.isShutdown()) {
                sched.start();      // 啟動
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 新增一個定時任務
     *
     * @param jobName          任務名
     * @param jobGroupName     任務組名
     * @param triggerName      觸發器名
     * @param triggerGroupName 觸發器組名
     * @param jobClass         任務
     * @param time             時間設定,參考quartz說明文件
     */
    public void addJob(String jobName, String jobGroupName,
                       String triggerName, String triggerGroupName, Class<? extends Job> jobClass,
                       String time) {
        try {
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();// 任務名,任務組,任務執行類
            CronTrigger trigger = TriggerBuilder     // 觸發器
                    .newTrigger()
                    .withIdentity(triggerName, triggerGroupName)
                    .withSchedule(CronScheduleBuilder.cronSchedule(time))
                    .build();
            sched.scheduleJob(jobDetail, trigger);
            if (!sched.isShutdown()) {
                sched.start();      // 啟動
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 新增一個定時任務  (帶引數)
     *
     * @param jobName          任務名
     * @param jobGroupName     任務組名
     * @param triggerName      觸發器名
     * @param triggerGroupName 觸發器組名
     * @param jobClass         任務
     * @param time             時間設定,參考quartz說明文件
     */
    public void addJob(String jobName, String jobGroupName,
                       String triggerName, String triggerGroupName, Class<? extends Job> jobClass,
                       String time, Map<String, Object> parameter) {
        try {
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();// 任務名,任務組,任務執行類
            jobDetail.getJobDataMap().put("parameterList", parameter);                                //傳引數
            CronTrigger trigger =  TriggerBuilder     // 觸發器
                    .newTrigger()
                    .withIdentity(triggerName, triggerGroupName)
                    .withSchedule(CronScheduleBuilder.cronSchedule(time))
                    .build();
            sched.scheduleJob(jobDetail, trigger);
            if (!sched.isShutdown()) {
                sched.start();      // 啟動
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 修改一個任務的觸發時間(使用預設的任務組名,觸發器名,觸發器組名)
     *
     * @param jobName 任務名
     * @param time    新的時間設定
     */
    public void modifyJobTime(String jobName, String time) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, TRIGGER_GROUP_NAME);        //通過觸發器名和組名獲取TriggerKey
            CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);                //通過TriggerKey獲取CronTrigger
            if (trigger == null) {
                return;
            }
            String oldTime = trigger.getCronExpression();
            if (!oldTime.equalsIgnoreCase(time)) {
                JobKey jobKey = JobKey.jobKey(jobName, JOB_GROUP_NAME);                        //通過任務名和組名獲取JobKey
                JobDetail jobDetail = sched.getJobDetail(jobKey);
                Class<? extends Job> objJobClass = jobDetail.getJobClass();
                removeJob(jobName);
                addJob(jobName, objJobClass, time);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 修改一個任務的觸發時間
     *
     * @param triggerName      任務名稱
     * @param triggerGroupName 傳過來的任務名稱
     * @param time             更新後的時間規則
     */
    public void modifyJobTime(String triggerName, String triggerGroupName, String time) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);    //通過觸發器名和組名獲取TriggerKey
            CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);                //通過TriggerKey獲取CronTrigger
            if (trigger == null) return;
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(trigger.getCronExpression());
            String oldTime = trigger.getCronExpression();
            if (!oldTime.equalsIgnoreCase(time)) {
                trigger = (CronTrigger) trigger.getTriggerBuilder()        //重新構建trigger
                        .withIdentity(triggerKey)
                        .withSchedule(scheduleBuilder)
                        .withSchedule(CronScheduleBuilder.cronSchedule(time))
                        .build();
                sched.rescheduleJob(triggerKey, trigger);                //按新的trigger重新設定job執行
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 移除一個任務(使用預設的任務組名,觸發器名,觸發器組名)
     *
     * @param jobName 任務名稱
     */
    public void removeJob(String jobName) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, TRIGGER_GROUP_NAME);    //通過觸發器名和組名獲取TriggerKey
            JobKey jobKey = JobKey.jobKey(jobName, JOB_GROUP_NAME);                        //通過任務名和組名獲取JobKey
            sched.pauseTrigger(triggerKey);    // 停止觸發器
            sched.unscheduleJob(triggerKey);// 移除觸發器  
            sched.deleteJob(jobKey);        // 刪除任務
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 移除一個任務
     *
     * @param jobName          任務名
     * @param jobGroupName     任務組名
     * @param triggerName      觸發器名
     * @param triggerGroupName 觸發器組名
     */
    public void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);    //通過觸發器名和組名獲取TriggerKey
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);                            //通過任務名和組名獲取JobKey
            sched.pauseTrigger(triggerKey);    // 停止觸發器
            sched.unscheduleJob(triggerKey);// 移除觸發器  
            sched.deleteJob(jobKey);        // 刪除任務
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

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

    /**
     * 關閉所有定時任務
     */
    public void shutdownJobs() {
        try {
            if (!sched.isShutdown()) {
                sched.shutdown();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}  

 http://cron.qqe2.com/ 這個是自動生成cron表示式的工具網址。

  • 方式二

使用simpleSchedule來新增任務。

package com.atao.zowei.job;

import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QuartzConfig {
    /**
     * 定時獲取AccessToken儲存到redis中
     * @return
     */
    @Bean
    public JobDetail getWeiXinAccessTokenQuartzDetail(){
        return JobBuilder.newJob(WeiXinAccessTokenJob.class).withIdentity("getWeiXinAccessTokenQuartz").storeDurably().build();
    }
    @Bean
    public Trigger getWeiXinAccessTokenTrigger(){
        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(7200)  //設定時間週期單位秒
                .repeatForever();
        return TriggerBuilder.newTrigger().forJob(getWeiXinAccessTokenQuartzDetail())
                .withIdentity("getWeiXinAccessTokenQuartz")
                .withSchedule(scheduleBuilder)
                .build();
    }

}

 

下面說下使用simpleSchedule建立job和Scheduler建立job的區別

 

其實我研究也不是很深入,我只能講到我遇到的問題。

  • 在使用持久化到資料庫的時候使用simpleSchedule建立的任務式可以重複建立的就是說你在開發環境下的話難免會重啟服務,使用simpleSchedule的方式的話會覆蓋持久化在資料庫中的job記錄。
  • 而使用Scheduler配合cron表示式的方式建立的,他需要你又任務組名和任務名,然後你的任務名是不能重複的建立的,就是說如果在開發環境下使用了這種方式,你重啟了服務或者你重複的添加了這個任務,任務名重複的話,系統則會報錯,你不會像每次啟動服務的時候都去換一個任務名的,當然也有直接用UUID當任務名的,但是我個人建議的話還是使用class的name比較好。或者你去把資料庫的表重新構建一遍清空資料表。

  我就在這上面踩了雷,我就一直重複的去啟動專案,然後第一次是成功的,第二次就不行了。所以這邊點的話注意一下。

 

貼上建表的sql語句

 

/*
Navicat MySQL Data Transfer

Source Server         : local
Source Server Version : 50505
Source Host           : localhost:3306
Source Database       : quartz

Target Server Type    : MYSQL
Target Server Version : 50505
File Encoding         : 65001

Date: 2017-11-05 18:01:51
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for qrtz_blob_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_blob_triggers`;
CREATE TABLE `qrtz_blob_triggers` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `TRIGGER_NAME` varchar(200) NOT NULL,
  `TRIGGER_GROUP` varchar(200) NOT NULL,
  `BLOB_DATA` blob DEFAULT NULL,
  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
  KEY `SCHED_NAME` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
  CONSTRAINT `qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for qrtz_calendars
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_calendars`;
CREATE TABLE `qrtz_calendars` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `CALENDAR_NAME` varchar(200) NOT NULL,
  `CALENDAR` blob NOT NULL,
  PRIMARY KEY (`SCHED_NAME`,`CALENDAR_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for qrtz_cron_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_cron_triggers`;
CREATE TABLE `qrtz_cron_triggers` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `TRIGGER_NAME` varchar(200) NOT NULL,
  `TRIGGER_GROUP` varchar(200) NOT NULL,
  `CRON_EXPRESSION` varchar(120) NOT NULL,
  `TIME_ZONE_ID` varchar(80) DEFAULT NULL,
  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
  CONSTRAINT `qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for qrtz_fired_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_fired_triggers`;
CREATE TABLE `qrtz_fired_triggers` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `ENTRY_ID` varchar(95) NOT NULL,
  `TRIGGER_NAME` varchar(200) NOT NULL,
  `TRIGGER_GROUP` varchar(200) NOT NULL,
  `INSTANCE_NAME` varchar(200) NOT NULL,
  `FIRED_TIME` bigint(13) NOT NULL,
  `SCHED_TIME` bigint(13) NOT NULL,
  `PRIORITY` int(11) NOT NULL,
  `STATE` varchar(16) NOT NULL,
  `JOB_NAME` varchar(200) DEFAULT NULL,
  `JOB_GROUP` varchar(200) DEFAULT NULL,
  `IS_NONCONCURRENT` varchar(1) DEFAULT NULL,
  `REQUESTS_RECOVERY` varchar(1) DEFAULT NULL,
  PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`),
  KEY `IDX_QRTZ_FT_TRIG_INST_NAME` (`SCHED_NAME`,`INSTANCE_NAME`),
  KEY `IDX_QRTZ_FT_INST_JOB_REQ_RCVRY` (`SCHED_NAME`,`INSTANCE_NAME`,`REQUESTS_RECOVERY`),
  KEY `IDX_QRTZ_FT_J_G` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
  KEY `IDX_QRTZ_FT_JG` (`SCHED_NAME`,`JOB_GROUP`),
  KEY `IDX_QRTZ_FT_T_G` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
  KEY `IDX_QRTZ_FT_TG` (`SCHED_NAME`,`TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for qrtz_job_details
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_job_details`;
CREATE TABLE `qrtz_job_details` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `JOB_NAME` varchar(200) NOT NULL,
  `JOB_GROUP` varchar(200) NOT NULL,
  `DESCRIPTION` varchar(250) DEFAULT 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 DEFAULT NULL,
  PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
  KEY `IDX_QRTZ_J_REQ_RECOVERY` (`SCHED_NAME`,`REQUESTS_RECOVERY`),
  KEY `IDX_QRTZ_J_GRP` (`SCHED_NAME`,`JOB_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for qrtz_locks
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_locks`;
CREATE TABLE `qrtz_locks` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `LOCK_NAME` varchar(40) NOT NULL,
  PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for qrtz_paused_trigger_grps
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_paused_trigger_grps`;
CREATE TABLE `qrtz_paused_trigger_grps` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `TRIGGER_GROUP` varchar(200) NOT NULL,
  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for qrtz_scheduler_state
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_scheduler_state`;
CREATE TABLE `qrtz_scheduler_state` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `INSTANCE_NAME` varchar(200) NOT NULL,
  `LAST_CHECKIN_TIME` bigint(13) NOT NULL,
  `CHECKIN_INTERVAL` bigint(13) NOT NULL,
  PRIMARY KEY (`SCHED_NAME`,`INSTANCE_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for qrtz_simple_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_simple_triggers`;
CREATE TABLE `qrtz_simple_triggers` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `TRIGGER_NAME` varchar(200) NOT NULL,
  `TRIGGER_GROUP` varchar(200) 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`),
  CONSTRAINT `qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for qrtz_simprop_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_simprop_triggers`;
CREATE TABLE `qrtz_simprop_triggers` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `TRIGGER_NAME` varchar(200) NOT NULL,
  `TRIGGER_GROUP` varchar(200) NOT NULL,
  `STR_PROP_1` varchar(512) DEFAULT NULL,
  `STR_PROP_2` varchar(512) DEFAULT NULL,
  `STR_PROP_3` varchar(512) DEFAULT NULL,
  `INT_PROP_1` int(11) DEFAULT NULL,
  `INT_PROP_2` int(11) DEFAULT NULL,
  `LONG_PROP_1` bigint(20) DEFAULT NULL,
  `LONG_PROP_2` bigint(20) DEFAULT NULL,
  `DEC_PROP_1` decimal(13,4) DEFAULT NULL,
  `DEC_PROP_2` decimal(13,4) DEFAULT NULL,
  `BOOL_PROP_1` varchar(1) DEFAULT NULL,
  `BOOL_PROP_2` varchar(1) DEFAULT NULL,
  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
  CONSTRAINT `qrtz_simprop_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for qrtz_triggers
-- ----------------------------
DROP TABLE IF EXISTS `qrtz_triggers`;
CREATE TABLE `qrtz_triggers` (
  `SCHED_NAME` varchar(120) NOT NULL,
  `TRIGGER_NAME` varchar(200) NOT NULL,
  `TRIGGER_GROUP` varchar(200) NOT NULL,
  `JOB_NAME` varchar(200) NOT NULL,
  `JOB_GROUP` varchar(200) NOT NULL,
  `DESCRIPTION` varchar(250) DEFAULT NULL,
  `NEXT_FIRE_TIME` bigint(13) DEFAULT NULL,
  `PREV_FIRE_TIME` bigint(13) DEFAULT NULL,
  `PRIORITY` int(11) DEFAULT NULL,
  `TRIGGER_STATE` varchar(16) NOT NULL,
  `TRIGGER_TYPE` varchar(8) NOT NULL,
  `START_TIME` bigint(13) NOT NULL,
  `END_TIME` bigint(13) DEFAULT NULL,
  `CALENDAR_NAME` varchar(200) DEFAULT NULL,
  `MISFIRE_INSTR` smallint(2) DEFAULT NULL,
  `JOB_DATA` blob DEFAULT NULL,
  PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
  KEY `IDX_QRTZ_T_J` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
  KEY `IDX_QRTZ_T_JG` (`SCHED_NAME`,`JOB_GROUP`),
  KEY `IDX_QRTZ_T_C` (`SCHED_NAME`,`CALENDAR_NAME`),
  KEY `IDX_QRTZ_T_G` (`SCHED_NAME`,`TRIGGER_GROUP`),
  KEY `IDX_QRTZ_T_STATE` (`SCHED_NAME`,`TRIGGER_STATE`),
  KEY `IDX_QRTZ_T_N_STATE` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
  KEY `IDX_QRTZ_T_N_G_STATE` (`SCHED_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
  KEY `IDX_QRTZ_T_NEXT_FIRE_TIME` (`SCHED_NAME`,`NEXT_FIRE_TIME`),
  KEY `IDX_QRTZ_T_NFT_ST` (`SCHED_NAME`,`TRIGGER_STATE`,`NEXT_FIRE_TIME`),
  KEY `IDX_QRTZ_T_NFT_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`),
  KEY `IDX_QRTZ_T_NFT_ST_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_STATE`),
  KEY `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_GROUP`,`TRIGGER_STATE`),
  CONSTRAINT `qrtz_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `qrtz_job_details` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

 

最後還是在提一下cron表示式吧

上面的話你選完條件了,看下面的。就只要記得cron表示式 下面的執行時間就是馬上任務執行的時間節點。

他只認絕對的時間,就是在下面的那個時間點的時候會去執行,別的時間不會去執行

至於是到底怎麼寫還是別去深究了,就看下面給你的執行時間,就是那個時間節點就行了,拋開以前那些什麼相對時間,從現在開始多久執行一次,他就是固定的時間點,都是如此。好了,現在就想到這麼多。對於查詢sql資料庫什麼的到時候研究出來的再來補充。