面試官問:訂單的定時提醒支付功能是怎麼實現的?我的回答讓我拿到了offer!

在項目中常常會想要這樣的功能:在客戶把商品加入到購物車後,如果30分鐘沒支付該訂單,那麼該訂單失效,或者在這個時候提醒客戶進行支付,這些需求的實現都來自於定時任務調度框架.

今天來學一個簡單的任務調度框架Quartz

簡介

Quartz:

是一個定時任務調度框架.比如你遇到這樣的問題:

  • 想在30分鐘後,查看訂單是否支付,未支付則取消訂單
  • 想在每月29號,信用卡自動還款
  • 想定時在某個時間,去做某件事(任務)

​ Quartz是要做定時任務的調度,設置好觸發時間規則,以及相應任務(Job)即可.

Quartz使用

導入依賴

        <!-- Quartz任務調度  -->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.1</version>
        </dependency>

定製一個Job(任務)

實現接口Job

package per.leiyu;

import org.quartz.*;

/**
 * @author 雷雨
 * @date 2020/6/27 21:05
 */

/**
 * 定義了一個Job任務
 */
public class MyJob01 implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("你好,我是定時任務");


        //可以通過JobExecutionContext來獲取任務的標識(name)和組別(group)
        JobDetail jobDetail = jobExecutionContext.getJobDetail();
        JobKey key = jobDetail.getKey();
        System.out.println(key.getName());//任務標識
        System.out.println(key.getGroup());//任務組別
    }
}

Quartz API

package per.leiyu;

/**
 * @author 雷雨
 * @date 2020/6/27 21:06
 */

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

import java.util.GregorianCalendar;

/**
 * Quartz  API
 */
public class HelloQuartz {
    public static void main(String[] args) throws SchedulerException {
        //1.定義一個調度器  Scheduler
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        //2.定義一個觸發器
        //觸發器中描述任務Job的觸發規則
        SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).withRepeatCount(10))
                .endAt(new GregorianCalendar(2020, 5, 27, 21, 25, 30).getTime())
                .build();

        //3,JobDetail
        //注意jbo的名字和組別和觸發器的名稱和組別是隔離的,那麼就可以同名
        JobDetail jobDetail = JobBuilder.newJob(MyJob01.class).withIdentity("job1", "group1").build();

        //4.將JobDetail和觸發器添加到調度器中
        scheduler.scheduleJob(jobDetail,trigger);

        //5.啓動  調度器開始工作
        scheduler.start();

    }
}

測試結果

定時任務結果,爲了方便觀察在輸出中加了時間戳
image-20200627212813536

配置

可以添加Quartz的配置文件,設置Quartz的默認啓動配置

#名爲:quartz.properties ,放置在classpath下,如果沒有此配置則按默認配置啓動
# 指定調度器名稱,非實現類
org.quarz.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

核心類說明

  • Scheduler:調度器.所有的調度都是由它控制,是Quartz的大腦,所有任務和調度都由它管理
  • Job:任務,想定時執行的事情(定義業務邏輯)
  • JobDetail:基於Job,進一步包裝.其中關聯一個Job,併爲Job指定更爲詳細的屬性,比如標識等
  • Trigger:觸發器.可以指定給某個任務,指定任務的觸發機制

Trigger

SimpleTrigger

以一定的時間間隔(單位是毫秒)執行的任務

  • 指定起始和截止時間(時間段)
  • 指定時間間隔,執行次數
        SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
            .startNow()
            .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2)//每兩秒執行一次
            .withRepeatCount(10))//執行次數不超過10次
            .endAt(new GregorianCalendar(2020, 5, 27, 21, 30, 30).getTime())
            .build();
        SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1")
            .startNow()
            .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2)//每兩秒執行一次
            .repeatForever())//不限制執行次數,由起始截止時間和間隔決定執行次數
            .endAt(new GregorianCalendar(2020, 5, 27, 21, 30, 30).getTime())
            .build();
  • 注意在SimpleTrigger中指定月份是0代表的是1月,1代表的是2月

CronTrigger

適合於更復雜的任務,它支持類型於Linux Cron的語法(很強大)

  • 執行Cron表達式即可

示例:

        CronTrigger trigger1 = TriggerBuilder.newTrigger()
                .withIdentity("trigger1","group1")
                .withSchedule(CronScheduleBuilder.cronSchedule("0 0/2 10-12 * * ?"))
                .build();

Cron表達式組成

表達式組成"秒 分 時 日 月 星期幾 [年]",其中年是可選參數,一般不指定

  • 注意日 ,月可以決定星期,因此如果日,月執行明確的話,星期用 ?表示
位置 時間域 允許值 特殊值
1 0-59 ,-*/
2 分鐘 0-59 ,-*/
3 小時 0-23 ,-*/
4 日期 1-31 ,-*?/LW
5 月份 1-12 ,-*/
6 星期 1-7 ,-*?/LW
7 年份(可選) ,-*/
  • 在CronTrigger中表示月份是1代表的是1月,2代表的是2月
  • 用數字1是的是星期天,數字2表示的是星期1,星期也可以使用英文表示

Cron表達式符號

表達式中可使用的符號的含義

符號 語義
星號(*) 可用在所有字段中,表示對應時間域的每一個時刻,例如在分鐘字段中,表示的是"每分鐘"
問號(?) 該字符只在日期和星期字段中使用,它通常指定爲"不確定值"
減號(-) 表示一個範圍,如在小時字段中使用"10-12",則表示從10點到12點,即10,11,12
逗號(,) 表示一個列表值,如在星期字段中使用"MON,WEB,FRI",則表示星期一,星期二,星期三
斜杆(/) x/y表示一個等步長序列,x爲起始值,y爲增量步長值.如在分鐘字段中使用0/15,則表示的是0,15,30,45,分鐘
井號(#) 該字符只用在星期字段中,"4#2"表示的是第二個星期3,"5#4"表示的是第4個星期四
L 該字符只能出現在日期和星期字段中,代表的是"Last"的意思,但它在兩個字段中含義不同
如果L用在星期字段中,則表示星期6,等同於7
L出現在星期字段中,而且在前面有一個數值x,則表示"這個月最後一個周x",例如:6L代表這個月最後一個週五
L在日期字段中,表示這個月份的最後一天,如一月的31號
W 該字符只能出現在日期字段裏,是對前導日期的修飾,表示離該日期最近的工作日
例如15W表示離該月15號最近的工作日,如果該月15號是星期六,則匹配14號星期五,如果15號是星期日,則匹配16號星期一;如果15號是星期二,那結果就是15號星期二;但必須注意關聯的匹配日期不能跨月
LW組合 在日期字段可以組合使用LW,它的意思是當月的最後一個工作日

我是雷雨,一個普本科的學生,主要專注於Java後端和大數據開發

如果這篇文章有幫助到你,希望你給我一個大大的贊
如果有什麼問題,希望你能留言和我一起研究,學習靠自覺,分享靠自願

轉載註明出處
https://blog.csdn.net/qq_40742223

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