Quartz是什麼mysql
Quartz是一個用Java編寫的任務調度框架,任務調度是什麼,舉例說明:好比咱們須要在每一個星期四下午三點時候發週報,咱們須要一個系統在兩點半的時候給咱們一個發週報的提醒,這個提醒就是一次任務,每週星期四下午兩點半的時候自動觸發這個任務,這就能夠理解爲這個系統的一次任務調度。Quartz提供給咱們定時調度已定義好的任務的能力,若是你瞭解quartz的調度計劃cronExpression表達式的配置,你會感嘆quartz的靈活與強大。spring
Quartz的應用普遍,對於Hudson報表系統,剛好爲郵件定製功能提供強有力的支持。sql
Quartz的簡單使用數據庫
在Hudson報表系統的一期中也用到了quartz,不過當時是把任務調度信息寫死在配置文件中,每次系統啓動後,調度的配置都加載在內存中,沒有實現多任務的動態加載。咱們先以此來講明quartz的基本用法。Hudson報表系統是用spring框架將quartz整合起來的,故只介紹spring和quartz的整合使用。框架
下圖爲spring配置文件中quartz的配置:編碼
其實quartz的使用主要有三個部分,一個調度器Scheduler,一個要被調度的任務JobDetail,一個觸發器Trigger,對上面的配置作一說明,在圖中從下到上:對象
一、 配置一個job,這個job就是咱們要調度的任務類,繼承
二、 配置jobDetail,jobDetail須要加載job實現類,而且指定目標方法即完成任務須要執行的方法爲execute,在這個方法裏面定義咱們要作的任務,execute方法須要咱們在job類中實現。接口
三、 配置trigger,用於觸發咱們定義的任務,在觸發器的配置中,咱們須要加載須要調度的任務jobDetail,固然還要配置好咱們須要觸發的時間,觸發的時間配置在cronExperssion表達式中,這個表達式很是靈活與強大,舉個例子:咱們須要每一個工做日早八點到晚八點之間,每半個小時觸發一次任務,咱們能夠將表達式配置爲:0 0/30 8-20 ? * MON-FRI。這個表達式的詳細解釋能夠登陸Hudson報表系統(連接:http://10.232.29.21:8080/hudson-report/),點擊郵件信息維護裏面的「郵件發送時間計劃配置幫助」查看。內存
四、 配置scheduler,只須要加載trigger便可,能夠在list標籤下配置多個trigger。注意,scheduler的配置中有個lazy-init=false的配置,這代表只要咱們的spring一啓動,quartz的scheduler也跟着啓動,不然其值爲true的話,會由於惰性加載的問題,致使quartz不起做用,此項默認值是false。
至此,咱們的配置寫好了,只須要實現擁有execute方法的job類就能夠了。
這種方法也能夠實現多任務調度,具體作法爲:咱們每新增一個調度,就須要在配置文件中多加這個調度相關的配置,這樣顯然很麻煩。
Quartz的多任務動態加載
先作簡要說明:
多個任務的動態加載是指:在當前的scheduler中已經有可觸發的任務的狀況下,咱們須要新增一條任務進去,而且使得新增的任務也當即加載到scheduler中,等待觸發。要實現這樣的功能,上面的方法明顯不能達到,並且咱們須要使得咱們的任務狀態持久化,即每次重啓quartz後,自動加載重啓前擁有的任務,把任務保存於內存也明顯不能達到此目的。怎麼辦?添加數據庫支持,將信息保存於數據表中。
Quartz的官方文檔中提供了在各類類型數據庫中創建數據表的sql文件(/docs/dbTables目錄下),咱們採用MySQL數據庫能夠選擇tables_mysql_innodb.sql這個文件。這裏須要注意的是編碼,quartz默認採用latin1編碼,咱們通常用urf-8或者gbk編碼,創建表的時候會提示表中存在過長的字段,怎麼辦,改編碼?但咱們須要中文字符,因此咱們能夠將過長的字段長度改成支持的長度便可,現階段並無發現反作用。
創建起來的數據表以下圖:
共十二張表,從上到下依次解釋:
qrtz_blob_triggers:
qrtz_calendars:存放日曆信息, quartz可配置一個日從來指定一個時間範圍。
qrtz_cron_triggers:存放cron類型的觸發器
qrtz_fired_triggers:存放已觸發的觸發器
qrtz_job_details:存放一個jobDetail信息
qrtz_job_listeners:job監聽器
qrtz_locks:
qrtz_paused_trigger_graps:存放暫停掉的觸發器
qrtz_scheduler_state:調度器狀態
qrtz_simple_triggers:簡單觸發器的信息
qrtz_trigger_listeners:觸發器監聽器
qrtz_triggers:觸發器的基本信息
Quartz的觸發時間的配置有三種方式:
cron的方式:採用cronExpression表達式配置時間;
simple的方式,和JavaTimer差很少,能夠指定一個開始時間和結束時間外加一個循環時間;
calendars方式,能夠和cron配合使用,用cron表達式指定一個觸發時間規律,用calendar指定一個範圍。
咱們採用的是cron方式,須要用到的數據表主要是:qrtz_triggers ,qrtz_cron_triggers,qrtz_fired_triggers,qrtz_job_details。
到這裏開始講到底怎麼來實現咱們的多任務動態加載。
其實咱們要實現咱們的多任務動態調度根本不須要了解這些表,咱們要作的只是實現一個作任務的job類,而後新建一個jobDetail,設置參數,新建一個trigger,設置參數,一塊兒加入到scheduler裏面去就好了。具體過程以下:
一、 創建數據表,配置好數據庫鏈接。
二、 在Spring的配置文件中配置好schedule:
其中dataSource配置的是數據庫鏈接,threadCount配置的是允許同時5個任務觸發,
startupDelay配置的是觸發啓動後的時延,這些配置的具體信息你們能夠閱讀quartz的官方幫助文檔來了解。
三、 創建一個用於提供schedule服務的接口ScheduleService及其實現類ScheduleServiceImpl,
這裏提供scheduleJob的方法做爲示例,以咱們的郵件任務爲例,咱們直接傳入一條郵件記錄對象,這個對象擁有id,name,收件人,抄送人,主題,還要有一個cronExpression表達式用於定時發送,看具體實現:
在上面的方法中,咱們要新增一條郵件任務的時候,拿到這個郵件信息對象,先新建一個JobDetail對象,設置參數,setName方法能夠給jobDetail對象指定一個名字,咱們但願一條郵件信息對象對應一個jobDetail,故把郵件信息對象的id傳入,不然假如兩次新增任務時jobDetail的名字同樣,那麼後者會覆蓋前者的數據,使得前者失效。JopDataMap裏面能夠保存咱們須要傳入的業務參數,郵件信息的參數就保存在郵件信息對象裏面,因此咱們把整個對象傳入,最重要的是setJobClass這個方法,設置了要處理咱們任務的類,使得任務觸發後quartz知道去哪裏執行任務。最後將此任務加入scheduler。
而後新建一個CronTrigger對象,構造對象的時候就傳入trigger本身的名字和所在組,jobDetail的名字和所在組,設置好cronExpression表達式,這樣此trigger就會按此表達式的計劃作觸發。須要說明的是:一個jobDetail能夠對應多個trigger,只要在構造時設置trigger名字不一樣,而jobDetail的名字相同,就能夠爲相同的jobDetail創建不一樣的trigger觸發器。並且對於trigger也能夠設置jobDataMap,保存此觸發器觸發時須要的業務參數。
最後SchedulerJob方法把trigger加入scheduler,等待觸發。
四、 創建任務類MyJob,MyJob類須要繼承QuartzJobBean類,重載其executeInternal方法:
在重載executeInternal方法時,其形參jobExecutionContext中包含了觸發任務的環境信息,和觸發這個任務的jobDetail實例和trigger實例,咱們能夠從中取得咱們想要的信息。