Quartz:是一個定時任務調度框架。
比如遇到問題:
1.想在30分鐘後,查看訂單是否支付,未支付則取消訂單
2.想在每個月29號,信用卡自動還款
…
想定時在某個事件,去做某件事(任務)
Quartz是要做定時任務的調度,設置好觸發時間,以及相應的任務(job)即可
Quartz使用步驟
1.導入依賴
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
2.定義一個Job任務實現Job接口
public class HelloJob implements Job {
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
JobDetail jobDetail = jobExecutionContext.getJobDetail();
JobKey key = jobDetail.getKey(); //獲取JobDetail的名字 和分組
System.out.println(key.getName());//任務名字
System.out.println(key.getGroup());//任務的分組
System.out.println("hello job exec"+new Date());
}
}
3. 在主方法中定義調度器,觸發器,JobDetail
3.1 新建一個調取器調度器
StdScheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
3.2觸發器
SimpleTrigger build = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
.startNow()//起始時間
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(2)//每多少秒執行一次
.repeatForever()) //不限定執行次數
.endAt(new GregorianCalendar(2020, 5, 2, 12, 22, 0).getTime())//截止時間
.build();
3.3 獲取JobDetail對象
JobDetail JobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();
3.4.將JobDetail 和 觸發器增加到調度器中
scheduler.scheduleJob(JobDetail,build);
3.5 啓動,調度器開始工作
scheduler.start();
4.Quartz配置
名爲quertz.properties,放置在classpath下,如果沒有此配置就默認配置啓動
#指定調度器名稱,非實現類
org.quartz.scheduler.instanceName = DefaultQuartzScheduler
# 指定線程池實現類
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
# 線程池線程數量
org.quartz.threadPool.threadCount = 10
# 優先級,默認5
org.quartz.threadPool.threadPriority = 5
# 非持久化job
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
核心類的說明
**1.Scheduler:**調度器。所有的調度都是由它控制,是Quartz的大腦,所有任務都是由它來管理的
**2.Job:**任務。想定時執行的事情定義業務邏輯
**3.JobDetail:**基於Job,進一步包裝,其中關聯一個Job,併爲Job指定更詳細的屬性,比如標識等
**4.Trigger:**觸發器,可以指定給某個任務,指定任務的觸發機制
Trigger:觸發器
1.SimpleTrigger
以一定的時間間隔(單位是毫秒)執行的任務
1.指定起始和截止時間(時間段)
2.指定時間間隔。執行次數
SimpleTrigger build = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
.startNow()//起始時間
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(2)//每多少秒執行一次
.repeatForever()) //不限定執行次數
.endAt(new GregorianCalendar(2020, 5, 2, 12, 22, 0).getTime())//截止時間
.build();
SimpleTrigger build = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
.startNow()//起始時間
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInMinutes(3)/每多少分鐘執行一次
.withRepeatCount(3)) //執行次數不超過三次
.endAt(new GregorianCalendar(2020, 5, 2, 12, 22, 0).getTime())//截止時間
.build();
注意截止時間月份是從0開始的
package com.qf.job;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.util.GregorianCalendar;
public class HelloQuertz {
public static void main(String[] args) throws SchedulerException {
// quartz API
//1.創建一個調度器Scheduler
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
//2.觸發器
SimpleTrigger build = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever())
.endAt(new GregorianCalendar(2020, 5, 2, 12, 22, 0).getTime())
.build();
//3. JobDetail
JobDetail JobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();
//4.將JobDetail 和 觸發器增加到調度器中
scheduler.scheduleJob(JobDetail,build);
//5.啓動,調度器開始工作
scheduler.start();
}
}
2.CronTrigger【常用】
適合於更復雜的任務。它支持類型於Linux Cron的語法(並且更強大)
指定Cron表達式即可
public class CronTrigger {
public static void main(String[] args) throws SchedulerException {
// 1. 獲取調取器
Scheduler defaultScheduler = StdSchedulerFactory.getDefaultScheduler();
// 2. 設置觸發器
org.quartz.CronTrigger build = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule("*/2 * * 2 6 ?")) //秒 分 時 日 月 星期幾 年份(可以省略)
.build();
//3.JobDatail
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();
//4.將JobDatail 和觸發器 增加到調度器中
defaultScheduler.scheduleJob(jobDetail,build);
//5.啓動,調度器開始運作
defaultScheduler.start();
}
}
cron 表達式
表達式組成:“秒 分 時 日 月 星期幾 [年]” 年可選,一般不知道
如:“10 20 18 3 5 ?” 代表的是5月 3日 18時 20 分 10秒
秒 0-59 特殊值:,- * /
分鐘 0-59 特殊值:,- * /
小時 0-23 特殊值:,- * /
日期 1-31 特殊值:,- * ? / L W
月份 1-12 特殊值:,- * /
星期 1-7 特殊值:,- * ? / L #
注意:1:代表星期天 2代表週一
年份(可選) 特殊值:,- * /
特殊值的使用
(1):表示匹配該域的任意值。假如在Minutes域使用, 即表示每分鐘都會觸發事件。
(2)?:只能用在DayofMonth和DayofWeek兩個域。它也匹配域的任意值,但實際不會。因爲DayofMonth和DayofWeek會相互影響。例如想在每月的20日觸發調度,不管20日到底是星期幾,則只能使用如下寫法: 13 13 15 20 * ?, 其中最後一位只能用?,而不能使用*,如果使用*表示不管星期幾都會觸發,實際上並不是這樣。
(3)-:表示範圍。例如在Minutes域使用5-20,表示從5分到20分鐘每分鐘觸發一次
(4)/:表示起始時間開始觸發,然後每隔固定時間觸發一次。例如在Minutes域使用5/20,則意味着5分鐘觸發一次,而25,45等分別觸發一次.
(5),:表示列出枚舉值。例如:在Minutes域使用5,20,則意味着在5和20分每分鐘觸發一次。
(6)L:表示最後,只能出現在DayofWeek和DayofMonth域。如果在DayofWeek域使用5L,意味着在最後的一個星期四觸發。
(7)W:表示有效工作日(週一到週五),只能出現在DayofMonth域,系統將在離指定日期的最近的有效工作日觸發事件。例如:在 DayofMonth使用5W,如果5日是星期六,則將在最近的工作日:星期五,即4日觸發。如果5日是星期天,則在6日(週一)觸發;如果5日在星期一到星期五中的一天,則就在5日觸發。另外一點,W的最近尋找不會跨過月份 。
(8)LW:這兩個字符可以連用,表示在某個月最後一個工作日,即最後一個星期五。
(9)#:用於確定每個月第幾個星期幾,只能出現在DayofWeek域。例如在4#2,表示某月的第二個星期三。
Spring整合-任務管理
1.導入相關依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.qf</groupId>
<artifactId>quartz02</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<springframework.version>5.1.6.RELEASE</springframework.version>
<quartz.version>2.2.3</quartz.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>${quartz.version}</version>
</dependency>
</dependencies>
</project>
2.定義Job類
public class MyJob implements Job {
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("job 執行了");
System.out.println(new Date());
}
}
3.配置Spring相關配置
3.1.調度器:SchedulerFactory Bean
3.2. 觸發器(CronTrigger)CronTriggerFactory Bean
3.3. JobDetail JobDatailFactory Bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
Spring整合Quartz進行配置遵循下面的步驟:
1:定義工作任務的Job
2:定義觸發器Trigger,並將觸發器與工作任務綁定
3:定義調度器,並將Trigger註冊到Scheduler
-->
<!-- 1:定義任務的bean ,這裏使用JobDetailFactoryBean,也可以使用MethodInvokingJobDetailFactoryBean ,配置類似-->
<bean name="lxJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<!-- 指定job的名稱 -->
<property name="name" value="job1"/>
<!-- 指定job的分組 -->
<property name="group" value="job_group1"/>
<!-- 指定具體的job類 -->
<property name="jobClass" value="com.qf.quartz.MyJob"/>
</bean>
<!-- 2:定義觸發器的bean,定義一個Cron的Trigger,一個觸發器只能和一個任務進行綁定 -->
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!-- 指定Trigger的名稱 -->
<property name="name" value="trigger1"/>
<!-- 指定Trigger的名稱 -->
<property name="group" value="trigger_group1"/>
<!-- 指定Tirgger綁定的JobDetail -->
<property name="jobDetail" ref="lxJob"/>
<!-- 指定Cron 的表達式 ,當前是每隔5s運行一次 -->
<property name="cronExpression" value="*/5 * * * * ?" />
</bean>
<!-- 3.定義調度器,並將Trigger註冊到調度器中 -->
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger"/>
</list>
</property>
<!-- 添加 quartz 配置,如下兩種方式均可 -->
<!--<property name="configLocation" value="classpath:quartz.properties"></property>-->
<property name="quartzProperties">
<value>
# 指定調度器名稱,實際類型爲:QuartzScheduler
org.quartz.scheduler.instanceName = MyScheduler
# 指定線程池
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
# 線程池線程數量
org.quartz.threadPool.threadCount = 11
# 優先級
org.quartz.threadPool.threadPriority = 5
# 不持久化job
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
</value>
</property>
</bean>
</beans>
操作
1.啓動:創建工廠後就會執行
public class QuartzTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");//new 一個工廠
}
}
2.任務操作
2.1.刪除任務
//從工廠中拿到調度器
StdScheduler scheduler = (StdScheduler) context.getBean("scheduler");
//利用調度器 刪除任務
scheduler.deleteJob(JobKey.jobKey("job1","job_group1")); //傳遞Job的name 及 group
2.2.暫停,恢復
scheduler.pauseJob(JobKey.jobKey("job1","job_group1"));
Thread.sleep(3000);
scheduler.resumeJob(JobKey.jobKey("job1","job_group1"));
2.3.批量操作
利用group組進行批量操作(刪除沒有批量操作)
scheduler.pauseJobs(GroupMatcher.groupEquals("job_group1")); //暫停job_group1組中所有的job
scheduler.resumeJobs(GroupMatcher.groupEquals("job_group1"));//重寫啓動job_group1組中所有的job