Хотя вкратце это описано в официальной документации, я считаю, что
плагины Quartz недостаточно известны, если посмотреть, насколько они полезны.
По сути, плагины в Quartz — это удобные классы, заключающие в себе регистрацию базовых
слушателей . Вы можете написать свои собственные плагины, но мы сосредоточимся на существующих, поставляемых с Quartz.
LoggingTriggerHistoryPlugin
Сначала немного предыстории. Две основные абстракции в Кварце — рабочие места и триггеры. Работа — это кусок кода, который мы хотели бы запланировать. Trigger указывает планировщику, когда должен выполняться этот код. CRON (например, запускаются каждую пятницу с 9:00 до 17:00 до ноября ) и простые ( запускаются 100 раз каждые 2 часа ) триггеры наиболее часто используются. Вы связываете любое количество триггеров с одной работой.
Верьте или нет, Quartz по умолчанию не обеспечивает ведение журнала или мониторинг выполненных заданий и триггеров. Существует API, но встроенное ведение журнала не реализовано. Он не покажет вам, что теперь он выполняет эту конкретную работу из-за срабатывания триггера. Поэтому первое, что вы должны сделать, это добавить следующие строки в ваш quartz.properties:
org.quartz.plugin.triggerHistory.class=org.quartz.plugins.history.LoggingTriggerHistoryPlugin
org.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-two-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}
Правило то же самое — плагин + дополнительная настройка. Посмотрите JavaDoc LoggingJobHistoryPlugin для деталей и возможных заполнителей. Быстрый просмотр журналов показывает очень описательный вывод:
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>
Файл поддерживает как простые триггеры, так и триггеры CRON и хорошо описан с использованием схемы XML . Можно даже указать на XML-файлы где-нибудь в файловой системе и периодически сканировать их на наличие изменений (!) (См. XMLSchedulingDataProcessorPlugin.setScanInterval () . Угадайте, что использует Quartz для планирования периодического сканирования?
org.quartz.plugin.xmlScheduling.fileNames=/etc/quartz/system-jobs.xml,/home/johnny/my-jobs.xml org.quartz.plugin.xmlScheduling.scanInterval=60
ShutdownHookPlugin
Наконец, что не менее важно , ShutdownHookPlugin . Небольшой, но, вероятно, полезный плагин, который регистрирует отключение в JVM, чтобы аккуратно остановить планировщик. Однако я рекомендую отключить cleanShutdown — если система уже пытается внезапно остановить приложение (обычно завершение работы планировщика вызывается Spring через SchedulerFactoryBean) или пользователь нажимает Ctrl + C — ожидание текущих выполняемых заданий кажется плохой идеей. В конце концов, может быть, мы убиваем приложение, потому что некоторые задания выполняются слишком долго / зависают?
org.quartz.plugin.shutdownHook.class=org.quartz.plugins.management.ShutdownHookPlugin org.quartz.plugin.shutdownHook.cleanShutdown=false
Как вы можете видеть корабли Qurtz с несколькими довольно интересными плагинами. По некоторым причинам они не описаны подробно в официальной документации, но они работают довольно хорошо и являются ценным дополнением к планировщику.
Исходный код с примененными плагинами доступен на GitHub.