quartz 核心3个类
调度器 触发器 任务
Scheduler :这是Quartz Scheduler的主要接口,代表一个独立运行容器。调度程序维护JobDetails和触发器的注册表。 一旦注册,调度程序负责执行作业,当他们的相关联的触发器触发(当他们的预定时间到达时)。
Trigger :具有所有触发器通用属性的基本接口,描述了job执行的时间出发规则。 - 使用TriggerBuilder实例化实际触发器。
JobDetail :传递给定作业实例的详细信息属性。 JobDetails将使用JobBuilder创建/定义。
Job:要由表示要执行的“作业”的类实现的接口。只有一个方法 void execute(jobExecutionContext context)
(jobExecutionContext 提供调度上下文各种信息,运行时数据保存在jobDataMap中)
定义一个简单的任务实现
1.定义任务类
package com.xxq.qianniu.rest.framework.system;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class HelloJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//打印当前的时间
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date date = new Date();
System.out.println("current exec time is :"+sf.format(date));
}
}
2.main方法测试
package com.xxq.qianniu.rest.framework.task;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
public class TestHelloWord {
public static void main(String[] args) throws SchedulerException {
// 定义,jobdetal 给 jobdetail定义
// 要定时跑的任务类,任务名称,任务所属组名称,任务描述,
JobDetail jobDetail = JobBuilder.newJob(HelloWord.class).withIdentity("xxq_jobdetail_001", "xxq_jobdetail_group_1").
withDescription("xxq_jobdetail_desc").requestRecovery(true).build();
// 第二 ,定义 触发器 trigger
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("xxq_trigger_001", "xxq_trigger_grouop1").
withDescription("xxq_trigger.desc").withPriority(Trigger.DEFAULT_PRIORITY).startNow().
withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever()).build();
// 第三,定义 调度器
Scheduler schedule = StdSchedulerFactory.getDefaultScheduler();
// 调度器 绑定任务 触发器
schedule.scheduleJob(jobDetail, trigger);
// 开启
schedule.start();
}
}
执行代码
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
当前运行线程 :DefaultQuartzScheduler_Worker-1 : 运行时间 :2018-08-30 10:43:18
hello word
8月 30, 2018 10:43:18 下午 com.xxq.qianniu.rest.framework.task.HelloWord execute
信息: hello word
当前运行线程 :DefaultQuartzScheduler_Worker-2 : 运行时间 :2018-08-30 10:43:20
hello word
8月 30, 2018 10:43:20 下午 com.xxq.qianniu.rest.framework.task.HelloWord execute
信息: hello word
当前运行线程 :DefaultQuartzScheduler_Worker-3 : 运行时间 :2018-08-30 10:43:22
hello word
8月 30, 2018 10:43:22 下午 com.xxq.qianniu.rest.framework.task.HelloWord execute
信息: hello word
简单入门
2.JOb是什么
Job:接口非常容易实现,只有一个execute方法,类似于Runable的run方法,在里面编写业务逻辑。
job实例在quartz中的声明周期:
每次调度器在执行job时,它在执行execute方法前创建一个job实例
当调用完成之后,关联的job对象实例会被释放,释放的实例被垃圾回收期你回收。
jobDetail简介
JobDetail为Job实例提供了许多设置属性,以及JobDataMap成员变量属性,它用来存储特定job实例的状态信息系,调度器需要借助Jobdetail对象来添加Job实例。
属性:
name:任务的名称,必须属性
group:任务所在的组,也是必须,默认值是DEFAULT
jobclass:任务的实现类
jobdatamap:用于传递传参数
JobExecutionContext简介
(1)当Scheduler调用一个Job,就会将JobExecutionContext传递给job的execute方法
quartz无法调用job的有参构造函数,所以创建job的实例的时候是运用反射机制,通过newInstance创建实例,并且通过JobDetail描述的name与group属性然后给Job设置一些属性。
(2)Job能通过JobExecutionContext对象访问到Quartz运行时候的环境以及Job本身的明细数据。
JobDataMap简介:
1.JobDataMap是什么?
(1)在进行任务调度时JobDataMap存储在JobExecutionContext中,非常方便获取
(2)JobDataMap可以用来装载任何可以序列化的数据对象,当job实例对象被执行时这些参数对象会传递给它
(3)JobDataMap实现了JDK的Map接口,并且添加了一些非常方便的方法用来存取数据基本数据类型。
通过usingJobData传递一些参数(JobDetail和Trigger都能使用此方法传递参数)
如何获取参数,设置参数?
2.获取JobDataMap的两种方式:
1.第一种方式:从JobExecutionContext实例中获取
(1)从实例中获取JobDetail与Trigger单独的JobDataMap的方法
1.通过usingJobData传递一些参数(JobDetail和Trigger都能使用此方法传递参数)
JobDetail jobDetail = JobBuilder.newJob(HelloWord.class).withIdentity("xxq_jobdetail_001", "xxq_jobdetail_group_1").
withDescription("xxq_jobdetail_desc").requestRecovery(true).usingJobData("message", "xxq").build();
2.获取
package com.xxq.qianniu.rest.framework.task;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/**
* @description 定义任务类
* @author xq
* @version 0.1
*/
public class HelloWord implements Job {
private Log LOG = LogFactory.getLog(HelloWord.class);
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
Date nowDate = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
System.out.println("当前运行线程 :" + Thread.currentThread().getName() + " : " + "运行时间 :" + simpleDateFormat.format(nowDate));
System.out.println("hello word ");
// 获取m方法传过来的参数
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
String object = (String) jobDataMap.get("message");
System.out.println("受到参数 :" + object);
LOG.info("hello word");
}
}
效果:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
当前运行线程 :DefaultQuartzScheduler_Worker-1 : 运行时间 :2018-08-30 11:00:31
hello word
受到参数 :xxq
8月 30, 2018 11:00:31 下午 com.xxq.qianniu.rest.framework.task.HelloWord execute
信息: hello word
当前运行线程 :DefaultQuartzScheduler_Worker-2 : 运行时间 :2018-08-30 11:00:33
hello word
受到参数 :xxq
8月 30, 2018 11:00:33 下午 com.xxq.qianniu.rest.framework.task.HelloWord execute
信息: hello word
(2)从实例中获取JobDetail与Trigger合并的JobDataMap的方法
理论上是将JobDatail的JobDataMap和Trigger的JobDataMap合并,当我们获取两者有相同的key值的时候,优先获取的是Trigger的值,也就是JobDatail的会被覆盖
如果JobDetail和Trigger的传递参数相同,使用合并后的JobDataMap获取的时候优先获取Trigger的参数
2.第二种方式:Job实现类添加setter方法对应JobDataMap的键值(Quartz框架默认的JobFactory实现类在初始化job实例对象时会自动调用这些setter方法)
(添加成员属性,并且添加对应的get,set方法,类似于struts的属性注入,当我们在使用JobDataMap添加数据的时候会自动映射到这个类的成员实现方法中,需要注意的是成员属性的名字要和jobDataMap添加时候的key值相同
package com.xxq.qianniu.rest.framework.system;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class HelloJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//打印当前的时间
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date date = new Date();
System.out.println("current exec time is :"+sf.format(date));
}
}
效果:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
当前运行线程 :DefaultQuartzScheduler_Worker-1 : 运行时间 :2018-08-30 11:13:56
hello word
受到参数 :xxq
受到合并后的 :xxq
8月 30, 2018 11:13:56 下午 com.xxq.qianniu.rest.framework.task.HelloWord execute
信息: hello word
受到自动注入的参数 : xxq
当前运行线程 :DefaultQuartzScheduler_Worker-2 : 运行时间 :2018-08-30 11:13:58
hello word
受到参数 :xxq
受到合并后的 :xxq
8月 30, 2018 11:13:58 下午 com.xxq.qianniu.rest.framework.task.HelloWord execute
信息: hello word
受到自动注入的参数 : xxq
3.Trigger是什么
Quartz中的触发器用来告诉调度程序什么时候触发,即Trigger对象是用来触发执行job的。
属性:
JobKey:表示job实例的标识,触发器被触发时,该指定的job实例会执行
StartTime:表示触发器的时间表 首次被触发的时间,值类型是Java.util.Date
EndTime:指定触发器的不再触发的时间,它的值类型是Java.util.Date
// 第二 ,定义 触发器 trigger
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("xxq_trigger_001", "xxq_trigger_grouop1").
withDescription("xxq_trigger.desc").withPriority(Trigger.DEFAULT_PRIORITY).startNow().
withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever()).build();
withIdentity 定义触发器 名称 ,所属类名称
withDescription 定义触发器描述
withPriority 设置优先级别
startNow 开始时间 现在开始
startAt 开始时间
endAt 结束时间
withSchedule 设定具体的触发器工厂调度 SimpleScheduleBuilder 这里使用简单调度器设置
4.SimpleTrigger是什么?
在一个指定时间段内执行一次作业任务或是在指定时间间隔内执行多次作业任务
package com.xxq.qianniu.rest.framework.task;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
public class SimpleTriggerTest {
public static void main(String[] args) throws SchedulerException {
// 定义,jobdetal 给 jobdetail定义
// 要定时跑的任务类,任务名称,任务所属组名称,任务描述,
JobDetail jobDetail = JobBuilder.newJob(HelloWord.class).withIdentity("xxq_jobdetail_001", "xxq_jobdetail_group_1").
withDescription("xxq_jobdetail_desc").requestRecovery(true).usingJobData("message", "xxq").build();
// 第二 ,定义 触发器 trigger
SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("xxq_trigger_001", "xxq_trigger_grouop1").
withDescription("xxq_trigger.desc").withPriority(Trigger.DEFAULT_PRIORITY).startNow().
withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).withRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY)).build();
// 第三,定义 调度器
Scheduler schedule = StdSchedulerFactory.getDefaultScheduler();
// 调度器 绑定任务 触发器
schedule.scheduleJob(jobDetail, trigger);
// 开启
schedule.start();
}
}
效果:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
当前运行线程 :DefaultQuartzScheduler_Worker-1 : 运行时间 :2018-08-30 11:33:09
hello word
受到参数 :xxq
受到合并后的 :xxq
受到自动注入的参数 : xxq
8月 30, 2018 11:33:09 下午 com.xxq.qianniu.rest.framework.task.HelloWord execute
信息: hello word
当前运行线程 :DefaultQuartzScheduler_Worker-2 : 运行时间 :2018-08-30 11:33:11
hello word
受到参数 :xxq
受到合并后的 :xxq
8月 30, 2018 11:33:11 下午 com.xxq.qianniu.rest.framework.task.HelloWord execute
信息: hello word
受到自动注入的参数 : xxq
SimpleTrigger总结:
1.重复次数可以是0,正整数或是SimpleTrigger.REPEAT_INDEFINITELY常量值。我们点击发现REPEAT_INDEFINITELY是-1,也就是-1表示无线次。
2.重复执行时间间隔必须为0或长整数。可以用小时,分钟,秒数的单位限制间隔
3.一旦指定了endTime参数,那么它会覆盖重复次数参数的效果。
5.CronTrigger是什么?
基于日历的作业调度器,而不是像SimpleTrigger那样精确指定间隔时间,比SimpleTrigger更常用。
1.Cron表达式
用于配置CronTrigger实例
是由7个子表达式组成的字符串,描述了时间表的详细信息
格式:[秒][分][小时][日][月][周][年]
书写规则:知道确定日期的写上,不知道的用*代替 (年可以省略,只写前6个)
Cron表达式举例
列:
package com.xxq.qianniu.rest.framework.task;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
public class CornTriggerTest {
public static void main(String[] args) throws SchedulerException {
// 定义,jobdetal 给 jobdetail定义
// 要定时跑的任务类,任务名称,任务所属组名称,任务描述,
JobDetail jobDetail = JobBuilder.newJob(HelloWord.class).withIdentity("xxq_jobdetail_001", "xxq_jobdetail_group_1").
withDescription("xxq_jobdetail_desc").requestRecovery(true).usingJobData("message", "xxq").build();
// 第二 ,定义 触发器 trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("xxq_trigger_001", "xxq_trigger_grouop1").
withDescription("xxq_trigger.desc").withPriority(Trigger.DEFAULT_PRIORITY).
withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ? *")).build();
// 第三,定义 调度器
Scheduler schedule = StdSchedulerFactory.getDefaultScheduler();
// 调度器 绑定任务 触发器
schedule.scheduleJob(jobDetail, trigger);
// 开启
schedule.start();
}
}
每隔2秒运行一次
效果:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
当前运行线程 :DefaultQuartzScheduler_Worker-1 : 运行时间 :2018-08-30 11:40:14
hello word
受到参数 :xxq
受到合并后的 :xxq
8月 30, 2018 11:40:14 下午 com.xxq.qianniu.rest.framework.task.HelloWord execute
信息: hello word
受到自动注入的参数 : xxq
当前运行线程 :DefaultQuartzScheduler_Worker-2 : 运行时间 :2018-08-30 11:40:16
hello word
受到参数 :xxq
受到合并后的 :xxq
8月 30, 2018 11:40:16 下午 com.xxq.qianniu.rest.framework.task.HelloWord execute
信息: hello word
受到自动注入的参数 : xxq