Хотя вкратце это описано в официальной документации, я считаю, что
плагины 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.