Автор оригинала: Arpendu Kumar Garai.
Вступление
Время дорого и делегирование времени и ресурсов для выполнения рутинных задач приводит к пустой трате ресурсов и денег. Следовательно, организации стремятся достичь полномасштабной автоматизации в своих системах, поскольку она намного масштабируема и значительно дешевле.
По мере усложнения бизнес-процессов возрастает и преимущество автоматизации в системе.
Автоматизация – это то, где преобладают концепции Рабочих мест или Графиков . Планирование заданий часто называют любым видом пакета процессов (заданий), выполняемых в заданное время. Поскольку большинство этих заданий не требуют немедленного выполнения, их можно запланировать для обработки в ближайшем будущем или через повторяющиеся интервалы времени.
В целом, автоматизация любого процесса с использованием ручного подхода приводит к:
- Эффективность Использования Ресурсов
- Меньше ошибок
- Большая масштабируемость
Одна из самых мощных и гибких систем планирования, используемых для крупномасштабных приложений Java, известна как Quartz .
В этом руководстве мы будем внедрять Quartz и его компоненты в приложение Spring Boot, создавая нашу собственную консоль управления Quartz для пользовательских Заданий и Триггеров .
Примечание: Работоспособная, полноценная копия Консоли управления Quartz , которую мы будем создавать, доступна на нашем GitHub .
Планировщик заданий Quartz
Quartz -это фреймворк планирования заданий с открытым исходным кодом, написанный на Java и предназначенный для интеграции с любым типом фреймворка J2EE или J2SE. Он обеспечивает огромную гибкость без ущерба для сложности или масштабируемости.
Название, предположительно, происходит от кварцевого кристалла , используемого в чрезвычайно точных часах и часах, которые при электрическом колебании перемещают стрелки часов в обычное время.
Если ожидается, что приложение будет выполнять задачи с запланированными интервалами или в связи с некоторыми событиями, Quartz отлично подойдет:
- Запуск напоминаний или предупреждений по электронной почте : вы можете легко запускать сообщения с истекшим сроком действия пароля или другие виды напоминаний для разных пользователей в зависимости от активности учетной записи.
- Выполнение операций передачи файлов или обмена сообщениями : Задания можно легко планировать через определенные промежутки времени для публикации/использования сообщений/данных/файлов от различных брокеров или FTP-сайтов.
- Автоматическое создание отчетов : Компании часто предпочитают создавать еженедельные/еженедельные отчеты для демонстрации эффективности бизнеса. Эти задания могут легко создавать отчеты и отправлять электронные письма сотрудникам в запланированное время.
- Управление рабочим процессом задачи : Крупные организации электронной коммерции могут планировать выполнение задания точно через определенные промежутки времени, чтобы выбрать заказ из канала и обработать его для выполнения или проявления.
Некоторые из характерных особенностей кварца являются:
- Он может быть создан в контейнере сервера приложений или сервлета и может участвовать в транзакциях XA.
- Он может быть размещен в виде кластера автономных программ (с возможностью балансировки нагрузки и отработки отказа) для выполнения заданий.
- Задания планируются для выполнения при возникновении триггера, например, в определенное время суток, определенные дни недель, месяцев или лет, пропуск выполнения в праздничные дни, повторное выполнение до определенной даты или на неопределенный срок и т.д.
- Задания могут сохраняться либо в памяти, либо в любом хранилище данных JDBC.
- Он может участвовать в транзакциях JTA.
Ключевые компоненты модели планировщика Quartz
Для улучшения масштабируемости Quartz работает в многопоточной среде. Это помогает платформе выполнять задания одновременно.
Сердцем общей структуры является интерфейс Планировщик
. Планировщик
отслеживает все Список заданий
и Триггеры
для них. Они представляют что необходимо выполнить (какое Задание
) и когда (что Запускает
это задание).
Таким образом, они образуют основные компоненты структуры. Остальные остальные компоненты обеспечивают, чтобы это происходило с должной осмотрительностью и эффективно.
Давайте взглянем орлиным глазом на ключевые компоненты, которые мы будем использовать:
- Фабрика планировщика – Компонент фабрики, который отвечает за построение модели
Планировщика
и подключение всех зависимых компонентов на основе содержимого файла свойств quartz. - Планировщик – Поддерживает Список заданий |//Триггер реестр. Он также отвечает за выполнение связанных заданий при срабатывании триггера. Поток планировщика
- – Поток, ответственный за выполнение работы по запуску триггеров. Он связывается с Магазином заданий
, чтобы получить следующий набор триггеров для запуска.
Задание - – Интерфейс, который должен быть реализован выполняемой задачей. Триггер
- – Указывает планировщику время выполнения соответствующего задания. JobStore
- – Интерфейс, реализуемый классами, обеспечивающими механизм хранения Заданий и триггеров. Пул потоков
- – Выполняемое задание передается в пул потоков, представленный пулом потоков
.
Рабочие потоки - – Отдельные потоки, которые создают Пул потоков
и выполняют задания.
Создание консоли управления Quartz
Мы создадим вашу собственную Консоль управления Quartz , чтобы получить представление и оценить жизненные циклы в планировщике Quartz.
С этой целью мы создадим простую консоль управления, управляемую пользовательским интерфейсом, которая может выполнять два вида задач:
- Планируйте и управляйте простой работой
- Планирование и управление заданием Cron
Это будет выглядеть примерно так после внедрения:
Настройка проекта
Давайте создадим проект Spring Boot и реализуем каждый компонент Quartz один за другим. Самый простой способ начать со скелетного проекта-это Spring Initializr :
Мы добавили Spring Web для функций MVC, Spring Data JPA для хранения данных в хранилище данных, H2 в качестве базы данных в памяти, Ломбок (дополнительная библиотека для сокращения шаблонов) и Thymeleaf (Механизм шаблонов для приложений Spring/MVC). Мы также включили пакет spring-boot-starter-quartz
, чтобы включить Кварц в наш проект.
Подключение и инициализация базы данных
Кварц приносит свои собственные встроенные Магазины вакансий . В весенней загрузке мы можем выбирать между:
- Хранилища заданий в памяти : Храните все данные в оперативной памяти, чтобы при остановке или сбое приложения все данные сбрасывались и вся информация о планировании терялась. Для этого мы используем
RAMJobStore
. - JDBC Jobstore : Сохраняйте все данные в хранилище данных, чтобы данные не были потеряны. Конфигурация немного сложнее, чем хранилища заданий в оперативной памяти (ОЗУ).
Примечание: Вы можете выбрать эти типы JobStore
независимо от вашей базы данных.
Мы будем использовать H2 в качестве хранилища данных и настраивать Quartz для сохранения данных.
Quartz требует, чтобы вы инициализировали таблицы базы данных для JDBC Jobstore, так как они не создаются автоматически. С этой целью мы будем использовать сценарий SQL для запуска при инициализации базы данных. Вы можете найти сценарий инициализации на нашем GitHub .
Давайте начнем разработку нашего приложения для управления с определения параметров подключения к базе данных для H2. В вашем файле application.properties
давайте определим init.schema
(сценарий начальной установки), а также источник данных
параметры:
server.port=8080 spring.sql.init.schema-locations=classpath:db/quartz_tables_h2.sql spring.h2.console.enabled=true spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.username=sa spring.datasource.password= logging.level.org.hibernate.SQL=debug
Сценарий quartz_tables_h2.sql
состоит из длинного набора команд SQL, используемых для его первоначальной настройки:
-- Note, Quartz depends on row-level locking which means you must use the MVC=TRUE -- setting on your H2 database, or you will experience dead-locks -- -- In your Quartz properties file, you'll need to set -- org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate CREATE TABLE QRTZ_CALENDARS ( SCHED_NAME VARCHAR(120) NOT NULL, CALENDAR_NAME VARCHAR (200) NOT NULL , CALENDAR IMAGE NOT NULL ); ... -- Download the entire script from our GitHub repository ... COMMIT;
Свойства Кварца
Как только соединение с базой данных будет установлено и у нас будет готов сценарий инициализации, мы захотим настроить планировщик Quartz и его компоненты.
Большинство аспектов и компонентов в определенной степени настраиваются, например, какие драйверы JobStore
должны использоваться, сколько потоков находится в Пуле потоков
и какой у них приоритет и т.д.
Все они определены в файле quartz.properties
, который должен находиться в разделе /src/ресурсы/|/. Это каталог, в котором класс
Quartz Properties по умолчанию ищет требуемые свойства.
Примечание: Если вы хотите определить его в другом файле свойств, вам нужно указать свойство org.quartz.properties
system, чтобы указать на этот файл.
Давайте теперь определим некоторые свойства:
#============================================================================ # Configure Main Scheduler Properties #============================================================================ org.quartz.scheduler.instanceName=spring-boot-quartz org.quartz.scheduler.instanceId=AUTO #============================================================================ # Configure ThreadPool #============================================================================ org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount = 25 org.quartz.threadPool.threadPriority = 5 #============================================================================ # Configure JobStore #============================================================================ org.quartz.jobStore.misfireThreshold=1000 org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate org.quartz.jobStore.useProperties=true org.quartz.jobStore.tablePrefix=QRTZ_ #============================================================================ # Configure Cluster properties #============================================================================ org.quartz.jobStore.isClustered=true org.quartz.jobStore.clusterCheckinInterval=1000
Определение компонента Фабрики заданий планировщика
Все эти свойства мало что значат, если мы не используем их в классе @Configuration
для настройки работы Quartz. Давайте введем свойства из quartz.properties
в класс Конфигурация планировщика
, где мы инициализируем класс SchedulerJobFactoryBean
, передав свойства.
Мы будем реализовывать наш собственный Планировщик JobFactory, который будет
как SpringBeanJobFactory
из проекта Quartz:
@Configuration public class SchedulerConfig { @Autowired private DataSource dataSource; @Autowired private ApplicationContext applicationContext; @Autowired private QuartzProperties quartzProperties; @Bean public SchedulerFactoryBean schedulerFactoryBean() { SchedulerJobFactory jobFactory = new SchedulerJobFactory(); jobFactory.setApplicationContext(applicationContext); Properties properties = new Properties(); properties.putAll(quartzProperties.getProperties()); SchedulerFactoryBean factory = new SchedulerFactoryBean(); factory.setOverwriteExistingJobs(true); factory.setDataSource(dataSource); factory.setQuartzProperties(properties); factory.setJobFactory(jobFactory); return factory; } }
Класс Свойства кварца
содержит свойства, определенные в файле quartz.properties
. Мы можем получить их с помощью GetProperties()
и добавить их в SchedulerFactoryBean
вместе с Источником данных
и SchedulerJobFactory
.
Планировщик JobFactory
– это наша пользовательская реализация SpringBeanJobFactory
, которую предоставляет нам Quartz. Давайте расширим его:
public class SchedulerJobFactory extends SpringBeanJobFactory implements ApplicationContextAware { private AutowireCapableBeanFactory beanFactory; @Override public void setApplicationContext(final ApplicationContext context) { beanFactory = context.getAutowireCapableBeanFactory(); } @Override protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception { final Object job = super.createJobInstance(bundle); beanFactory.autowireBean(job); return job; } }
Теперь мы можем создавать рабочие места на нашем заводе и подключать его автоматически, когда это необходимо. На этом этапе – мы можем вызвать запущенный экземпляр планировщика Quartz. Если мы запустим наше приложение, нас встретят чем-то вроде:
Определение создателя универсального планировщика заданий
В Quartz есть два типа триггеров – CronTrigger
и Простой триггер
. Они соответствуют планировщику Cron
и SimpleScheduler
соответственно, и мы можем создавать триггеры, используя их соответствующие фабрики.
/| CronTrigger запускает триггеры на основе выражения
cron , в то время как Простой триггер запускает на интервале.
Чтобы создать триггеры заданий, давайте определим несколько удобных методов, которые создают экземпляры и возвращают их через соответствующие фабрики. Эти методы будут расположены в Планировщике заданий Create
– a @Component
, который мы будем использовать для создания заданий и триггеров:
@Component public class JobScheduleCreator { // Creation methods }
Давайте начнем с метода CronTrigger
creator:
Git Essentials
Ознакомьтесь с этим практическим руководством по изучению Git, содержащим лучшие практики и принятые в отрасли стандарты. Прекратите гуглить команды Git и на самом деле изучите это!
public CronTrigger createCronTrigger(String triggerName, Date startTime, String cronExpression, int misFireInstruction) { CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean(); factoryBean.setName(triggerName); factoryBean.setStartTime(startTime); factoryBean.setCronExpression(cronExpression); factoryBean.setMisfireInstruction(misFireInstruction); try { factoryBean.afterPropertiesSet(); } catch (ParseException e) { log.error(e.getMessage(), e); } return factoryBean.getObject(); }
Используя CronTriggerFactoryBean
, мы передаем необходимую информацию о триггере
, такую как его имя, время запуска, а также выражение cron и инструкцию по пропуску. После создания – объект возвращается.
Почти тот же процесс применяется для создания Простого триггера
объектов:
public SimpleTrigger createSimpleTrigger(String triggerName, Date startTime, Long repeatTime, int misFireInstruction) { SimpleTriggerFactoryBean factoryBean = new SimpleTriggerFactoryBean(); factoryBean.setName(triggerName); factoryBean.setStartTime(startTime); factoryBean.setRepeatInterval(repeatTime); factoryBean.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY); factoryBean.setMisfireInstruction(misFireInstruction); factoryBean.afterPropertiesSet(); return factoryBean.getObject(); }
С помощью простого способа создания триггеров мы также можем создать удобный метод создания заданий – опираясь на JobDetailFactoryBean
:
public JobDetail createJob(Class extends QuartzJobBean> jobClass, boolean isDurable, ApplicationContext context, String jobName, String jobGroup) { JobDetailFactoryBean factoryBean = new JobDetailFactoryBean(); factoryBean.setJobClass(jobClass); factoryBean.setDurability(isDurable); factoryBean.setApplicationContext(context); factoryBean.setName(jobName); factoryBean.setGroup(jobGroup); // Set job data map JobDataMap jobDataMap = new JobDataMap(); jobDataMap.put(jobName + jobGroup, jobClass.getName()); factoryBean.setJobDataMap(jobDataMap); factoryBean.afterPropertiesSet(); return factoryBean.getObject(); }
Определение сущности Сведений о задании планировщика
Чтобы отслеживать детали и информацию о работе – мы можем использовать Сведения о работе
класс. Вот для чего это предназначено. Однако мы можем извлечь выгоду из определения собственного прокси-сервера для этого класса.
Не рекомендуется писать в таблицы Quartz напрямую самим , поэтому задания и их детали, хотя и сохраняются, исправлены. Мы можем определить новую сущность для отслеживания этих заданий в отдельной таблице и делать с ними все, что пожелаем, а также использовать эти объекты в качестве Объектов передачи данных (DTOs) одновременно.
Это позволяет нам выполнять проверку входящих данных и обеспечивает более детальный контроль над сохранением заданий в базе данных.
Хотя это необязательно, рекомендуется использовать такой прокси – сервер-мы назовем его SchedulerJobInfo
:
// Lombok annotations for getters, setters and constructor public class SchedulerJobInfo { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private String jobId; private String jobName; private String jobGroup; private String jobStatus; private String jobClass; private String cronExpression; private String desc; private String interfaceName; private Long repeatTime; private Boolean cronJob; }
Для простой функциональности CRUD – мы создадим простой JpaRepository
для этой сущности:
@Repository public interface SchedulerRepository extends JpaRepository{ SchedulerJobInfo findByJobName(String jobName); }
Выполнение заданий в Quartz – Работа и QuartzJobBean
Каждое задание должно либо расширить класс QuartzJobBean
, либо реализовать интерфейс Job
.
QuartzJobBean
реализует Задание
и единственная разница в том, что QuartzJobBean
применяет переданные JobDataMap
и SchedulerContext
в качестве значений свойств компонента, тогда как Задание
этого не делает.
Кроме того, Задание
требует реализации метода execute ()
, в то время как QuartzJobBean
требует реализации метода executeInternal ()
.
Давайте создадим Простое задание
, которое расширяет QuartzJobBean
и выводит целые числа из 0 чтобы 5 :
public class SimpleJob extends QuartzJobBean { @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { log.info("SimpleJob Start................"); IntStream.range(0, 5).forEach(i -> { log.info("Counting - {}", i); try { Thread.sleep(1000); } catch (InterruptedException e) { log.error(e.getMessage(), e); } }); log.info("SimpleJob End................"); } }
Аналогично, мы можем создать Простое задание Cron
, которое запускает определенное выражение cron:
@DisallowConcurrentExecution public class SimpleCronJob extends QuartzJobBean { @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { log.info("SimpleCronJob Start................"); IntStream.range(0, 10).forEach(i -> { log.info("Counting - {}", i); try { Thread.sleep(1000); } catch (InterruptedException e) { log.error(e.getMessage(), e); } }); log.info("SimpleCronJob End................"); } }
Примечание: Мы применяем @DisallowConcurrentExecution
, чтобы это задание не выполнялось несколькими планировщиками одновременно в кластеризованной настройке.
Определение пользовательских утилит для действий
В консоли управления Quartz у нас будет несколько вариантов заданий:
- Создавать
- Редактировать
- Беги Один Раз
- Пауза
- Возобновиться
- Удалить
Они позволяют нам создавать, редактировать, приостанавливать, возобновлять, удалять и запускать задание один раз. Чтобы облегчить это – мы напишем методы для каждой задачи, позволяющие нам управлять заданиями с помощью действительно простого и интуитивно понятного пользовательского интерфейса.
Чтобы связать все это воедино, мы создадим новый класс – Службу заданий Планировщика
для выполнения этих действий:
@Transactional @Service public class SchedulerJobService { @Autowired private Scheduler scheduler; @Autowired private SchedulerFactoryBean schedulerFactoryBean; @Autowired private SchedulerRepository schedulerRepository; @Autowired private ApplicationContext context; @Autowired private JobScheduleCreator scheduleCreator; // Create, edit, pause jobs, etc...
Создайте задание Quartz
Для создания заданий собственный метод saveOrUpdate()
определяет, должен ли экземпляр, созданный с помощью определенного SchedulerJobInfo
DTO, быть сохранен в существующей сущности или должно быть создано новое задание. Основываясь на параметрах полезной нагрузки, мы либо создадим Простое задание Cron
, либо Простое задание
:
public void saveOrUpdate(SchedulerJobInfo scheduleJob) throws Exception { if (scheduleJob.getCronExpression().length() > 0) { scheduleJob.setJobClass(SimpleCronJob.class.getName()); scheduleJob.setCronJob(true); } else { scheduleJob.setJobClass(SimpleJob.class.getName()); scheduleJob.setCronJob(false); scheduleJob.setRepeatTime((long) 1); } if (StringUtils.isEmpty(scheduleJob.getJobId())) { log.info("Job Info: {}", scheduleJob); scheduleNewJob(scheduleJob); } else { updateScheduleJob(scheduleJob); } scheduleJob.setDesc("i am job number " + scheduleJob.getJobId()); scheduleJob.setInterfaceName("interface_" + scheduleJob.getJobId()); log.info(">>>>> jobName = [" + scheduleJob.getJobName() + "]" + " created."); }
Если задание не существует – мы вызываем планировщик нового задания ()
, который планирует новое задание, используя наш автоматический Создатель расписания заданий
компонент из предыдущих:
private void scheduleNewJob(SchedulerJobInfo jobInfo) { try { Scheduler scheduler = schedulerFactoryBean.getScheduler(); JobDetail jobDetail = JobBuilder .newJob((Class extends QuartzJobBean>) Class.forName(jobInfo.getJobClass())) .withIdentity(jobInfo.getJobName(), jobInfo.getJobGroup()).build(); if (!scheduler.checkExists(jobDetail.getKey())) { jobDetail = scheduleCreator.createJob( (Class extends QuartzJobBean>) Class.forName(jobInfo.getJobClass()), false, context, jobInfo.getJobName(), jobInfo.getJobGroup()); Trigger trigger; if (jobInfo.getCronJob()) { trigger = scheduleCreator.createCronTrigger( jobInfo.getJobName(), new Date(), jobInfo.getCronExpression(), SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW); } else { trigger = scheduleCreator.createSimpleTrigger( jobInfo.getJobName(), new Date(), jobInfo.getRepeatTime(), SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW); } scheduler.scheduleJob(jobDetail, trigger); jobInfo.setJobStatus("SCHEDULED"); schedulerRepository.save(jobInfo); log.info(">>>>> jobName = [" + jobInfo.getJobName() + "]" + " scheduled."); } else { log.error("scheduleNewJobRequest.jobAlreadyExist"); } } catch (ClassNotFoundException e) { log.error("Class Not Found - {}", jobInfo.getJobClass(), e); } catch (SchedulerException e) { log.error(e.getMessage(), e); } }
При создании триггера мы передаем MISFIRE_INSTRUCTION
. Иногда Кварц может пропустить увольнение с определенной работы. Это может произойти, если рабочие потоки заняты, если планировщик не работает или если в прошлом планировалось выполнение задания, среди прочих подобных проблем.
Мы установили наши триггеры на MISFIRE_INSTRUCTION_FIRE_NOW
– который срабатывает снова, если происходит осечка. Если не определено MISFIRE_INSTRUCTION
, Quartz принимает Интеллектуальную политику – ИНСТРУКЦИЯ _ _MISFIRE _ _ УМНАЯ_ПОЛИТИКА
.
Редактирование задания Quartz
Для редактирования заданий мы можем использовать почти тот же метод, что и для их создания, однако мы должны сообщить Планировщику о переносе задания, как только его инструкции будут обновлены:
private void updateScheduleJob(SchedulerJobInfo jobInfo) { Trigger newTrigger; if (jobInfo.getCronJob()) { newTrigger = scheduleCreator.createCronTrigger( jobInfo.getJobName(), new Date(), jobInfo.getCronExpression(), simpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW); } else { newTrigger = scheduleCreator.createSimpleTrigger( jobInfo.getJobName(), new Date(), jobInfo.getRepeatTime(), SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW); } try { schedulerFactoryBean.getScheduler().rescheduleJob(TriggerKey.triggerKey(jobInfo.getJobName()), newTrigger); jobInfo.setJobStatus("EDITED & SCHEDULED"); schedulerRepository.save(jobInfo); log.info(">>>>> jobName = [" + jobInfo.getJobName() + "]" + " updated and scheduled."); } catch (SchedulerException e) { log.error(e.getMessage(), e); } }
Выполните задание Quartz Один раз
Иногда вам хотелось бы нажать на спусковой крючок в специальной ситуации. Вы также можете захотеть уволить работу, чтобы проверить, работает ли она нормально или нет, прежде чем придерживаться расписания.
Мы можем использовать метод trigger Job ()
, чтобы запустить его немедленно, не дожидаясь запланированного времени или времени. Это позволяет нам создать горячую клавишу тестирования:
public boolean startJobNow(SchedulerJobInfo jobInfo) { try { SchedulerJobInfo getJobInfo = schedulerRepository.findByJobName(jobInfo.getJobName()); getJobInfo.setJobStatus("SCHEDULED & STARTED"); schedulerRepository.save(getJobInfo); schedulerFactoryBean.getScheduler().triggerJob(new JobKey(jobInfo.getJobName(), jobInfo.getJobGroup())); log.info(">>>>> jobName = [" + jobInfo.getJobName() + "]" + " scheduled and started now."); return true; } catch (SchedulerException e) { log.error("Failed to start new job - {}", jobInfo.getJobName(), e); return false; } }
Приостановите работу с кварцем
Если вы хотите приостановить выполнение задания Cron или простого задания , мы можем использовать метод приостановить задание ()
, который приостановит задание до тех пор, пока вы его не возобновите:
public boolean pauseJob(SchedulerJobInfo jobInfo) { try { SchedulerJobInfo getJobInfo = schedulerRepository.findByJobName(jobInfo.getJobName()); getJobInfo.setJobStatus("PAUSED"); schedulerRepository.save(getJobInfo); schedulerFactoryBean.getScheduler().pauseJob(new JobKey(jobInfo.getJobName(), jobInfo.getJobGroup())); log.info(">>>>> jobName = [" + jobInfo.getJobName() + "]" + " paused."); return true; } catch (SchedulerException e) { log.error("Failed to pause job - {}", jobInfo.getJobName(), e); return false; } }
Возобновите работу с Кварцем
Естественно, мы можем возобновить приостановленную работу, просто используя метод resume Job()
:
public boolean resumeJob(SchedulerJobInfo jobInfo) { try { SchedulerJobInfo getJobInfo = schedulerRepository.findByJobName(jobInfo.getJobName()); getJobInfo.setJobStatus("RESUMED"); schedulerRepository.save(getJobInfo); schedulerFactoryBean.getScheduler().resumeJob(new JobKey(jobInfo.getJobName(), jobInfo.getJobGroup())); log.info(">>>>> jobName = [" + jobInfo.getJobName() + "]" + " resumed."); return true; } catch (SchedulerException e) { log.error("Failed to resume job - {}", jobInfo.getJobName(), e); return false; } }
Удаление задания Quartz
Наконец, мы можем удалить задание, вызвав метод delete Job()
:
public boolean deleteJob(SchedulerJobInfo jobInfo) { try { SchedulerJobInfo getJobInfo = schedulerRepository.findByJobName(jobInfo.getJobName()); schedulerRepository.delete(getJobInfo); log.info(">>>>> jobName = [" + jobInfo.getJobName() + "]" + " deleted."); return schedulerFactoryBean.getScheduler().deleteJob(new JobKey(jobInfo.getJobName(), jobInfo.getJobGroup())); } catch (SchedulerException e) { log.error("Failed to delete job - {}", jobInfo.getJobName(), e); return false; } }
Пользовательский интерфейс консоли управления Кварцем
Теперь у нас есть все функциональные возможности, необходимые для объединения нашей Консоли управления Quartz с пользовательским интерфейсом веб-приложения, где мы можем протестировать функции.
Примечание: Пользовательский интерфейс этого приложения предназначен для демонстрации управления жизненным циклом планировщика, а пользовательские интерфейсы гораздо более изменчивы, чем серверная часть. Из-за этого мы не будем уделять много внимания его реализации. Тем не менее, вы можете получить доступ к полному коду интерфейса в нашем репозитории GitHub .
Любой REST API, который запускает методы, которые мы определили ранее, будет работать просто отлично. Наша реализация использует Thymeleaf в качестве механизма рендеринга.
Если вы хотите узнать больше о Thymeleaf, прочитайте “Начало работы с Thymeleaf на Java и Spring”.
Если вы хотите узнать больше о создании REST API, прочитайте наше руководство по созданию REST API с помощью Spring Boot .
Как только вы запустите свое приложение, давайте перейдем к http://localhost:8080/index , чтобы увидеть панель мониторинга.
Во-первых, давайте выберем кнопку Создать , чтобы создать новое задание. Он откроет всплывающее окно и предложит нам заполнить данные о задании.
Давайте создадим задание Cron и Простое задание:
Мы можем видеть все добавленные вакансии в Магазине вакансий:
Вы также можете просматривать журналы заданий – когда задания запускаются одно за другим в соответствии с их критериями запуска.
Вывод
В этом руководстве мы познакомились с Quartz – мощным планировщиком и внедрили его в приложение Spring Boot.
Мы рассмотрели общее управление жизненным циклом планировщика Quartz с демонстрацией в упрощенном пользовательском интерфейсе. Мы использовали некоторые минималистичные задания, но вы можете попробовать определить сложные задания, такие как оповещения о пожаре по электронной почте или асинхронная обработка сообщений и т. Д., И запланировать их с помощью Quartz.
Как всегда, вы можете найти полный исходный код на GitHub .