Автор оригинала: 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 .