# Quartz教程 - 6 调度器

# 6.1 Calendar例外

如果我们想在某些时候不执行任务,例如有一个任务,一年每天都会执行,但是想在节假日不执行,该如何做呢?

这个时候,就可以使用例外规则的调度器。在 Quartz 中可以使用 Calendar 来定义例外规则。

举个栗子:

org.quartz.Calendar 在Quartz 中是一个接口,它有很多的实现类,我们这里演示一下,在指定的日期不执行任务。

主要有三个步骤:

  1. 定义例外
// 1.定义例外
AnnualCalendar holidays = new AnnualCalendar();
// 2024年元旦不执行
Calendar newYear = new GregorianCalendar(2024, Calendar.JANUARY, 1);
holidays.setDayExcluded(newYear, true);
// 2024年中秋不执行
Calendar middleAutumn = new GregorianCalendar(2024, Calendar.SEPTEMBER, 17);
holidays.setDayExcluded(middleAutumn, true);
1
2
3
4
5
6
7
8
  1. 将例外添加到调度器中
// 2.将自定义的 Calendar 添加到 Scheduler 中
scheduler.addCalendar("holidays", holidays, false, false);
1
2

第三个参数表示已存在具有相同名称的 Calendar,将其替换为新的 Calendar。如果设置为 false,如果已存在具有相同名称的 Calendar,则不会进行替换,而是保留现有的 Calendar

第四个参数如果设置为 true,则更新与 Calendar 相关联的触发器(如果有的话)。如果设置为 false,则不会更新与 Calendar 相关联的任何触发器。

  1. 在触发器中指定时候使用的例外
CronTrigger cronTrigger = TriggerBuilder.newTrigger()
    .withIdentity("cronTrigger1", "cGroup1")
    .withSchedule(CronScheduleBuilder.cronSchedule("*/2 * * * * ?"))
    // 3.与自定义的 Calendar 关联
    .modifiedByCalendar("holidays")
    .build();
1
2
3
4
5
6

完整代码:

package com.doubibiji;
import com.doubibiji.job.MyJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.calendar.AnnualCalendar;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.concurrent.TimeUnit;

public class TestClass {

    public static void main(String[] args) {

        // 1.定义例外
        AnnualCalendar holidays = new AnnualCalendar();
        // 2024年元旦不执行
        Calendar newYear = new GregorianCalendar(2024, Calendar.JANUARY, 1);
        holidays.setDayExcluded(newYear, true);
        // 2024年中秋不执行
        Calendar middleAutumn = new GregorianCalendar(2024, Calendar.SEPTEMBER, 17);
        holidays.setDayExcluded(middleAutumn, true);

        // 定义jobDetail
        JobDetail job = JobBuilder.newJob(MyJob.class)
                .withIdentity("job1", "jGroup1")
                .build();

        // 创建一个 Cron 触发器
        CronTrigger cronTrigger = TriggerBuilder.newTrigger()
                .withIdentity("cronTrigger1", "cGroup1")
                .withSchedule(CronScheduleBuilder.cronSchedule("*/2 * * * * ?"))
                // 3.与自定义的 Calendar 关联
                .modifiedByCalendar("holidays")
                .build();

        try {
            // 定义调度器
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            // 2.将自定义的 Calendar 添加到 Scheduler 中
            scheduler.addCalendar("holidays", holidays, false, false);
            // 设置任务和触发器,由触发器进行分派任务
            scheduler.scheduleJob(job, cronTrigger);
            scheduler.start();

            // 让主线程延迟执行,scheduler如果shutdown,则所有的定时任务会取消。
            TimeUnit.SECONDS.sleep(20);
            scheduler.shutdown();
        } catch (SchedulerException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

上面的 AnnualCalendar 是 org.quartz.Calendar 接口的一个实现,org.quartz.Calendar 接口定义了日历的抽象,而具体的日历实现则有多种方式,其中包括一些内置的和自定义的实现。

一些常见的 Quartz 内置日历实现包括:

  1. AnnualCalendar(年度日历): 允许你指定每年的特定日期,标记为不执行的日期,比如节假日等。
  2. CronCalendar(Cron日历): 根据 Cron 表达式指定一组不执行的日期。
  3. DailyCalendar(每日日历): 允许你指定每天的特定时间段,任务只能在该时间段内触发。
  4. HolidayCalendar(节假日日历): 类似 AnnualCalendar,允许你指定一年中不执行任务的特定日期。
  5. MonthlyCalendar(每月日历): 允许你指定每月的特定日期,标记为不执行的日期。

这些是 Quartz 中常见的内置日历实现,每种日历都有其特定的用途和功能。除了这些内置的日历实现外,你还可以实现自定义的 org.quartz.Calendar 接口,以满足你特定的业务需求。通过实现这个接口,你可以定义自己的日历逻辑,用于控制任务的执行时间。