Quartz-定時任務框架 Cron語法,以及Spring整合-任務管理

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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章