Quartz Scheduler插件–隐藏的宝藏

尽管在官方文档中进行了简要描述,但我相信Quartz插件了解得还不够多,看看它们有多有用。

本质上,Quartz中的插件是方便的类,用于包装基础侦听器的注册。 您可以自由编写自己的插件,但我们将专注于Quartz随附的现有插件。

LoggingTriggerHistoryPlugin

首先介绍一些背景。 Quartz中的两个主要抽象是作业和触发器。 Job是我们要计划的一段代码。 触发器指示调度程序何时应运行此代码。 CRON(例如,每个星期五在9 AM到5 PM之间运行直到11月)和简单的(每2小时运行100次)触发器是最常用的。 您可以将任意数量的触发器关联到一个作业。

信不信由你,Quartz默认不提供任何日志记录或监视任何已执行的作业和触发器。 有一个API,但是没有实现内置的日志记录。 它不会向您显示由于触发触发器而现在可以执行此特定作业。 因此,您应该做的第一件事是将以下几行添加到quartz.properties中:

org.quartz.plugin.triggerHistory.class=org.quartz.plugins.history.LoggingTriggerHistoryPluginorg.quartz.plugin.triggerHistory.triggerFiredMessage=Trigger [{1}.{0}] fired job [{6}.{5}] scheduled at: {2, date, dd-MM-yyyy HH:mm:ss.SSS}, next scheduled at: {3, date, dd-MM-yyyy HH:mm:ss.SSS}org.quartz.plugin.triggerHistory.triggerCompleteMessage=Trigger [{1}.{0}] completed firing job [{6}.{5}] with resulting trigger instruction code: {9}. Next scheduled at: {3, date, dd-MM-yyyy HH:mm:ss.SSS}org.quartz.plugin.triggerHistory.triggerMisfiredMessage=Trigger [{1}.{0}] misfired job [{6}.{5}]. Should have fired at: {3, date, dd-MM-yyyy HH:mm:ss.SSS}

第一行(也是唯一需要的行)将加载插件类LoggingTriggerHistoryPlugin。 其余各行将配置插件,自定义日志消息。 我发现内置默认值不是很周全,例如,它们显示当前时间,这已经是日志框架消息的一部分。 您可以自由构造任何日志消息,有关详细信息,请参阅API。 添加这些额外的几行使调试和监视更加容易:

LoggingTriggerHistoryPlugin | Trigger [Demo.Every-few-seconds] fired job [Demo.Print-message] scheduled at:  04-04-2012 23:23:47.036, next scheduled at:  04-04-2012 23:23:51.036
//...job output
LoggingTriggerHistoryPlugin | Trigger [Demo.Every-few-seconds] completed firing job [Demo.Print-message] with resulting trigger instruction code: DO NOTHING. Next scheduled at:  04-04-2012 23:23:51.036

现在您知道为什么命名触发器(Demo.Every-few-seconds)和作业(Demo.Print-message)如此重要。

LoggingJobHistoryPlugin

还有另一个与日志记录相关的便捷插件:

org.quartz.plugin.jobHistory.class=org.quartz.plugins.history.LoggingJobHistoryPlugin
org.quartz.plugin.jobHistory.jobToBeFiredMessage=Job [{1}.{0}] to be fired by trigger [{4}.{3}], re-fire: {7}
org.quartz.plugin.jobHistory.jobSuccessMessage=Job [{1}.{0}] execution complete and reports: {8}
org.quartz.plugin.jobHistory.jobFailedMessage=Job [{1}.{0}] execution failed with exception: {8}
org.quartz.plugin.jobHistory.jobWasVetoedMessage=Job [{1}.{0}] was vetoed. It was to be fired by trigger [{4}.{3}] at: {2, date, dd-MM-yyyy HH:mm:ss.SSS}

规则是相同的–插件+额外配置。 有关详细信息和可能的占位符,请参见LoggingJobHistoryPlugin的JavaDoc 。 快速查看日志可以发现非常具有描述性的输出:

Trigger [Demo.Every-few-seconds] fired job [Demo.Print-message] scheduled at:  04-04-2012 23:34:53.739, next scheduled at:  04-04-2012 23:34:57.739
Job [Demo.Print-message] to be fired by trigger [Demo.Every-few-seconds], re-fire: 0
//...job output
Job [Demo.Print-message] execution complete and reports: null
Trigger [Demo.Every-few-seconds] completed firing job [Demo.Print-message] with resulting trigger instruction code: DO NOTHING. Next scheduled at:  04-04-2012 23:34:57.739

我不知道为什么默认情况下不启用这些插件。 毕竟,如果您不需要这样的详细输出,则可以在日志记录框架中将其关闭。 没关系,我认为在对Quartz执行进行故障排除时将它们安装到位是个好主意。

XMLSchedulingDataProcessorPlugin

这是一个非常全面的插件。 它读取包含作业的XML文件(默认名称为quartz_data.xml)并触发定义,并将其添加到调度程序中。 当您有一次需要添加一次的全局作业时,此功能特别有用。 插件可以更新现有的作业/触发器,也可以忽略XML文件(如果它们已经存在)–在使用JDBCJobStore时非常有用。

org.quartz.plugin.xmlScheduling.class=org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin

在上述文章中,我们一直在手动将作业添加到调度程序中:

val trigger = newTrigger().withIdentity("Every-few-seconds", "Demo").withSchedule(simpleSchedule().withIntervalInSeconds(4).repeatForever()).build()val job = newJob(classOf[PrintMessageJob]).withIdentity("Print-message", "Demo").usingJobData("msg", "Hello, world!").build()scheduler.scheduleJob(job, trigger)

使用XML配置可以实现相同的效果,只需将以下quartz_data.xml放在CLASSPATH中:

<?xml version="1.0" encoding="UTF-8"?>
<job-scheduling-data xmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation=" http://www.quartz-scheduler.org/xml/JobSchedulingData http://www.quartz-scheduler.org/xml/job_scheduling_data_2_0.xsd "><processing-directives><overwrite-existing-data>false</overwrite-existing-data><ignore-duplicates>true</ignore-duplicates></processing-directives><schedule><trigger><simple><name>Every-few-seconds</name><group>Demo</group><job-name>Print-message</job-name><job-group>Demo</job-group><repeat-count>-1</repeat-count><repeat-interval>4000</repeat-interval></simple></trigger><job><name>Print-message</name><group>Demo</group><job-class>com.blogspot.nurkiewicz.quartz.demo.PrintMessageJob</job-class><job-data-map><entry><key>msg</key><value>Hello, World!</value></entry></job-data-map></job></schedule></job-scheduling-data>

使用XML配置可以实现相同的效果,只需将以下quartz_data.xml放在CLASSPATH中:

org.quartz.plugin.xmlScheduling.fileNames=/etc/quartz/system-jobs.xml,/home/johnny/my-jobs.xml
org.quartz.plugin.xmlScheduling.scanInterval=60

关机钩子插件

最后但并非最不重要的是ShutdownHookPlugin。 小型但可能有用的插件,可以在JVM中注册关闭钩子,以便轻轻地停止调度程序。 但是,我建议关闭cleanShutdown –如果系统已经试图突然停止应用程序(通常是Spring通过SchedulerFactoryBean通过SchedulerFactoryBean调用调度程序关闭)或用户按下Ctrl + C –等待当前正在运行的作业似乎是个坏主意。 毕竟,也许由于某些作业运行时间过长/过长而导致我们正在终止应用程序?

org.quartz.plugin.shutdownHook.class=org.quartz.plugins.management.ShutdownHookPlugin
org.quartz.plugin.shutdownHook.cleanShutdown=false

如您所见,Qurtz附带了一些非常有趣的插件。 由于某些原因,它们在官方文档中没有详细描述,但是它们工作得很好,并且是调度程序的重要补充。

带有已应用插件的源代码可在GitHub上获得。

参考: Quartz Scheduler插件– Java和社区博客上来自JCG合作伙伴 Tomasz Nurkiewicz的隐藏宝藏 。


翻译自: https://www.javacodegeeks.com/2012/04/quartz-scheduler-plugins-hidden.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372843.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql查询表名匹配只有字母的_MySQL按某些匹配字母查询表

MySQL查询是MySQL的核心功能&#xff0c;有时候我们需要查找带有某些匹配字母的表。下文对该MySQL查询方式作了详细的介绍&#xff0c;供您参考。在MySQL中我们可以使用LIKE或者NOT LIKE操作符进行比较。在MySQL中模式默认是不区分大小写的。查询示例&#xff0c;student表----…

hdu 1181(Floyed)

变形课 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 20748 Accepted Submission(s): 7494 Problem Description呃......变形课上Harry碰到了一点小麻烦,因为他并不像Hermione那样能够记住所有的咒语而随意的…

读书笔记-你不知道的JS上-混入与原型

继承 mixin混合继承 function mixin(obj1, obj2) {for (var key in obj2) {//重复不复制if (!(key in obj1)) {obj1[key] obj2[key];}}return obj1;} 这种复制是浅复制&#xff0c;对象或者数组函数等都是同一个引用&#xff0c;改变obj1的会同时影响obj2。 寄生继承 ... 隐式…

JUnit和Hamcrest:在assertEquals上进行改进

在我的博客文章中&#xff0c;Java越来越接受静态导入吗&#xff1f; &#xff0c;我讨论了在Java中越来越多地使用静态导入来使代码在某些情况下更流畅。 Java 单元测试特别受静态导入的影响&#xff0c;在此博客文章中&#xff0c;我提供了一个简单的示例&#xff0c;说明如何…

mysql delete temporary denied_这些错误是什么意思?djang中的mysql

我试着运行一个程序&#xff0c;我被给予了一个例子&#xff0c;它就像一个购物网站&#xff0c;使用MySQL数据库而不是Django提供的原始数据库&#xff01;我只是想看看有没有人理解这些错误的含义&#xff1f;任何信息都将不胜感激&#xff01;我本可以提供网页的代码&#x…

C语言 · 芯片测试

基础练习 芯片测试 时间限制&#xff1a;1.0s 内存限制&#xff1a;512.0MB问题描述有n&#xff08;2≤n≤20&#xff09;块芯片&#xff0c;有好有坏&#xff0c;已知好芯片比坏芯片多。每个芯片都能用来测试其他芯片。用好芯片测试其他芯片时&#xff0c;能正确给出被测试…

Animation用法

测试代码及说明&#xff1a; <!DOCTYPE html> <html lang"en-US"> <head><meta charset"UTF-8"><title>Simple CSS3 Animation</title><style type"text/css">#demo {position: absolute;left: 30%;t…

mysql dese_MySQL 5.6-类似于DENSE_RANK的功能,无需订购

小编典典对于 MySQL版本<8.0(OP的版本是5.6)&#xff1a;问题陈述看起来需要DENSE_RANK功能groupVarian; 但是事实并非如此。正如 GordonLinoff解释的那样 &#xff1a;您似乎希望按它们在数据中出现的顺序来枚举它们。假设您的表名是t(请为您的代码相应地更改表名和字段名)…

Spring和JSF集成:动态导航

通常&#xff0c;您的JSF应用程序将需要超越基本的静态导航并开始做出动态导航决策。 例如&#xff0c;您可能想根据用户的年龄重定向他们。 大多数JSF教程建议通过将命令的action属性绑定到支持bean来实现动态导航&#xff1a; <h:commandButton action"#{bean.action…

通过富文本改变UITextFieldPlaceholder颜色

1、通过属性 a、 //文字属性(一般) NSMutableDictionary *attrs [NSMutableDictionary dictionary]; attrs[NSForegroundColorAttributeName] [UIColor blueColor]; NSAttributedString *placeholderStr [[NSAttributedString alloc] initWithString:"手机号" a…

阻塞/非阻塞/同步/异步方法和多线程的关系?没有任何关系,俩不挨着

1.阻塞非阻塞异步同步是针对方法说的&#xff0c;是评判一个方法运行状态的。和多线程完全两个级别。 2.阻塞非阻塞异步同步是针对方法说的&#xff0c;是评判一个方法运行状态的。和多线程完全两个级别。 3.阻塞非阻塞异步同步是针对方法说的&#xff0c;是评判一个方法运行状…

mysql备份 where_MySQL备份与还原

1.mysqldumpmysqlbinlog介绍mysqldump备份结合binlog日志恢复。MySQL备份一般采取全库备份加日志备份的方式&#xff0c;例如每天执行一次全备份&#xff0c;每小时执行一次二进制日志备份&#xff0c;这样在MySQL故障后可以使用全备份和日志备份将数据恢复到最后一个二进制日志…

JMeter:负载测试关系数据库

Apache JMeter是完全使用Java编写的性能测试工具。 可以在请求/响应模型上运行的任何应用程序都可以使用JMeter进行负载测试。 关系数据库也不例外&#xff1a;接收sql查询&#xff0c;执行它们并返回执行结果。 我将向您展示使用JMeter的图形用户界面设置测试方案有多么容易。…

new: Set up a window

Nehe的教程确实太老了&#xff0c;不过我认为它也能够让我了解OpenGL3.2以前的管线渲染模式&#xff0c;即使它在现在已经不常见了。因为想要了解&#xff0c;所以我还是会看完Nehe的教程。 现在这是一个新的教程 - JoeyDeVries的教程&#xff0c;可以说是网上最好的OpenGL教程…

Python全栈开发:socket

Socket socket通常也称作"套接字"&#xff0c;用于描述IP地址和端口&#xff0c;是一个通信链的句柄&#xff0c;应用程序通常通过"套接字"向网络发出请求或者应答网络请求。 socket起源于Unix&#xff0c;而Unix/Linux基本哲学之一就是“一切皆文件”&…

oracle sga pga mysql_修改Oracle数据库SGA和PGA大小

SGA的大小&#xff1a;一般物理内存20%用作操作系统保留&#xff0c;其他80%用于数据库。SGA普通数据库可以分配40%-60%之间&#xff0c;PGA可以分配20%-40%之间。1、以dba身份登录并查看SGA信息&#xff1a;SQL>show parameter sga&#xff1b;查看PGA信息&#xff1a;SQL&…

NetBeans 7.1:创建自定义提示

我已经在帖子中介绍了一些我最喜欢的NetBeans提示 &#xff0c;这些信息是用于使Java代码现代化的七个NetBeans提示和七个不可或缺的NetBeans Java提示 。 这两个帖子中涉及的十四个提示仅占NetBeans支持的“即开即用”提示总数的一小部分。 但是&#xff0c;由于NetBeans 7.1使…

今年暑假不AC

Problem Description “今年暑假不AC&#xff1f;”“是的。”“那你干什么呢&#xff1f;”“看世界杯呀&#xff0c;笨蛋&#xff01;”“#$%^&*%...”确实如此&#xff0c;世界杯来了&#xff0c;球迷的节日也来了&#xff0c;估计很多ACMer也会抛开电脑&#xff0c;奔向…

qregexp括号匹配_转:Qt的正则表达式和QRegExp

考虑一下我们经常遇到的问题&#xff0c;比如gemfield想从青岛之光读书(www.civilnet.cn/book)中找一个关键的电话号码&#xff0c;通常第一步就是将书中所有的电话号码查找出来放在手边。那么怎么拟定查询条件呢&#xff1f;电话的格式有如下几种&#xff1a;01088888888010 8…

具有Tron效果的JavaFX 2 Form

这是一个具有TRON效果的简单JavaFX登录表单。 在此示例中&#xff0c;我使用CSS设置TextField和Button的样式。 这是CSS和Effect代码的片段&#xff1a; .text-field{-fx-background-color: transparent;-fx-border-color: #00CCFF;-fx-text-fill: white; }.password-field{-fx…