概述
Quartz是OpenSymphony开源组织的一个开源项目,定时任务框架,纯Java语言实现,最新版本为2.3.0。
Builder模式
Factory模式
组件模式
链式模式
Quartz组成部分
调度器:scheduler
任 务:JobDetail
-
触发器:Trigger,
包括SimpleTrigger和CronTrigger
第一个Quartz程序
实现每隔1秒打印一个Hello World
1.创建Maven项目,添加依赖:
org.quartz-scheduler quartz 2.3.0
2.创建HelloWorldJob类
package quartz; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import java.text.SimpleDateFormat; import java.util.Date; /** * created by Java-Road * created in 2018/5/26 */ public class HelloWorldJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { String strTime = new SimpleDateFormat("HH-mm-ss").format(new Date()); System.out.println( strTime + ":Hello World!"); } }
3.创建MyScheduler类
package quartz; import org.quartz.*; import org.quartz.impl.StdSchedulerFactory; /** * created by Java-Road * created in 2018/5/26 */ public class MyScheduler { public static void main(String[] args) throws SchedulerException { //创建调度器Schedule SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); //创建JobDetail实例,并与HelloWordlJob类绑定 JobDetail jobDetail = JobBuilder.newJob(HelloWorldJob.class).withIdentity("job1", "jobGroup1") .build(); //创建触发器Trigger实例(立即执行,每隔1S执行一次) Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("trigger1", "triggerGroup1") .startNow() .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever()) .build(); //开始执行 scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); } }
Quartz中几个重要的对象
1.Job和JobDetail
Job是Quartz中的一个接口,接口下只有execute方法,在这个方法中编写业务逻辑。
该接口的源码:
package org.quartz; public interface Job { void execute(JobExecutionContext var1) throws JobExecutionException; }
每次调度执行Job时,调用execute方法前会创建一个新的Job实例,执行完后,关联的Job对象实例会被释放,随后jvm执行GC。
JobDetail是用来绑定Job,为Job实例提供了许多属性,以及JobDataMap成员变量属性。调度器scheduler通过JobDetail对象来添加Job实例。
属性:
name
group
jobClass
jobDataMap
2.JobExecutionContext
当调度器Scheduler调用一个Job时,就会将JobExecutionContext传递给Job的execute()方法,Job能通过JobExecutionContext对象访问到Quartz运行时的环境以及Job本身的详细数据信息。
代码演示:
public class HelloWorldJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { String strTime = new SimpleDateFormat("HH-mm-ss").format(new Date()); System.out.println( strTime + ":Hello World!"); System.out.println("JobDetail'name:" + jobExecutionContext.getJobDetail().getKey().getName()); System.out.println("JobDetail'group:" + jobExecutionContext.getJobDetail().getKey().getGroup()); System.out.println("JobDetail'class:" + jobExecutionContext.getJobDetail().getClass()); } }
3.JobDataMap
任务调度时可以通过JobExecutionContext获取JobDataMap,可以装在任何可序列化的数据对象,JobDataMap实现了JDK的Map接口,可以以Key-Value的形式存储数据。
实战:JobDetail和Trigger传递数据,HelloWorldJob类execute三种方式获取数据。
//创建JobDetail实例,并与HelloWordlJob类绑定 JobDetail jobDetail = JobBuilder.newJob(HelloWorldJob.class).withIdentity("job1", "jobGroup1") .usingJobData("key1","this is jobDetail") .build(); //创建触发器Trigger实例(立即执行,每隔1S执行一次) Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("trigger1", "triggerGroup1") .usingJobData("key2", "this is trigger") .startNow() .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever()) .build();
HelloWorldJob获取数据:
public class HelloWorldJob implements Job { private String key1; private String key2; public String getKey1() { return key1; } public void setKey1(String key1) { this.key1 = key1; } public String getKey2() { return key2; } public void setKey2(String key2) { this.key2 = key2; } @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { String strTime = new SimpleDateFormat("HH-mm-ss").format(new Date()); System.out.println( strTime + ":Hello World!"); //获取DataMap数据方法一 System.out.println("JobDetail JobDataMap:" + jobExecutionContext.getJobDetail().getJobDataMap().get("key1")); System.out.println("Trigger JobDataMap:" + jobExecutionContext.getTrigger().getJobDataMap().get("key2")); //获取DataMap数据方法二 System.out.println("JobDataMap:" + jobExecutionContext.getMergedJobDataMap().get("key1")); System.out.println("JobDataMap:" + jobExecutionContext.getMergedJobDataMap().get("key2")); //获取数据方法三 System.out.println("通过成员变量获取" + key1); System.out.println("通过成员变量获取" + key2); } }
4.Trigger
Trigger是Quartz中的触发器,任务执行时会通知调度器Scheduler何时触发,几个重要的属性。
Jobkey:表示job实例的标识
StartTime:表示触发器首次被触发的时间(Java.util.Date)。
EndTime:表示触发器结束触发的时间(Java.util.Date)
实战:实现5S后执行,10S后结束,期间每隔1S执行一次定时任务
代码演示:
MyScheduler类
public class MyScheduler { public static void main(String[] args) throws SchedulerException { //创建调度器Schedule SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); //创建JobDetail实例,并与HelloWordlJob类绑定 JobDetail jobDetail = JobBuilder.newJob(HelloWorldJob.class).withIdentity("job1", "jobGroup1") .build(); //创建触发器Trigger实例(5S后执行,10S后结束) //开始时间(5S后) Date date1 = new Date(); date1.setTime(date1.getTime() + 5000); //结束时间(10S后) Date date2 = new Date(); date2.setTime(date2.getTime() + 10000); Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("trigger1", "triggerGroup1") .startAt(date1) .endAt(date2) .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever()) .build(); //开始执行 scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); } }
5.SimpleTrigger
SimpleTrigger可以实现在一个指定时间段内执行一次作业任务或一个时间段内多次执行作业任务。
实战:5S后开始执行,间隔时间为1S,第一次执行后连续执行3次
package quartz2; import org.quartz.*; import org.quartz.impl.StdSchedulerFactory; import java.util.Date; /** * created by Java-Road * created in 2018/5/27 */ public class MyScheduler2 { public static void main(String[] args) throws SchedulerException { //创建调度器Schedule SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); //创建JobDetail实例,并与HelloWordlJob类绑定 JobDetail jobDetail = JobBuilder.newJob(HelloWorldJob.class).withIdentity("job1", "jobGroup1") .build(); //创建触发器Trigger实例(5S后执行,一直执行) //开始时间(5S后) Date date1 = new Date(); date1.setTime(date1.getTime() + 5000); SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger() .withIdentity("trigger1", "triggerGroup1") .startAt(date1) .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1) .withRepeatCount(3)) .build(); //开始执行 scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); } }
6.CronTrigger
CronTrigger功能非常强大,是基于日历的作业调度,而SimpleTrigger是精准指定间隔,所以相比SimpleTrigger,CroTrigger更加常用。CroTrigger是基于Cron表达式的,先了解下Cron表达式:
由7个子表达式组成字符串的,格式如下:
[秒] [分] [小时] [日] [月] [周] [年]
Cron表达式的语法就不多说了,因为我也记不住只能度娘,给大家提供个在线生成Cron表达式的工具:http://cron.qqe2.com/ ,方便实用。
实战:实现每周一到周五上午10:30执行定时任务
package quartz2; import org.quartz.*; import org.quartz.impl.StdSchedulerFactory; import java.util.Date; /** * created by Java-Road * created in 2018/5/27 */ public class MyScheduler3 { public static void main(String[] args) throws SchedulerException { //创建调度器Schedule SchedulerFactory schedulerFactory = new StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); //创建JobDetail实例,并与HelloWordlJob类绑定 JobDetail jobDetail = JobBuilder.newJob(HelloWorldJob.class).withIdentity("job1", "jobGroup1") .build(); //创建触发器CronTrigger实例(每周一到周五10:30执行任务) CronTrigger trigger = (CronTrigger) TriggerBuilder.newTrigger() .withIdentity("trigger1", "triggerGroup1") .startNow() .withSchedule(CronScheduleBuilder.cronSchedule("* 30 10 ? * 1/5 *")) .build(); //开始执行 scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); } }