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