一,Quartz的核心概念
Quartz是什么?Quartz是一个强大任务调度框架,可以用来干嘛?如一个OA系统需要在每周五9点自动生成数据报表,或者想每月10号自动还款,又或者每周给暗恋的女生定时发送邮件等等。下面介绍Quartz的三个核心概念(job,Trigger,Scheduler)。
1,任务job
job就是你想实现的任务类,每一个job必须实现org.quartz.job接口,且只需实现接口定义的execute()方法。
Job:工作任务调度的接口,任务类需要实现该接口,该接口中定义execute方法,类似jdk提供的TimeTask类的run方法,在里面编写任务执行的业务逻辑。
Job:实例在Quartz中的生命周期,每次调度器执行job时它在调用execute方法前,会创建一个新的job实例,当调用完成后,关联
的job对象实例会被是释放,释放的实例会被垃圾回收机制回收。
2,触发器Trigger
Trigger 为你执行任务的触发器,比如你想每天定时1点发送邮件,Trigger将会设置1点执行该任务。
Trigger主要包含两种:SimpleTrigger和CronTriggerr。
3,调度器Scheduler
Scheduler是任务的调度器,会将任务job和触发器TRigger结合,负责基于Trigger设定的时间执行job。
4,jobDetail 重要属性:
name: System.out.println(jobDetail.getKey().getName());//job
group: System.out.println(jobDetail.getKey().getGroup());//class org.quartz.JobKey
jobClass: System.out.println(jobDetail.getJobClass());//class wachs.quartz.HelloJob2
jobDataMap: System.out.println(jobDetail.getJobDataMap());//org.quartz.JobDataMap@0
二,Quartz体系结构

三,Quartz的几个常用API
Scheduler :用于与调度程序交互的主程序接口。
Job :预先定义的希望在未来时间被调度程序执行的任务类,自定义。
JobDetall :使用JobDetail来定义定时任务的实例,JobDetail实例是通过JobBuilder类创建。
JobDataMap :可包含数据对象,在job实例执行的是好,可使用包含的数据;JobDataMap是java Map接口的实现,增加了一些存取基本类型方法。
Trgger触发器 :Trigger对象是用于触发执行Job的,当调度一个Job时,我们实例一个触发器然后调整它的属性来满足Job执行的条件,表明任务在什么时候执行。定义了一个已经被安排的任务将在什么时候执行的时间条件,比如每秒执行一次。
JobBuilder :用于声明一个任务实例,也可以定义关于该任务的详情比如:任务名,组名等,这个声明的实例将作为一个实例执行的任务。
TriggerBuilder :触发器创建器,用于创建触发器trigger实例。
JobListener,TriggerListener,SchedulerListener监听器,用于对组件的监听。
四,Quartz的使用
导入依赖
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.1</version>
</dependency>
SimpleTrigger触发器。
public class HelloJob implements Job{
/**
* 定时要执行的任务逻辑。
*/
@Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
// (1)JobExecutionContext:
// 当Scheduler调用一个Job,就会将JobExecutionContext传递给Job的execute()方法;
// Job能够通过JobExecutionContext对象访问到Job本身的数据。
// (2)JobDataMap:
// JobDataMap,可以用来装载任何可序列化的数据对象,当job实例对象被执行时这些参数对象会传递。
// JobDataMap,实现了jdk的map接口。
System.out.println(arg0.getJobDetail().getJobDataMap().get("dataMap"));
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
System.out.println("Hello Quartz");
}
public static void main(String[] args) throws Exception {
//1,任务实例
Date date=new Date();
date.setTime(date.getTime()+2000);//设置2秒后结束
JobDetail jobDetail=JobBuilder.newJob(HelloJob.class)//加载任务类,与任务类绑定
.withIdentity("job", "group")//参数1:任务名称,参数2:组名称
.usingJobData("dataMap", "message")//可以设置JobDataMap,获取存取信息
.build();//创建实例
//2,触发器,Quartz里有多个触发器,最常用的是SimpleTrigger,CronTrigger;
SimpleTrigger trigger=TriggerBuilder.newTrigger().withIdentity("trigger", "group")
.withSchedule(SimpleScheduleBuilder.simpleSchedule()//属性有开始时间,结束时间,重复次数,重复时间间隔
.repeatSecondlyForTotalCount(5, 1))//参数1:count,参数2:second.每一秒重复执行,总共执行3遍
// .startNow()//立刻执行
.startAt(new Date())//设置任务开始时间
.endAt(date)//设置任务结束时间
.build();
//3,调度器,方法之一:从工厂中获取new
// Scheduler scheduler = new StdSchedulerFactory().getScheduler();
// 方法之二:从工厂中获取默认的
Scheduler scheduler=StdSchedulerFactory.getDefaultScheduler();
scheduler.scheduleJob(jobDetail,trigger);//关联两者
scheduler.start();//启动
// scheduler.shutdown();//关闭定时任务
}
}
CronTrigger触发器。
public class HelloJob2 implements Job{
@Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
public static void main(String[] args) throws Exception {
//任务实例
JobDetail jobDetail=JobBuilder.newJob(HelloJob2.class)
.withIdentity("job","group")
.build();
//触发器
CronTrigger trigger=TriggerBuilder.newTrigger().withIdentity("trigger", "group").startNow()//立刻执行
.withSchedule(CronScheduleBuilder.cronSchedule("0 * * * * ?"))//表示每次0秒时候执行。
.build();
//调度器
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.scheduleJob(jobDetail,trigger);
scheduler.start();
}
}
CronTrigger触发器的corn表达式书写规则:https://blog.youkuaiyun.com/qq_45315910/article/details/95489298
在线生成corn表达式:http://cron.qqe2.com/
五,JobListener
HelloJob implements Job
public class HelloJob implements Job{
/**
* 定时要执行的任务逻辑。
*/
public void execute(JobExecutionContext arg0) throws JobExecutionException {
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
public static void main(String[] args) throws Exception {
//1,任务实例
JobDetail jobDetail=JobBuilder.newJob(HelloJob.class)
.withIdentity("jobName", "groupName")//参数1:任务名称,参数2:组名称
.usingJobData("dataMap", "message")//可以设置JobDataMap,获取存取信息
.build();
//2,触发器,Quartz里有多个触发器,最常用的是SimpleTrigger,CronTrigger;
SimpleTrigger trigger=TriggerBuilder.newTrigger().withIdentity("trigger", "group")
.withSchedule(SimpleScheduleBuilder.simpleSchedule()//属性有开始时间,结束时间,重复次数,重复时间间隔
.repeatSecondlyForTotalCount(1, 1))//参数1:count,参数2:second.每一秒重复执行,总共执行10遍
.startNow()//立刻执行
.build();
Scheduler scheduler=StdSchedulerFactory.getDefaultScheduler();
scheduler.scheduleJob(jobDetail,trigger);//关联两者
Matcher<JobKey> matcher=EverythingMatcher.allJobs();//获取全部job对象
//在此 注册一个【全局】的jobListener的监听器。
scheduler.getListenerManager().addJobListener(new MyQuartzListener("myJobListenerName"), matcher);
//------------------------------------------------------------------------------
//Matcher<JobKey> matchers=KeyMatcher.keyEquals(JobKey.jobKey("jobName", "groupName"));
//jobName:自定义的jobName,groupName:自定义的groupName
//在此 注册一个【局部】的jobListener的监听器。
//scheduler.getListenerManager().addJobListener(new MyQuartzListener("myJobListenerName"), matchers);
scheduler.start();//启动
}
}
自定义MyQuartzListener
public class MyQuartzListener implements JobListener{
private String name;
//用于获取该自定义JobListener的名称
public MyQuartzListener(String name)
{
this.name=name;
}
public String getName() {
// String simpleName = this.getClass().getSimpleName();
// System.out.println("我的监听器名:"+simpleName);
System.out.println("我的监听器名:"+name);
return name;
}
//Scheduler在jobDetail将要被执行时调用这个方法(执行前)
public void jobToBeExecuted(JobExecutionContext context) {
String jobName = context.getJobDetail().getKey().getName();
System.out.println("我的job名1:"+jobName);
}
//Scheduler在jobDetail即将被执行,但又被TriggerListermer 否定时会调用该方法
public void jobExecutionVetoed(JobExecutionContext context) {
String jobName = context.getJobDetail().getKey().getName();
System.out.println("我的job名2:"+jobName);
}
//Scheduler在jobDetail即将被执行之后调用这个方法。(执行后)
public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
String jobName = context.getJobDetail().getKey().getName();
System.out.println("我的job名3:"+jobName);
}
}
结果展示:使用默认构造函数
使用自定义JobListenerName:
六,TriggerListener
任务调度过程中,与触发器Trigger相关的事件包括:触发器触发,触发器未正常触发,触发器完成等。
HelloJob implements Job
public class HelloJob implements Job{
/**
* 定时要执行的任务逻辑。
*/
public void execute(JobExecutionContext arg0) throws JobExecutionException {
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
public static void main(String[] args) throws Exception {
//1,任务实例
JobDetail jobDetail=JobBuilder.newJob(HelloJob.class)
.withIdentity("jobName", "groupName")//参数1:任务名称,参数2:组名称
.usingJobData("dataMap", "message")//可以设置JobDataMap,获取存取信息
.build();
//2,触发器,Quartz里有多个触发器,最常用的是SimpleTrigger,CronTrigger;
SimpleTrigger trigger=TriggerBuilder.newTrigger().withIdentity("trigger", "group")
.withSchedule(SimpleScheduleBuilder.simpleSchedule()//属性有开始时间,结束时间,重复次数,重复时间间隔
.repeatSecondlyForTotalCount(1, 1))//参数1:count,参数2:second.每一秒重复执行,总共执行10遍
.startNow()//立刻执行
.build();
Scheduler scheduler=StdSchedulerFactory.getDefaultScheduler();
scheduler.scheduleJob(jobDetail,trigger);//关联两者
//在此 注册一个【全局】的TriggerListener的监听器。
// scheduler.getListenerManager().addTriggerListener(new MyQuartzListener2(),EverythingMatcher.allTriggers());
//------------------------------------------------------------------------------
// Matcher<JobKey> matchers=KeyMatcher.keyEquals(JobKey.jobKey("jobName", "groupName"));
//jobName:自定义的jobName,groupName:自定义的groupName
//在此 注册一个【局部】的jobListener的监听器。
scheduler.getListenerManager().addTriggerListener(new MyQuartzListener2(), KeyMatcher.keyEquals(TriggerKey.triggerKey("trigger", "group")));
scheduler.start();//启动
}
}
自定义 MyQuartzListener2
public class MyQuartzListener2 implements TriggerListener{
//用于获取触发器的名称
public String getName() {//获取默认类名
return this.getClass().getSimpleName();
}
//当与监听器相关联的trigger被触发,job上的execute()方法将被执行时,Scheduler就调用该方法
public void triggerFired(Trigger trigger, JobExecutionContext context) {
System.out.println("hhhhh...");
}
//在Trigger触发后,job将要被执行时由Scheduler调用这个方法。
//TriggerListener给一个选择去否决job的执行。如方法返回true,job此次将不会为trigger触发执行。false,放行。
public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
System.out.println("true -no-- vetoJobExecution...");
return false;
}
//Scheduler 调用这个方法是在trigger错过时触发。
public void triggerMisfired(Trigger trigger) {
System.out.println("triggerMisfired...");
}
//triggerComplete:trigger被触发并且完成了job的执行时,Scheduler调用这个方法。
public void triggerComplete(Trigger trigger, JobExecutionContext context,
CompletedExecutionInstruction triggerInstructionCode) {
System.out.println("triggerComplete...");
}
}
结果展示:vetoJobExecution return false
vetoJobExecution return true
七, SchedulerListener
SchedulerListener会在scheduler的生命周期中关键事件发生时被调用,与Scheduler有关事件;增加或者删除一个 job/trigger,关闭scheduler等。
HelloJob implements Job
public class HelloJob implements Job{
public void execute(JobExecutionContext arg0) throws JobExecutionException {
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
public static void main(String[] args) throws Exception {
JobDetail jobDetail=JobBuilder.newJob(HelloJob.class)
.withIdentity("jobName", "groupName")
.usingJobData("dataMap", "message")
.build();
SimpleTrigger trigger=TriggerBuilder.newTrigger().withIdentity("trigger", "group")
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.repeatSecondlyForTotalCount(1, 1))
.startNow()
.build();
Scheduler scheduler=StdSchedulerFactory.getDefaultScheduler();
scheduler.scheduleJob(jobDetail,trigger);
//创建SchedulerListener监听器。
scheduler.getListenerManager().addSchedulerListener(new MyQuartzListener3());
//移除SchedulerListener监听器。
// scheduler.getListenerManager().removeSchedulerListener(new MyQuartzListener3());
scheduler.start();
// scheduler.shutdown();//可以设置多少秒后关闭
}
}
MyQuartzListener3 implements SchedulerListener
public class MyQuartzListener3 implements SchedulerListener{
//用于部署JobDetail 的时候调用
public void jobScheduled(Trigger trigger) {
String name = trigger.getKey().getName();
System.out.println("获取触发器名称:"+name);
}
//卸载JobDetail 的时候调用
public void jobUnscheduled(TriggerKey triggerKey) {
System.out.println(triggerKey.getName());
}
//当trigger来到再也不会触发的时候调用这个方法
public void triggerFinalized(Trigger trigger) {
String name = trigger.getKey().getName();
System.out.println("获取触发器名称:"+name);
}
//当trigger 被暂停时候调用
public void triggerPaused(TriggerKey triggerKey) {
System.out.println("被暂停1");
}
//当trigger组 被暂停时候调用
public void triggersPaused(String triggerGroup) {
System.out.println("被暂停2");
}
///当trigger从 被暂停 到恢复 时候 调用
public void triggerResumed(TriggerKey triggerKey) {
System.out.println("恢复");
}
///当trigger组从 被暂停 到恢复 时候 调用
public void triggersResumed(String triggerGroup) {
System.out.println("恢复");
}
//添加工作任务调用
public void jobAdded(JobDetail jobDetail) {
System.out.println("添加工作任务");
}
//删除工作任务
public void jobDeleted(JobKey jobKey) {
System.out.println("删除工作任务");
}
public void jobPaused(JobKey jobKey) {
// TODO Auto-generated method stub
}
public void jobsPaused(String jobGroup) {
// TODO Auto-generated method stub
}
public void jobResumed(JobKey jobKey) {
// TODO Auto-generated method stub
}
public void jobsResumed(String jobGroup) {
// TODO Auto-generated method stub
}
//scheduler产生Error调用
public void schedulerError(String msg, SchedulerException cause) {
// TODO Auto-generated method stub
}
//scheduler被挂起时候调用
public void schedulerInStandbyMode() {
// TODO Auto-generated method stub
}
//scheduler开启的时候调用
public void schedulerStarted() {
System.out.println("scheduler kai qi ");
}
//scheduler 正在开启的时候调用 ing.....
public void schedulerStarting() {
System.out.println("scheduler 正在开启的时候调用 ing.....");
}
////scheduler关闭 的时候调用
public void schedulerShutdown() {
System.out.println("scheduler关闭 的时候调用");
}
//scheduler 正在关闭的时候调用 ing.....
public void schedulerShuttingdown() {
System.out.println("//scheduler 正在关闭的时候调用 ing.....");
}
//scheduler 数据被清除了的时候调用
public void schedulingDataCleared() {
System.out.println("//scheduler 数据被清除了的时候调用");
}
}
结果展示: