Quartz之基本使用
一、定時任務含義
在很多情況下任務并非需要立即執行,而是需要往后或定期執行,這不可能人工去操作,所以定時任務就出現了。
使用定時任務的情況:
????????每周末凌晨備份數據
????????觸發條件 5 分鐘后發送郵件通知
????????30 分鐘未支付取消訂單
????????每 1 小時去拉取數據
二、搭建項目
1、新建模塊
2、導入依賴
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>3、Scheduled(調度器)創建定時任務?
在SpringBoot的啟動類(Quartz01Application)類中加? @EnableScheduling 注解,啟?定時任務的配置
4、創建執行類
package com.lv.code;import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component;import java.time.LocalDateTime;@Component @Slf4j public class Task {@Scheduled(fixedRate = 1000)public void test(){log.warn("現在時間:" + LocalDateTime.now());}}5、測試
每秒執行一次:
package com.lv.code;import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest class Quartz01ApplicationTests {@Testvoid contextLoads() {while (true){}}}?6、Scheduled參數
@Scheduled(fixedRate=5000):上?次開始執?時間點之后5秒再執?
@Scheduled(fixedDelay=5000):上?次執?完畢時間點之后5秒再執?
@Scheduled(initialDelay=1000, fixedRate=5000):第?次延遲1秒后執?,之后按fixedRate的規則每5秒執??次
@Scheduled(cron="*/5 * * * * *"):通過cron表達式定義規則
cron表達式
cron表達式是一個字符串,以5或者6個空格隔開(示例中是被5個空格隔開),字符串被切割為6個或者7個域,每個域都代表不同的含義
注:日與星期不能同時出現,會矛盾,可以其中一個填?
星期里,1表示的是星期天,2表示的是星期一,以此類推,7表示的是星期六
?只存在于某天或某星期中,且不能同時存在(還不支持同時指定某天和星期)
'L'和'W'字符也可以在日期字段中組合以產生'LW',這轉換為“最后一個工作日”
法定字符以及月份和星期的名稱不區分大小寫,如MON 與mon相同
{Seconds} {Minutes} {Hours} {DayofMonth} {Month} {DayofWeek} {Year}
{Seconds} {Minutes} {Hours} {DayofMonth} {Month} {DayofWeek}
?每個域都可以用數字表示,還可以出現如下特殊字符
* : 表示匹配該域的任意值,比如Minutes域使用*,就表示每分鐘都會觸發
- : 表示范圍,比如Minutes域使用10-20,就表示從10分鐘到20分鐘每分鐘都會觸發一次
, : 表示列出枚舉值,比如Minutes域使用1,3.就表示1分鐘和3分鐘都會觸發一次
/ : 表示間隔時間觸發(開始時間/時間間隔),例如在Minutes域使用 5/10,就表示從第5分鐘開始,每隔10分鐘觸發一次
? : 表示不指定值,簡單理解就是忽略該字段的值,直接根據另一個字段的值觸發執行
# : 表示該月第n個星期x(x#n),僅用星期域,如:星期:6#3,表示該月的第三個星期五
L : 表示最后,是單詞"last"的縮寫(最后一天或最后一個星期幾);僅出現在日和星期的域中,用在日則表示該月的最后一天,用在星期則表示該月的最后一個星期,如:星期域上的值為5L,則表示該月最后一個星期的星期四,在使用'L'時,不要指定列表','或范圍'-',否則易導致出現意料之外的結果
W: 僅用在日的域中,表示距離當月給定日期最近的工作日(周一到周五),是單詞"weekday"的縮寫
例子:
0 */5 * * * ?? ?——》在0秒開始,每隔5分鐘執行一次
0 2,22,32 * * * ?? ——》在第2分鐘,第22分鐘和第32分鐘的0秒都會執行一次
0 0 4-8 * * ?? ——》在第4個小時到第8個小時的0分0秒執行一次
0 0 2 1 * ?? ——》每個月的1號的2點鐘0分0秒執行一次
0 0/5 14,18 * * ?? ——》每一天的14點和18點每隔5分鐘執行一次
二、Quartz集成
1、Quartz創建定時任務
兩種任務存儲方式:這期內容講解的是內存方式
內存方式(RAMJobStore):將任務臨時存儲到內存中,僅支持單項目部署,項目重啟后任務會失效,不支持由調度器控制任務漂移,不建議使用。
數據庫方式(JDBCJobStore): Quartz提供了多種數據庫的所需表結構腳本,它內部通過 DataSource來操作數據,支持分布式方式部署、支持任務漂移,項目重啟后任務不會丟失,直到任務執行完成后才會
被從數據庫內清除。
2、導入依賴
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId></dependency>3、測試類
Quartz01ApplicationTests:
package com.lv.code;import org.junit.jupiter.api.Test;import org.quartz.*; import org.quartz.impl.StdSchedulerFactory; import org.springframework.boot.test.context.SpringBootTest;import java.util.Date;import static org.quartz.JobBuilder.newJob; import static org.quartz.SimpleScheduleBuilder.simpleSchedule;@SpringBootTest class Quartz01ApplicationTests {@Testvoid contextLoads() throws Exception{ // 1、實例化調度器工廠SchedulerFactory factory=new StdSchedulerFactory(); // 2、得到調度器Scheduler scheduler = factory.getScheduler(); // 3、創建任務 newJob為靜態方法,按住Alt+Enter,選擇導入static方法JobDetail jobDetail = newJob(MyJob.class) // 描述.withDescription("開年大掃除") // 定義任務的主鍵:context.getJobDetail().getKey() = name + group,在同樣的分組不能出現相同的名字,不同的名字則可以.withIdentity("大掃除", "廁所").usingJobData("name", "王阿姨") // 同樣可以用集合 // JobDataMap jobDataMap=jobDetail.getJobDataMap(); // jobDataMap.put("name","xx"); // 構建出來,一定要寫.build(); // 4、創建觸發器Trigger trigger = TriggerBuilder.newTrigger().withDescription("大掃除觸發器").withIdentity("大掃除", "廁所").startAt(new Date()) // .withSchedule( // simpleSchedule() // .withIntervalInSeconds(10)重復次數 // .withRepeatCount(10) //SimpleTrigger.REPEAT_INDEFINITELY // ) // 基于 Cron 表達式的觸發器 CronTrigger.withSchedule(CronScheduleBuilder.cronSchedule("* * * * * ?")).build(); // 5、將觸發器和任務綁定到調度器scheduler.scheduleJob(jobDetail, trigger); // 6、啟動調度器scheduler.start();}}Scheduler 調度器:
用于與調度程序交互的主程序接口.
Scheduler維護了一個JobDetails和Triggers 的注冊表。
一旦在Scheduler注冊過了,當定時任務觸發時間一到,調度程序就會負責執行預先定義的Job
調度程序創建之后,處于“待機”狀態,必須調用 scheduler 的 start() 方法啟用調度程序
可以使用 shutdown() 方法關閉調度程序,使用 isShutdown() 方法判斷該調度程序是否已經處于關閉狀態
通過 Scheduler.scheduleJob(…) 方法將任務納入調度程序中,當任務觸發時間到了的時候,該任務將被執行
實例化過程:
創建一個 Job 類,在調度程序中可以創建很多個 JobDetai,分別設置不同的 JobDataMap,JobBuilder 用于創建 JobDetail,如果沒有調用 withIdentity 指定 job 的名字,會自動生成一個。
Trigger 觸發器:
觸發器使用 TriggerBuilder 來實例化,有一個 TriggerKey 關聯,在一個 Scheduler 中必須是唯一的。多個觸發器可以指向同一個工作,但一個觸發器只能指向一個工作。
觸發器可以傳送數據給 job,通過將數據放進觸發器的 JobDataMap。
觸發器常用屬性:
觸發器也有很多屬性,這些屬性都是在使用 TriggerBuilder 定義觸發器時設置的。
TriggerKey,唯一標識,在一個 Scheduler 中必須是唯一的
startTime,開始時間,通常使用 startAt(java.util.Date)
endTime,結束時間,設置了結束時間則在這之后,不再觸發,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?如果沒有使用 withIdentity(..) 會自動生成一個觸發器名稱。
觸發器的優先級:
有時候,會安排很多任務,但是 Quartz 并沒有更多的資源去處理它。
這種情況下,必須需要很好地控制哪個任務先執行。這時候可以設置 priority 屬性(使用方法
withPriority(int))來控制觸發器的優先級。優先級只有觸發器出發時間一樣的時候才有意義。當一個任務請求恢復執行時,它的優先級和原始優先級是一樣的。
常見觸發器:
TriggerBuilder 用于創建 Trigger,如果沒有調用 withSchedule(..) 方法,會使用默認的schedule 。
簡單觸發器 SimpleTrigger
SimpleTrigger 包含幾個特點:開始時間、結束時間、重復次數以及重復執行的時間間隔。
基于 Cron 表達式的觸發器 CronTrigger:
.withSchedule(CronScheduleBuilder.cronSchedule("2 * * * * *"))
4、Job 定時任務
任務是一個實現 org.quartz.Job 接口的類,任務類必須含有空構造器
當關聯這個任務實例的觸發器表明的執行時間到了的時候,調度程序 Scheduler 會調用這個方法來執行任務,任務內容就可以在這個方法中執行
新建Task 類:?
package com.lv.code;import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component;import java.time.LocalDateTime;@Component @Slf4j public class Task {@Scheduled(cron = "10 10 * * * ?")public void test(){log.warn("現在時間:" + LocalDateTime.now());}}JobDataMap 提供了一種“初始化成員屬性數據的機制”,在實現該 Job 接口的時候可以取到需要的數據
5、測試結果
?
本期內容結束~~~~
總結
以上是生活随笔為你收集整理的Quartz之基本使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: astropy对fits文件的基础操作
- 下一篇: 新浪财经股票数据的获取方法