与Quartz的半日情结

2023-12-05 04:32
文章标签 quartz 半日 情结

本文主要是介绍与Quartz的半日情结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

12月8日
与Quartz的半日情结
最近一直在处理报表订阅的一些历史遗留问题,编码人离职了,理所当然就得是我这个专门负责给人"擦PP"的人去解决了.虽然解决了大部分问题,但今天好悬就把偶搞傻掉了.

先说下Quartz这个玩意吧,说得挺悬乎,是一个开源组织在任务调度方面的一个框架.它可以用来创建简单的任务,当然也可以去运行上万个任务的复杂程序表.

之前解决问题时,没怎么涉及到这个东西,即便是涉及,那也是非常简单的配置参数错误或者分组混乱而已,所以对它也没有什么了解或是学习.但今天出现的问题,真是把我逼到了悬崖上,呵呵.

怎么说呢,问题那是相当严重啊.B/S下的Quartz应用配置涉及到三个文件:
1.配置启动Quartz服务的web.xml;
2.配置Quartz运行时环境的quartz.properties;
3.配置任务明细的任务单--job.xml.
PS:后两个配置文件的名称可变.

我们的问题首先出在,应用服务器启动状态下,当对任务进行了修改时(即修改了job.xml中的任务明细),Quartz无法响应这种变化.也就是说,Quartz并没有进行"有状态"作业!这对于我来说的确是一个比较棘手的问题,因为针对我们的报表订阅来说,无论是修改了任务明细中的参数列表--JobDataMap,或是CronExpression中的定时表达式,都应该立即做出响应,并按照新的配置参数去执行这个任务并发送Excel或PDF格式的报表.

怎么说呢,这个问题并不至于让我慌乱,因为直觉告诉我,使用Quartz的应用job reload应该是一个相对来说比较常见的事情,而一个在任务调度领域倍受好评的开源框架不会不去解决它.Google了一下,不知是我的搜索条件写得准确还是这个问题较常见,第一条结果就是我想要的.只需要在quartz.properties中加入下面两行配置即可:
#自动扫描任务单并发现改动的时间间隔,单位为秒
org.quartz.plugin.jobInitializer.scanInterval = 10
#覆盖任务调度器中同名的jobDetail,避免只修改了CronExpression所造成的不能重新生效情况
org.quartz.plugin.jobInitializer.overWriteExistingJobs = true

搞定这个问题后本来应该是大吉安事了,没想到的是,前边这个问题仅仅是暴风雨的前夜而已...

测试任务单变更自检的问题时,突然发现,当通过web页面提供的任务配置接口进行报表订阅任务的新增、修改等操作时,由于job.xml是在classes目录下,所以tomcat会进行自动的reload.这看起来好象没什么问题,但在实际的应用环境下却非常危险,因为web.xml中配置的随tomcat启动而启动的程序都会reload.可能这些程序很简单,并不会产生什么问题,但我们的软件则不同,随tomcat的启动,会有很多服务被启动并进行着极为复杂的操作,所以classes目录下的程序配置项都不会轻易修改.即使是修改,那也会重新启动tomcat使服务正常运转.

修改了任务单后观察了下,果然最郁闷的事情发生了,某个服务出现了Illegal Access问题.这还只是一个服务,谁又能保证其它的服务不会产生问题呢?最终的结论很让我沮丧:一是使用Quartz去做这个极容易改变任务明细的产品,彻头彻尾就是错误的,从而直接否定了目前报表订阅的所有工作,包括前期的分析与设计;二就是答应用户12月可以使用的报表订阅产品搁浅,因为这样就投入使用,就好象浑身缠满TNT去玩Zippo一样,后果...
在思考如何解决这个问题的过程中,我以Debug的方式,将Quartz的源代码从头到尾的跑了N遍.不仅弄清楚了其工作原理,而且还知道了它的配置项对任务执行所起到的作用.感觉Quartz嘛,就是一个帮我们考虑了很多可能发生的事情,并且还给了我们一些额外功能的Timer.

问题的解决往往就在不经意之间,并且要敢于向常理说不.既然Quartz的两个主要配置文件名称可变,而且是从web.xml加载quartz.properties,又从quartz.properties找到job.xml,那么凭什么job.xml就必须要放到classes目录下呢?

好,既然不凭什么,那就彻底颠覆一下吧,呵呵.首先将job.xml拿到web目录下,就放到config/job.xml吧.然后修改quartz.properties文件,将文件指向修改成绝对路径:
org.quartz.plugin.jobInitializer.fileName = D:/tomcat/webapps/report/config/job.xml
然后修改job.xml的XML文件操作接口,将配置文件获取部分的代码从/WEB-INF/classes目录变更到/config目录.测试通过!这种不按常理出牌的方式,解决了所有问题,仍然可对任务明细进行操作,并且通过quartz.properties中的配置让Quartz自己发现这种变更.而且,job.xml无论如何变更,tomcat都不会reload,因为它已经不在classes目录下了.捏哈哈^_^

在Debug过程中,发现Quartz的一个小问题,可能会对资源造成无谓的占用.那就是当一个任务从job.xml中被删除时,Quartz是不会响应这种减少任务的改变的,此任务的进程仍然被占用,而且任务还会被执行.处理这种问题,可以考虑在JobDataMap中增加是否执行的配置项,即使任务会执行,但根据这种配置项,仍然可以拒绝下一步的操作.当然了,修改CronExpression使之成为一个永远不会执行到的时间也是一个BT的办法.

最后再来一个个人想法,算是以后考虑实现的Quartz高级应用吧.那就是目前Quartz只会去加载一个job.xml.这对于多模块使用job.xml有一点不爽,因为无法具体将任务按照不同模块进行区分或单独维护.实现SchedulerPlugin接口并提供多任务文件加载功能,将会是解决这个事情的好方法.

从入门到精通,半天时间不是啥难事,上次是Ajax,这次是Quartz而已.

这篇关于与Quartz的半日情结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/456162

相关文章

spring quartz详解

1、   CronTrigger时间格式配置说明 CronTrigger配置格式: 格式: [秒] [分] [小时] [日] [月] [周] [年] 序号 说明 是否必填 允许填写的值 允许的通配符 1 秒 是 0-59  , - * / 2 分 是 0-59 , - * / 3 小时 是 0-23 , - * / 4 日 是 1

Quartz 作业调度器

1、Quartz  java实现  注:这里使用的是Quartz1.6.5版本(包:quartz-1.6.5.jar)   [java]  view plain copy //测试main函数   //QuartzTest.java   package quartzPackage;         import java.text.SimpleDateFormat

Quartz数据表-Oracle

在Quartz的安装包中,解压文件,可以得到数据库脚本文件。 QRTZ_CALENDARS 以 Blob 类型存储 Quartz 的 Calendar 信息  QRTZ_CRON_TRIGGERS 存储 Cron Trigger,包括 Cron表达式和时区信息  QRTZ_FIRED_TRIGGERS 存储与已触发的 Trigger 相关的状态信息,以及相联 Job的执行信息 QR

quartz基本概念

入门案例 import org.quartz.Job;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;public class HelloJob implements Job {private String j1;public void setJ1(String j1) {this.j

quartz源码-Schedule启动过程分析

演示demo public class HelloJob implements Job {private String j1;public void setJ1(String j1) {this.j1 = j1;}@Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {Syst

Quartz.Net_依赖注入

简述 有时会遇到需要在IJob实现类中依赖注入其他类或接口的情况,但Quartz的默认JobFactory并不能识别具有有参构造函数的IJob实现类,也就无法进行依赖注入 需要被依赖注入的类: public class TestClass{public TestClass(Type jobType, string cronExpression){JobType = jobType;Cron

java定时器task:scheduler和quartz

在javaweb项目中,经常用到定时器功能,这里介绍两个我使用过的解决方案,分别是:scheduler 和 quartz。 scheduler: 需要在spring.xml配置文件中添加关于task的配置: <beans xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="

Quartz.Net_侦听触发器

简述 触发器执行任务时存在数个阶段,利用侦听器可以在对应的阶段执行一些代码 如何侦听 1.实现ITriggerListener接口,并实现其函数,具体说明见代码注释 public class DeleteAfterCompleted : ITriggerListener{public string Name => "X";// 触发时public async Task TriggerFi

SpringBoot整合自定义quartz实现任务调度

在不引入quartz相关表的情况下,自定义任务调度存储表,实现SpringBoot项目启动后自动执行自定义任务调度类。 1、建立自定义任务调度存储表 DROP TABLE IF EXISTS `bmd_flow_schedule`;CREATE TABLE `bmd_flow_schedule` (`taskID` char(20) NOT NULL,`taskName` varchar(3

Quartz任务调度框架

文章目录 前言一、介绍二、使用步骤1.创建maven工程,添加依赖2.创建任务3.启动任务 三、基本实现原理1. Scheduler任务调度器2. Triggers触发器2.1 SimpleTrigger2.2 CronTirgger 3. Misfire策略4 任务Job4.1 Job4.2 JobDetail4.3 JobDataMap 前言 最近跟的一个系统需要实时