quartz监听器使用
前言
和许多框架类似,quartz也提供了监听器即listener的功能,通过监听器可以达到在被调度的任务之前,之后,或者任务执行过程中,得到人为的干预的效果,举例来说,我们希望在某个job执行前过滤一部分数据,或者在job完成时给系统管理员发一封邮件,甚至我们希望调度任务跳过节假日的执行等,在类似的业务场景下,我们就可以考虑使用quartz提供的监听器功能
Quartz监听器类型
Quartz主要提供了3种类型的监听器,分别是:
JobListener、TriggerListener、SchedulerListener三种,顾名思义,可分别理解为任务、触发器、调度器对应的监听器
三者的使用方法类似,quartz提供了各自的接口,我们只需要实现相应的方法即可。
在开始介绍三种监听器之前,需要掌握两个概念:全局监听器与非全局监听器,二者的区别在于:全局监听器能够接收到所有的Job/Trigger的事件通知,非全局监听器只能接收到在其上注册的Job或Trigger的事件,不在其上注册的Job或Trigger则不会进行监听。这个在:scheduler.getListenerManager().addJobListener 对应的API中会得到体现,下面通过代码分别演示下各个监听器的使用
1、JobListener
JobListener是一个接口,里面提供了几个方法,完整的接口如下:
public interface JobListener {String getName();void jobToBeExecuted(JobExecutionContext var1);void jobExecutionVetoed(JobExecutionContext var1);void jobWasExecuted(JobExecutionContext var1, JobExecutionException var2);
}
- getName方法:用于获取该JobListener的名称
- jobToBeExecuted方法:Scheduler在JobDetail将要被执行时调用这个方法
- jobExecutionVetoed方法:Scheduler在JobDetail即将被执行,但又被TriggerListerner否决时会调用该方法
- jobWasExecuted方法:Scheduler在JobDetail被执行之后调用这个方法
演示demo
@Slf4j
public class MyJobTriggerListener implements JobListener {/*** 获取job名称* @return*/@Overridepublic String getName() {String name = getClass().getSimpleName();log.info(name);return name;}/*** job将要被执行时调用的方法* @param jobExecutionContext*/@Overridepublic void jobToBeExecuted(JobExecutionContext jobExecutionContext) {log.info("2 === jobToBeExecuted");}@Overridepublic void jobExecutionVetoed(JobExecutionContext jobExecutionContext) {System.out.println("jobExecutionVetoed");}/*** job执行完毕之后执行的方法* @param jobExecutionContext* @param e*/@Overridepublic void jobWasExecuted(JobExecutionContext jobExecutionContext, JobExecutionException e) {log.info("5 ========== jobWasExecuted");}
}
public class DemoTest1 {private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();public static void main(String[] args) throws Exception {Scheduler scheduler = schedulerFactory.getScheduler();JobDetail job = JobBuilder.newJob(MyJob.class).withIdentity("myJob", "myJobGroup")//.requestRecovery() // 执行中应用发生故障,需要重新执行.build();Trigger trigger = TriggerBuilder.newTrigger().withIdentity("myFirstTrigger", "myFirstTriggerGroup").startNow().withSchedule(CronScheduleBuilder.cronSchedule("0/3 * * * * ?")).build();//关联job和trigger对象scheduler.scheduleJob(job, trigger);scheduler.getListenerManager().addJobListener(new MyJobTriggerListener(), EverythingMatcher.allJobs());if(!scheduler.isShutdown()){scheduler.start();}}
}
最后再提供一个实现job接口的类即可
@Slf4j
public class MyJob implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {log.info("job task begin");}
}
本段代码基本上没有什么逻辑,仅仅就是在之前的demo篇的最后,通过scheduler这个对象将监听器调用起来即可,运行这段代码,观察控制台效果,
个人理解,其实把监听器类比servlet的生命周期函数可能更好理解,即在job执行之前,之后或者执行过程中动态去添加一些额外的动作
2、TriggerListener
triggerListener中的方法稍微多一些
public interface TriggerListener {String getName();void triggerFired(Trigger var1, JobExecutionContext var2);boolean vetoJobExecution(Trigger var1, JobExecutionContext var2);void triggerMisfired(Trigger var1);void triggerComplete(Trigger var1, JobExecutionContext var2, CompletedExecutionInstruction var3);
}
简单解释下几个方法:
- triggerFired方法:当与监听器相关联的Trigger被触发,Job上的execute()方法将被执行时,Scheduler就调用该方法
- vetoJobExecution方法:在 Trigger 触发后,Job 将要被执行时由 Scheduler 调用这个方法。TriggerListener 给了一个选择去否决 Job 的执行。假如这个方法返回 true,这个 Job 将不会为此次 Trigger 触发而得到执行
- triggerMisfired方法:Scheduler 调用这个方法是在 Trigger 错过触发时。你应该关注此方法中持续时间长的逻辑:在出现许多错过触发的 Trigger 时,长逻辑会导致骨牌效应。你应当保持这上方法尽量的小
- triggerComplete方法:Trigger 被触发并且完成了 Job 的执行时,Scheduler 调用这个方法
总体的使用和jobTrigger类似,下面看具体代码,
public class TriggerListener1 implements TriggerListener {Logger logger = LoggerFactory.getLogger(TriggerListener1.class);private String timerTriggerName = "";public TriggerListener1(String timerTriggerName) {this.timerTriggerName = timerTriggerName;}@Overridepublic String getName() {logger.info("1 -----> 触发器名称 :" + timerTriggerName);return timerTriggerName;}@Overridepublic void triggerFired(Trigger trigger, JobExecutionContext jobExecutionContext) {logger.info("2 -----> Trigger被激发 它关联的job即将被运行");}@Overridepublic boolean vetoJobExecution(Trigger trigger, JobExecutionContext jobExecutionContext) {return false;}@Overridepublic void triggerMisfired(Trigger trigger) {logger.info("触发器错过执行时候被执行");}@Overridepublic void triggerComplete(Trigger trigger, JobExecutionContext jobExecutionContext, Trigger.CompletedExecutionInstruction completedExecutionInstruction) {logger.info("5 ====== triggerComplete ----------");}}
public class DemoTest2 {private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();public static void main(String[] args) throws Exception{Scheduler scheduler = schedulerFactory.getScheduler();JobDetail job = JobBuilder.newJob(MyJob.class).withIdentity("myJob1", "myJobGroup1")//.requestRecovery() // 执行中应用发生故障,需要重新执行.build();Trigger trigger = TriggerBuilder.newTrigger().withIdentity("myFirstTrigger1", "myFirstTriggerGroup1").startNow().withSchedule(CronScheduleBuilder.cronSchedule("0/3 * * * * ?")).build();scheduler.scheduleJob(job, trigger);scheduler.getListenerManager().addTriggerListener(new TriggerListener1("myFirstTrigger1"), EverythingMatcher.allTriggers());if(!scheduler.isShutdown()){scheduler.start();}}}
其实我们在阅读listener的接口实现代码时,可以发现在它的实现类中,有一个TriggerListenerSupport的抽象类,即我们也可以继承这个类,只实现其中的部分业务关注的方法
运行这段代码,观察控制台效果,和上面的效果差不多
3、SchedulerListener
SchedulerListener会在Scheduler的生命周期关键事件发生时被调用。与Scheduler有关的事件包括:增加一个job/trigger,删除一个job/trigger,scheduler发生严重错误,关闭scheduler等
参考前面两种的方式,有兴趣的同学可以点击进去看看具体的方法,这里对其中涉及到的几个方法简单解释下
- jobScheduled方法:用于部署JobDetail时调用
- jobUnscheduled方法:用于卸载JobDetail时调用
- triggerFinalized方法:当一个 Trigger 来到了再也不会触发的状态时调用这个方法。除非这个 Job 已设置成了持久性,否则它就会从 Scheduler 中移除
- triggersPaused方法:Scheduler 调用这个方法是发生在一个 Trigger 或 Trigger 组被暂停时。假如是 Trigger 组的话,triggerName 参数将为 null
- triggersResumed方法:Scheduler 调用这个方法是发生成一个 Trigger 或 Trigger 组从暂停中恢复时。假如是 Trigger 组的话,假如是 Trigger 组的话,triggerName 参数将为 null。参数将为 null
- jobsPaused方法:当一个或一组 JobDetail 暂停时调用这个方法
- jobsResumed方法:当一个或一组 Job 从暂停上恢复时调用这个方法。假如是一个 Job 组,jobName 参数将为 null
- schedulerError方法:在 Scheduler 的正常运行期间产生一个严重错误时调用这个方法
- schedulerStarted方法:当Scheduler 开启时,调用该方法
- schedulerInStandbyMode方法: 当Scheduler处于StandBy模式时,调用该方法
- schedulerShutdown方法:当Scheduler停止时,调用该方法
- schedulingDataCleared方法:当Scheduler中的数据被清除时,调用该方法
在接口实现上,可以实现SchedulerListener,也可以继承SchedulerListenerSupport抽象类,下面看具体的代码实现
@Slf4j
public class SchedulerTrigger1 extends SchedulerListenerSupport {@Overridepublic void jobAdded(JobDetail jobDetail) {log.info("1 === 监听到有一个job准备加入进去");}@Overridepublic void jobScheduled(Trigger trigger) {log.info("job准备被调度 jobScheduled");}@Overridepublic void schedulerShutdown() {log.info("job 调度准备停止的时候 schedulerShutdown");}@Overridepublic void schedulerStarted() {log.info("job 调度要开始了 schedulerStarted");}@Overridepublic void schedulerStarting() {super.schedulerStarting();}
}
public class DemoTest3 {private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();public static void main(String[] args) throws Exception {Scheduler scheduler = schedulerFactory.getScheduler();JobDetail job = JobBuilder.newJob(MyJob.class).withIdentity("myJob3", "myJobGroup3")//.requestRecovery() // 执行中应用发生故障,需要重新执行.build();Trigger trigger = TriggerBuilder.newTrigger().withIdentity("myFirstTrigger3", "myFirstTriggerGroup3").startNow().withSchedule(CronScheduleBuilder.cronSchedule("0/3 * * * * ?")).build();scheduler.scheduleJob(job, trigger);scheduler.getListenerManager().addSchedulerListener(new SchedulerTrigger1());scheduler.start();Thread.sleep(12000);scheduler.shutdown();}}
运行上面的代码,效果和上面的类似
quartz监听器与springboot的整合
在上一篇中我们讲解了与springboot的整合,这里简单的再走一遍
1、添加依赖
<dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--quartz相关依赖--><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.3.1</version></dependency><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz-jobs</artifactId><version>2.3.1</version></dependency><!--spring boot集成quartz--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>
2、两个主要的配置类
@Configuration
public class SchedulerConfig {@Autowiredprivate SpringJobFactory springJobFactory;@Bean(name="SchedulerFactory")public SchedulerFactoryBean schedulerFactoryBean() throws IOException {SchedulerFactoryBean factory = new SchedulerFactoryBean();factory.setAutoStartup(true);factory.setStartupDelay(5);//延时5秒启动factory.setQuartzProperties(quartzProperties());factory.setJobFactory(springJobFactory);return factory;}@Beanpublic Properties quartzProperties() throws IOException {PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));propertiesFactoryBean.afterPropertiesSet();return propertiesFactoryBean.getObject();}/** quartz初始化监听器*/@Beanpublic QuartzInitializerListener executorListener() {return new QuartzInitializerListener();}/** 通过SchedulerFactoryBean获取Scheduler的实例*/@Bean(name="Scheduler")public Scheduler scheduler() throws IOException {return schedulerFactoryBean().getScheduler();}}
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;
/*** 解决spring bean注入Job的问题*/
@Component
public class SpringJobFactory extends AdaptableJobFactory {@Autowiredprivate AutowireCapableBeanFactory capableBeanFactory;@Overrideprotected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {// 调用父类的方法Object jobInstance = super.createJobInstance(bundle);// 进行注入capableBeanFactory.autowireBean(jobInstance);return jobInstance;}
}
在实际开发中,最好再在资源目录下添加quartz.properties配置文件,控制quartz运行时的相关参数,比如分配线程数等,在之前的篇章中有介绍这里就不再罗列了
3、提供一个任务类,用于初始化调度任务
@Component
public class TaskRunner implements ApplicationRunner {private final static Logger LOGGER = LoggerFactory.getLogger(TaskRunner.class);@Autowired@Qualifier("Scheduler")private Scheduler scheduler;@Overridepublic void run(ApplicationArguments var) throws Exception {LOGGER.info("初始化测试任务");Date date = DateBuilder.futureDate(7, DateBuilder.IntervalUnit.SECOND);//构建job信息JobDetail job = JobBuilder.newJob(QuartzDemo.class).withIdentity("triggerJob", "triggerJobGroup").withDescription("测试任务").build();// 触发时间点CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/3 * * * * ?");Trigger trigger = TriggerBuilder.newTrigger().withIdentity("triggerJob", "triggerJobGroup").startAt(date).withSchedule(cronScheduleBuilder).build();//交由Scheduler安排触发scheduler.scheduleJob(job, trigger);//安排一个监听器scheduler.getListenerManager().addJobListener(new MyJobTriggerListener());if (!scheduler.isShutdown()) {scheduler.start();}}}
启动项目,设置的是7秒之后任务开始调度,观察控制台执行效果,到这里,与springboot的整合也完成
本篇主要讲述了quartz监听器的基本使用以及与springboot的整合,有兴趣的同学可以继续深入研究,本篇到此结束,最后感谢观看!
quartz监听器使用相关推荐
- Quartz定时任务学习(九)Quartz监听器
Quartz 提供了三种类型的监听器:监听 Job 的,监听 Trigger 的,和监听 Scheduler 自已的. 本章解释如何应用每一种类型来更好的管理你的 Quartz 应用,并获悉到什么事件 ...
- 项目中使用Quartz集群分享--转载
原文:http://hot66hot.iteye.com/blog/1726143 在公司分享了Quartz,发布出来,希望大家讨论补充. CRM使用Quartz集群分享 一:CRM对定时任务的依赖 ...
- Quartz调用大全
Quartz调用大全 1.Quartz应用范围广泛,可单独执行也可在spring中嵌入执行. 类似的定时任务在linux下可以用crontab执行 2.实现代码: QuartzTest :主要执行类 ...
- 【Quartz】解密properties配置文件中的账号密码
在配置quartz时,为了保密某些信息(特别是账号密码),通常会使用密文.那么在实际使用这些配置信息时,需要进行解密.本文提供一种解密方法如下: (1)假设在properties文件中加密了账号密码 ...
- Servlet过滤器Filter和监听器
一.Servlet过滤器的概念: *********************************************************************************** ...
- 【Quartz】任务调度
Quartz任务调度 一.Quartz概念 二.Quartz运行环境 三.Quartz设计模式 四.Quartz学习的核心概念 五.Quartz的体系结构 六.Quartz的几个常用API 七.Qua ...
- Quartz任务调度——快速入门
目录 一.Quartz概念 二.Quartz运行环境 三.Quartz设计模式 四.Quartz学习的核心概念 五.Qutarz的体系结构 六.Quartz的几个常用API 七.Quartz的使用 八 ...
- Quartz中文文档使用
Quartz中文使用说明文档,内容相当详细,有需要的码友们可以看看!! 好东西要分享!! 下面是文档的内容目录,附上下载的地址:点击打开链接,下载文档 中文版目录总汇及内容提要 第一章. 企业应用中的 ...
- quartz记录job状态
quartz记录job状态 记录job执行状态 记录执行次数 记录job执行状态 需要记录定时任务每一次的执行情况,并记录执行的次数.因为quartz在1.x版本之后不推荐使用stateful接口,我 ...
最新文章
- 编码中统一更该变量的快捷键_流媒体的7种方式使您成为更好的编码器
- 8瓶酒一瓶有毒,用人测试。每次测试结果8小时后才会得出,而你只有8个小时的时间。问最少需要(B)人测试?
- uva1624knots
- Web使用热敏打印小票(IE环境)
- 关于逻辑删除标识字段value的设定
- 最近做项目的一些关于重构方面的总结
- (二)html常用标签
- 最全的常用正则表达式大全——包括校验数字、字符、一些特殊的需求等等
- 俄罗斯方块java分析_[源码和文档分享]基于Java的俄罗斯方块游戏
- 一位教授跟我说:线性代数应该这样学
- 数据库索引类型介绍及其优缺点、区别、适用场景
- div圆角,阴影效果。
- 网络地址与直接广播地址有关计算
- Greenplum集群扩容总结
- D - Sleepy Game
- 经纬高坐标系转到东北天坐标系
- mysql 存储类型文本最大长度longtext
- c语言引用性间接变量,c语言取地址和间接引用
- 使用NPOI设置Excel表的单元格背景颜色
- 优美图案c语言程序,C语言编程之一个最优美的图案