为什么Quartz也有个Calendar?

1,037 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

1. 两个Calendar类

Java.util包中有一个Calendar日历类,在使用Quartz框架时,使用日历类时却错误引用了Quertz框架中org.quartz包下的Calendar,导致发生了一些错误。

下面就来学习一下,Quertz框架中的Calendar是用来干什么的。

2. Quartz中的组织结构

Calendar作为一个顶层接口,其相关实现结构为:

image.png

结构图中虽然有很多的实现类,但是由于AnnualCalendar等类继承BaseCalendar类的同时还实现了Calendar接口,会在结构中重复显示,去除重复的结构可以表示为:

  • Calender,接口
    • BaseCalendar,类,实现Calender接口
      • AnnualCalendar类,继承BaseCalendar、同时实现Calender
      • MonthlyCalendar类,继承BaseCalendar、同时实现了Calender
      • WeeklyCalendar类,继承BaseCalendar、同时实现了Calender
      • DailyCalendar类,继承BaseCalendar
      • HolidayCalendar类,继承BaseCalendar
      • CronCalendar类,继承BaseCalendar

3. 实现功能

了解Calender的结构信息后,便可以对实现类逐个击破,看一下实现的功能。

  • AnnualCalendar:年度日历类,可以设置一年中的一组日期,生效后表示这些日期时间触发器都不会生效触发,粒度在日
//国庆节放假,不触发
AnnualCalendar annualCalendar = new AnnualCalendar();
Calendar calendar = new GregorianCalendar();
calendar.add(Calendar.MONTH,10);
calendar.add(Calendar.DATE,1);
annualCalendar.addExcludedDate(calendar)
  • BaseCalendar:日历的基类,增加了一些额外的方法,如果需要可以实现该基类
  • CronCalendar:使用cron表达式来设置触发器不触发的时间(段)
//cron表达式,如晚上22:00-23:00停止触发
CronCalendar calendar = new CronCalendar("* * 22-23 ? * *");
  • DailyCalendar:日度日历类,设置一天中的某个时间段内触发器是否触发,setInvertTimeRange(false)表示不触发
//中午11:45-13:30午休,不触发
DailyCalendar dailyCalendar = new DailyCalendar("11:45:00", "13:30:00");
dailyCalendar.setInvertTimeRange(false);
  • HolidayCalendar:节假日日历类,可以设置多年份的日期触发器失效,粒度在日
//设置1024程序员节日,触发器停止执行
HolidayCalendar holidayCalendar = new HolidayCalendar();
Calendar calendar = new GregorianCalendar(2021, 24, 10);
holidayCalendar.addExcludedDate(calendar);
  • MonthlyCalendar:月度日历类,设置一个月中的哪些日期不触发触发器
//设置每月1号和15号不触发
MonthlyCalendar monthlyCalendar = new MonthlyCalendar();
monthlyCalendar.setDayExcluded(1, true);
monthlyCalendar.setDayExcluded(15, true)
  • WeeklyCalendar:周日历类,设置一周中的周几不触发
//设置周六日双休
WeeklyCalendar weeklyCalendar = new WeeklyCalendar();
weeklyCalendar.setDayExcluded(Calendar.SATERDAY, true);
weeklyCalendar.setDayExcluded(Calendar.SUNDAY, true);
  • 多个日历对象组合使用
//设置周五晚上20:00-21:00不触发
DailyCalendar dailyCalendar = new DailyCalendar("20:00:00", "21:00:00");
dailyCalendar.setInvertTimeRange(false);  
WeeklyCalendar weeklyCalendar = new WeeklyCalendar(dailyCalendar);
weeklyCalendar.setDayExcluded(Calendar.FRIDAY, true);

4. 配置流程

  1. 选择创建日历对象
  2. 设置日历时间段策略
  3. 将日历对象配置到触发器中
  4. 将日历对象注册到调度器中
  5. 调度器执行触发器和任务

示例代码:

//①-②选择合适的日历对象创建,并设置不触发的策略
DailyCalendar dailyCalendar = new DailyCalendar("11:45:00", "13:30:00");
dailyCalendar.setInvertTimeRange(false);

//③将日历对象信息配置到触发器中,使用.modifiedByCalendar("dailyCalendar")
SimpleTrigger trigger = newTrigger() 
.withIdentity("trigger1", "group1")
.startNow()
.withSchedule(simpleSchedule()
.withIntervalInSeconds(3)
.repeatForever())
.modifiedByCalendar("dailyCalendar")
.build();

//④-⑤将日历注册到调度器中,并执行调度器定时触发任务
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler scheduler = sf.getScheduler();
sched.addCalendar("dailyCalendar", dailyCalendar, false, false);
scheduler.scheduleJob(job, trigger);

5. 总结

以上就是Quartz框架中的Calendar的作用和使用方法,尽管Quartz为我们提供了一整套的定时策略,并可以根据节假日等排除日期时间,但实际使用时,大部分的时间策略都可以使用cron表达式来完成。在创建触发器时使用类型为CronTrigger的触发器对象可快速完成自定义时间的定时任务,更简单方便。