Обратите внимание на публичный аккаунт WeChat:CodingTechWork, учиться и прогрессировать вместе.
введение
Как правило, мы сначала подумаем об использовании задач на время.@ScheduledАннотируйте, чтобы установить запланированное время для запланированного выполнения задачи. Когда слишком много запланированных задач или когда есть необходимость добавить, удалить, изменить и проверить,@ScheduledАннотации не будут соответствовать нашим потребностям. В этой статье мы учимся вместе и подводим итогиQuartz定时框架использование.
О кварце
Обзор
Quartz is a richly featured, open source job scheduling library that can be integrated within virtually any Java application - from the smallest stand-alone application to the largest e-commerce system. Quartz can be used to create simple or complex schedules for executing tens, hundreds, or even tens-of-thousands of jobs; jobs whose tasks are defined as standard Java components that may execute virtually anything you may program them to do. The Quartz Scheduler includes many enterprise-class features, such as support for JTA transactions and clustering. Quartz is freely usable, licensed under the Apache 2.0 license.
Quartz — это проект с открытым исходным кодом OpenSymphony, платформы планирования заданий с открытым исходным кодом, написанной на Java.
Функции
- Поддержка распределенной высокой доступности, нам нужен Quartz для реализации запланированной задачи, когда только один узел может выполняться в нескольких узлах, иначе все узлы будут выполняться один раз с помощью @Scheduled и других методов.
- Упорство, Quartz имеет специальную таблицу данных для обеспечения постоянства задач, рассчитанных по времени.
- Поддержка многозадачного планирования и управления, Quartz может хранить несколько запланированных задач в базе данных для планирования заданий и может осуществлять управление добавлением, удалением, изменением и проверкой запланированных задач.
сочинение
Кварц состоит из трех частей:
- Задача: JobDetail
- Триггер: Триггер (делится на SimpleTrigger и CronTrigger)
- Планировщик: Планировщик
JobDetail
JobDetail в основном состоит из JobKey (имя задания и группа группы), JobClass, JobDataMap (данные, связанные с задачей) и JobBuilder. Обычно используются первые несколько.
Исходный код JobDetail
package org.quartz;
import java.io.Serializable;
public interface JobDetail extends Serializable, Cloneable {
JobKey getKey();
String getDescription();
Class<? extends Job> getJobClass();
JobDataMap getJobDataMap();
boolean isDurable();
boolean isPersistJobDataAfterExecution();
boolean isConcurrentExectionDisallowed();
boolean requestsRecovery();
Object clone();
JobBuilder getJobBuilder();
}
Пример труда
Map<String,String> jobData = new HashMap<>();
String jobName = "schedulerJob";
String jobGroup = "schedulerGroup";
jobData.put("key00", "value00");
JobDetail jobDetail = JobBuilder.newJob(SchedulerJob.class)
.withIdentity(jobName, jobGroup)
.usingJobData("key01", "value01")
.usingJobData(jobData)
.storeDurably()
.build();
Trigger
Trigger определяет классы запуска и выполнения заданий, в основном включая SimpleTrigger и CronTrigger. Триггер состоит из следующих частей:
- TriggerKey (название задания и группа группы)
- JobDataMap (данные, связанные с триггером, такие же, как JobDataMap в JobDetail, хранят один и тот же ключ, если значение отличается, оно перезапишет первое.)
- ScheduleBuilder (есть CronScheduleBuilder, SimpleScheduleBuilder, CalendarIntervalScheduleBuilder, DailyTimeIntervalScheduleBuilder, обычно используемые первые 2 типа.)
Пример триггера
//SimpleScheduleBuilder
String triggerName = "schedulerJob";
String triggerGroup = "schedulerGroup";
Trigger trigger = TriggerBuilder
.newTrigger()
.withIdentity(triggerName, triggerGroup)
.withSchedule(SimpleScheduleBuilder)
.repeatSecondlyForever(1)
.withIntervalInSeconds(0)
.withRepeatCount(0))
.startNow()
.build();
//CronScheduleBuilder
String triggerName2 = "schedulerJob2";
String triggerGroup2 = "schedulerGroup2";
String jobTime = "0 0 * * * ?";
Trigger trigger2 = TriggerBuilder
.newTrigger()
.withIdentity(triggerName2, triggerGroup2)
.startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND))
.withSchedule(CronScheduleBuilder.cronSchedule(jobTime))
.startNow()
.build();
Scheduler
Планировщик должен считывать триггер Trigger для запуска запланированной задачи JobDetail. Планировщики могут быть созданы через SchedulerFactory, которые разделены наStdSchedulerFactory(常用)和DirectSchedulerFactoryдва вида.
- StdSchedulerFactory создает и инициализирует планировщик с набором свойств (положенных в файле конфигурации), затем передает
getScheduler()способ создания планировщика. - DirectSchedulerFactory обычно не используется и легко программируется.
Пример планировщика
//建好jobDetail,trigger
... ...
//StdSchedulerFactory方式,用的多
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler schedulerStd = schedulerFactory.getScheduler();
//DirectSchedulerFactory方式
DirectSchedulerFactory directSchedulerFactory = DirectSchedulerFactory.getInstance();
Scheduler schedulerDir=directSchedulerFactory.getScheduler();
//执行调度
schedulerStd.scheduleJob(jobDetail, trigger);
schedulerStd.start();
Cron-выражения
Задачи времени неразделимы от экспрессии CRON, чтобы установить конкретное время выполнения или цикл выполнения. Выражение Cron - это строка, и в целом есть два выражения:
秒 分 小时 日 月 星期 年秒 分 小时 日 月 星期
Среди них год является необязательным, поэтому общая экспрессия составляет 6-7 полей, каждое поле разделено пространством. В дополнение к английскому аббревиатуру, неделя также может быть числом1-7数字выражать, отметить1Значит это星期日,7указано星期六.
-
*: звездочка, обозначающая временной интервал, соответствующий каждому полю.每一个, например, в день, значит каждый день. -
?: вопросительный знак, может использоваться только в полях даты и недели, указывая无意义的值, что эквивалентно символу точки. -
-: знак минус, указывающий диапазон, используемый в минутах5-8, это значит5-8分钟, т.е. 5, 6, 7, 8 минут. -
,: запятая, представляющая значение списка, используемое на неделе понедельника и среды.MON,WED, которые также могут быть представлены в виде чисел:1,3. -
/: косая черта, использованиеx/yдля представления последовательности равных шагов, x представляет собой начальное значение, а y представляет значение шага. как используется в поле секунд0/15, указывающее, что он начинается с 0 секунд и увеличивается каждые 15 секунд, то есть 0 секунд, 15 секунд, 30 секунд и 45 секунд.Это можно понимать как每15秒выполнять задания. -
L: Может использоваться только в полях даты и недели, указывающие наLast.在日期中,LУказывает на последний день месяца, например, 31 января; в середине недели,LПредставляет субботу (или число 7). -
W: его можно использовать только в поле даты, указывая рабочий период, ближайший к дате, и не может охватывать месяцы. как10W, указывающий рабочий день, ближайший к 10-му числу месяца, если 10-е число — суббота, оно соответствует пятнице 9-го числа; если 10-е число — воскресенье, оно соответствует понедельнику 11-го числа; если 10-е число — понедельник, оно соответствует понедельнику 10-го числа.LWКомбинация представляет собой последний рабочий день месяца. -
C: может использоваться только в полях даты и недели, указываяCalendar, Дата связанной программы, если дата не связана, это эквивалентна всей связанной дате. Как используется в дату4C, обозначающий первый день после 4-го числа; использовать в течение недели1C, который представляет первый день после воскресенья. -
#: Знак фунта можно использовать только в поле дня недели, указывая на определенный день недели месяца. как6#2представляет вторую пятницу месяца (где,6значит пятница,#3Это представляет второй месяц).
CRON-пример
| Cron-выражения | инструкция |
|---|---|
| 0 0 * * * ? | Работает каждый час в 0 минут и 0 секунд |
| 0 0 1 * * ? | Выполнять каждый день в 01:00:00 |
| 0 0 1 * * ? * | Выполнять каждый день в 01:00:00, как указано выше. |
| 0 0 1 * * ? 2021 | Он будет работать в 01:00 часов каждый день в 2021 году |
| 0 * 10 * * ? | Ходит каждую минуту с 10:00 до 11:00 каждый день, начиная с 10:00:00 и заканчивая в 10:59:00. |
| 0 0/5 10 * * ? | Ходит каждые 5 минут с 10:00 до 11:00 каждый день, начиная с 10:00:00 и заканчивая в 10:59:00. |
| 0 0/5 10,15 * * ? | Он курсирует каждые 5 минут с 10:00 до 11:00 каждый день и каждые 5 минут с 15:00 до 16:00 каждый день. |
| 0 0-10 10 * * ? | Ходит каждую минуту с 10:00 до 10:10 каждый день |
| 0 10 1 ? * MON-FRI | Каждый понедельник, вторник, среду, четверг, пятницу в 1:10 |
| 0 10 1 1 * ? | Выходит в 1:10 1-го числа каждого месяца |
| 0 10 1 L * ? | Последний день каждого месяца для запуска суб 1:10 |
| 0 10 1 ? * 6L | Выходит в 1:10 в последнюю пятницу каждого месяца |
| 0 10 1 ? * 6#3 | Выходит в 1:10 в 3-ю пятницу каждого месяца. |
Кварцевый CRUD-шаблон
Класс интерфейса QuartzService
package com.andya.selfcode.quartzservice;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.util.List;
import java.util.Map;
/**
* @author Andya
* @date 2021/4/01
*/
public interface QuartzService {
/**
* 增加一个任务job
* @param jobClass 任务job实现类
* @param jobName 任务job名称(保证唯一性)
* @param jobGroupName 任务job组名
* @param jobTime 任务时间间隔(秒)
* @param jobTimes 任务运行次数(若<0,则不限次数)
* @param jobData 任务参数
*/
void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, int jobTime,
int jobTimes, Map jobData);
/**
* 增加一个任务job
* @param jobClass 任务job实现类
* @param jobName 任务job名称(保证唯一性)
* @param jobGroupName 任务job组名
* @param jobTime 任务时间表达式
* @param jobData 任务参数
*/
void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, String jobTime, Map jobData);
/**
* 修改一个任务job
* @param jobName 任务名称
* @param jobGroupName 任务组名
* @param jobTime cron时间表达式
*/
void updateJob(String jobName, String jobGroupName, String jobTime);
/**
* 删除一个任务job
* @param jobName
* @param jobGroupName
*/
void deleteJob(String jobName, String jobGroupName);
/**
* 暂停一个任务job
* @param jobName
* @param jobGroupName
*/
void pauseJob(String jobName, String jobGroupName);
/**
* 恢复一个任务job
* @param jobName
* @param jobGroupName
*/
void resumeJob(String jobName, String jobGroupName);
/**
* 立即执行一个任务job
* @param jobName
* @param jobGroupName
*/
void runAJobNow(String jobName, String jobGroupName);
/**
* 获取所有任务job
* @return
*/
List<Map<String, Object>> queryAllJob();
/**
* 获取正在运行的任务job
* @return
*/
List<Map<String, Object>> queryRunJob();
}
Класс реализации QuartzServiceImpl
package com.andya.selfcode.quartz.service;
import com.andya.selfcode.quartz.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.DateBuilder.IntervalUnit;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.*;
/**
* @author Andya
* @date 2021/4/01
*/
@Slf4j
@Service
public class QuartzServiceImpl implements QuartzService {
@Autowired
private Scheduler scheduler;
@PostConstruct
public void startScheduler() {
try {
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* 增加一个job
*
* @param jobClass
* 任务实现类
* @param jobName
* 任务名称
* @param jobGroupName
* 任务组名
* @param jobTime
* 时间表达式 (这是每隔多少秒为一次任务)
* @param jobTimes
* 运行的次数 (<0:表示不限次数)
* @param jobData
* 参数
*/
@Override
public void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, int jobTime,
int jobTimes, Map jobData) {
try {
// 任务名称和组构成任务key
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName)
.build();
// 设置job参数
if(jobData!= null && jobData.size()>0){
jobDetail.getJobDataMap().putAll(jobData);
}
// 使用simpleTrigger规则
Trigger trigger = null;
if (jobTimes < 0) {
trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1).withIntervalInSeconds(jobTime))
.startNow().build();
} else {
trigger = TriggerBuilder
.newTrigger().withIdentity(jobName, jobGroupName).withSchedule(SimpleScheduleBuilder
.repeatSecondlyForever(1).withIntervalInSeconds(jobTime).withRepeatCount(jobTimes))
.startNow().build();
}
log.info("jobDataMap: {}", jobDetail.getJobDataMap().getWrappedMap());
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
e.printStackTrace();
throw new BaseException("add job error!");
}
}
/**
* 增加一个job
*
* @param jobClass
* 任务实现类
* @param jobName
* 任务名称(建议唯一)
* @param jobGroupName
* 任务组名
* @param jobTime
* 时间表达式 (如:0/5 * * * * ? )
* @param jobData
* 参数
*/
@Override
public void addJob(Class<? extends QuartzJobBean> jobClass, String jobName, String jobGroupName, String jobTime, Map jobData) {
try {
// 创建jobDetail实例,绑定Job实现类
// 指明job的名称,所在组的名称,以及绑定job类
// 任务名称和组构成任务key
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName)
.build();
// 设置job参数
if(jobData!= null && jobData.size()>0){
jobDetail.getJobDataMap().putAll(jobData);
}
// 定义调度触发规则
// 使用cornTrigger规则
// 触发器key
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
.startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND))
.withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).startNow().build();
// 把作业和触发器注册到任务调度中
scheduler.scheduleJob(jobDetail, trigger);
log.info("jobDataMap: {}", jobDetail.getJobDataMap());
} catch (Exception e) {
e.printStackTrace();
throw new BaseException("add job error!");
}
}
/**
* 修改 一个job的 时间表达式
*
* @param jobName
* @param jobGroupName
* @param jobTime
*/
@Override
public void updateJob(String jobName, String jobGroupName, String jobTime) {
try {
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
log.info("new jobTime: {}", jobTime);
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
.withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).build();
// 重启触发器
scheduler.rescheduleJob(triggerKey, trigger);
} catch (SchedulerException e) {
e.printStackTrace();
throw new BaseException("update job error!");
}
}
/**
* 删除任务一个job
*
* @param jobName
* 任务名称
* @param jobGroupName
* 任务组名
*/
@Override
public void deleteJob(String jobName, String jobGroupName) {
try {
scheduler.deleteJob(new JobKey(jobName, jobGroupName));
} catch (Exception e) {
e.printStackTrace();
throw new BaseException("delete job error!");
}
}
/**
* 暂停一个job
*
* @param jobName
* @param jobGroupName
*/
@Override
public void pauseJob(String jobName, String jobGroupName) {
try {
JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
scheduler.pauseJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
throw new BaseException("pause job error!");
}
}
/**
* 恢复一个job
*
* @param jobName
* @param jobGroupName
*/
@Override
public void resumeJob(String jobName, String jobGroupName) {
try {
JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
scheduler.resumeJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
throw new BaseException("resume job error!");
}
}
/**
* 立即执行一个job
*
* @param jobName
* @param jobGroupName
*/
@Override
public void runAJobNow(String jobName, String jobGroupName) {
try {
JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
scheduler.triggerJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
throw new BaseException("run a job error!");
}
}
/**
* 获取所有计划中的任务列表
*
* @return
*/
@Override
public List<Map<String, Object>> queryAllJob() {
List<Map<String, Object>> jobList = null;
try {
GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
jobList = new ArrayList<Map<String, Object>>();
for (JobKey jobKey : jobKeys) {
log.info("maps: {}", scheduler.getJobDetail(jobKey).getJobDataMap().getWrappedMap());
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
for (Trigger trigger : triggers) {
Map<String, Object> map = new HashMap<>();
map.put("jobName", jobKey.getName());
map.put("jobGroupName", jobKey.getGroup());
map.put("description", "触发器:" + trigger.getKey());
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
map.put("jobStatus", triggerState.name());
if (trigger instanceof CronTrigger) {
CronTrigger cronTrigger = (CronTrigger) trigger;
String cronExpression = cronTrigger.getCronExpression();
map.put("jobTime", cronExpression);
}
jobList.add(map);
}
}
} catch (SchedulerException e) {
e.printStackTrace();
throw new BaseException("query all jobs error!");
}
return jobList;
}
/**
* 获取所有正在运行的job
*
* @return
*/
@Override
public List<Map<String, Object>> queryRunJob() {
List<Map<String, Object>> jobList = null;
try {
List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
jobList = new ArrayList<Map<String, Object>>(executingJobs.size());
for (JobExecutionContext executingJob : executingJobs) {
Map<String, Object> map = new HashMap<String, Object>();
JobDetail jobDetail = executingJob.getJobDetail();
JobKey jobKey = jobDetail.getKey();
Trigger trigger = executingJob.getTrigger();
map.put("jobName", jobKey.getName());
map.put("jobGroupName", jobKey.getGroup());
map.put("description", "触发器:" + trigger.getKey());
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
map.put("jobStatus", triggerState.name());
if (trigger instanceof CronTrigger) {
CronTrigger cronTrigger = (CronTrigger) trigger;
String cronExpression = cronTrigger.getCronExpression();
map.put("jobTime", cronExpression);
}
jobList.add(map);
}
} catch (SchedulerException e) {
e.printStackTrace();
throw new BaseException("query run jobs error!");
}
return jobList;
}
}
Как использовать кварц
Вызывается автоматически при запуске приложения
Напишите класс конфигурации, используйте@Bean注解Выполните создание экземпляра конфигурации.
Класс конфигурации QuartzConfig
package com.andya.selfcode.quartz;
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;
/**
* @author Andya
* @create 2021/04/01
*/
@Configuration
@Service
public class QuartzConfig {
@Bean
public JobDetail scheduleJobDetail() {
System.out.println("**************************************** scheduler job begin");
JobDetail jobDetail = JobBuilder.newJob(SchedulerJob.class)
.withIdentity("schedulerJob")
.storeDurably()
.build();
System.out.println("**************************************** scheduler job end");
return jobDetail;
}
@Bean
public Trigger scheduleJobDetailTrigger() {
Trigger trigger = TriggerBuilder
.newTrigger()
.forJob(scheduleJobDetail())
.withIdentity("schedulerJob")
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withRepeatCount(0))
.startNow()
.build();
System.out.println("schedulerJob trigger end");
return trigger;
}
Добавление и удаление класса задач SchedulerJob
package com.andya.selfcode.quartz;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.quartz.QuartzJobBean;
/**
* @author Andya
* @create 2021/04/01
*/
@Slf4j
public class SchedulerJob extends QuartzJobBean {
@Autowired
QuartzService quartzService;
@Value("${schedule.cron.withJob1}")
private String cronTimeJob1;
public String getCronTimeJob1() {
return cronTimeJob1;
}
@Value("${schedule.cron.withJob2}")
private String cronTimeJob2;
public String getCronTimeJob1() {
return cronTimeJob2;
}
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
try{
//job1先删后增
log.info("job1: delete scheduleWithJob1");
quartzService.deleteJob("scheduleWithJob1", "scheduleWithJob1_Group1");
log.info("job1: add scheduleWithJob1");
quartzService.addJob(ScheduleWithJob1.class, "scheduleWithJob1",
"scheduleWithJob1_Group1", cronTimeJob1, null);
//按小时定时的job先删后增
log.info("job2: delete scheduleWithJob2");
quartzService.deleteJob("scheduleWithJob2", "scheduleWithJob2_Group2");
log.info("job2: add scheduleWithJob2");
quartzService.addJob(ScheduleWithJob2.class, "scheduleWithJob2",
"scheduleWithJob2_Group2", cronTimeJob2, null);
} catch (Exception e) {
log.error("quartz service scheduler job failed!");
e.printStackTrace();
}
}
}
Конкретный класс задач Job
Класс ScheduleWithJob1
package com.andya.selfcode.quartz;
import com.andya.selfcode.service.ScheduleJobService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.time.LocalDateTime;
/**
* @author Andya
* @create 2021/04/01
*/
@Slf4j
public class ScheduleWithJob1 extends QuartzJobBean {
@Autowired
ScheduleJobService scheduleJobService;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException{
System.out.println("start schedule job1: " + LocalDateTime.now());
try {
scheduleJobService.scheduleWithJob1();
} catch (Exception e) {
e.printStackTrace();
}
}
}
CHECLELEWITHJOB2 класс
package com.andya.selfcode.quartz;
import com.andya.selfcode.service.ScheduleJobService;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.time.LocalDateTime;
/**
* @author Andya
* @create 2021/04/01
*/
public class ScheduleWithJob2 extends QuartzJobBean {
@Autowired
ScheduleJobService scheduleJobService;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
try {
System.out.println("start schedule with job2: " + LocalDateTime.now());
scheduleJobService.scheduleJob2();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Класс интерфейса ScheduleJobService
package com.andya.selfcode.service;
/**
* @author Andya
* @create 2021/04/01
*/
public interface ScheduleJobService {
/**
* job1定时任务
* @throws Exception
*/
void scheduleJob1() throws Exception;
/**
* job2定时任务
* @throws Exception
*/
void scheduleJob2() throws Exception;
}
Вызов интерфейса HTTP
Напишите уровень контроллера для прямого вызова класса интерфейса QuartzService.
package com.andya.selfcode.quartz.controller;
import com.andya.selfcode.quartz.bean.UpdateJobBean;
import com.andya.selfcode.quartz.bean.JobXXXBean;
import com.andya.selfcode.quartz.exception.BadRequestException;
import com.andya.selfcode.quartz.service.QuartzService;
import com.andya.selfcode.quartz.service.jobs.Job1;
import io.swagger.annotations.*;
import org.quartz.JobDataMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* @author Andya
* @create 2021/04/01
*/
@RestController
@Api(value = "quartz增删改查相关API")
@RequestMapping(value = "/quartz")
public class YarnFlexibleCapacityExpansionController {
@Autowired
QuartzService quartzService;
@ApiOperation(value = "使用quartz添加job")
@RequestMapping(value = "/addJob/{jobUUID}", method = RequestMethod.POST)
public void addQuartzJob(
@ApiParam(name = "jobUUID") @PathVariable("jobUUID") String jobUUID,
@ApiParam(name = "JobXXXBean") @RequestBody JobXXXBean jobXXXBean) {
if (jobXXXBean.getOpenBean() != null) {
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("key01", jobXXXBean.getKey01());
jobDataMap.put("key02", jobXXXBean.getKey02());
jobDataMap.put("key03", jobXXXBean.getKey03());
jobDataMap.put("jobTimeCron", jobXXXBean.getJobTimeCron());
jobDataMap.put("key04", jobXXXBean.getKey04());
quartzService.addJob(Job1.class,
jobUUID,
jobUUID,
jobXXXBean.getJobTimeCron(),
jobDataMap);
} else {
throw new BadRequestException("参数错误");
}
}
@ApiOperation(value = "使用quartz查询所有job")
@RequestMapping(value = "/queryAllJob", method = RequestMethod.GET)
public List<Map<String, Object>> queryAllQuartzJob() {
List<Map<String, Object>> list = quartzService.queryAllJob();
return list;
}
@ApiOperation(value = "使用quartz查询所有运行job")
@RequestMapping(value = "/queryRunJob", method = RequestMethod.GET)
public List<Map<String, Object>> queryRunQuartzJob() {
List<Map<String, Object>> list = quartzService.queryRunJob();
return list;
}
@ApiOperation(value = "使用quartz删除job")
@RequestMapping(value = "/deleteJob/{jobUUID}", method = RequestMethod.DELETE)
public void deleteJob(
@ApiParam(name = "jobUUID") @PathVariable("jobUUID") String jobUUID) {
quartzService.deleteJob(jobUUID, jobUUID);
}
@ApiOperation(value = "使用quartz修改job的cron时间")
@RequestMapping(value = "/updateJob/{jobUUID}", method = RequestMethod.PUT)
public void deleteJob(
@ApiParam(name = "jobUUID") @PathVariable("jobUUID") String jobUUID,
@ApiParam(name = "jobCronTime") @RequestBody UpdateJobBean updateJobBean) {
quartzService.updateJob(jobUUID, jobUUID, updateJobBean.getJobCronTime());
}
}
/**
* @author Andya
* @create 2021/04/01
*/
@ApiModel(value = "更新job cron时间参数")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class UpdateJobBean {
@ApiModelProperty(value = "jobTime的cron表达式", example = "0 0 1 * * ?")
String jobCronTime;
public String getJobCronTime() {
return jobCronTime;
}
public void setJobCronTime(String jobCronTime) {
this.jobCronTime = jobCronTime;
}
}
Скрипт таблицы данных кварца
Сценарий SQL для кварца для инициализации таблицы данных выглядит следующим образом.
-- 1.1. qrtz_blob_triggers : 以Blob 类型存储的触发器。
-- 1.2. qrtz_calendars:存放日历信息, quartz可配置一个日历来指定一个时间范围。
-- 1.3. qrtz_cron_triggers:存放cron类型的触发器。
-- 1.4. qrtz_fired_triggers:存放已触发的触发器。
-- 1.5. qrtz_job_details:存放一个jobDetail信息。
-- 1.6. qrtz_job_listeners:job监听器。
-- 1.7. qrtz_locks: 存储程序的悲观锁的信息(假如使用了悲观锁)。
-- 1.8. qrtz_paused_trigger_graps:存放暂停掉的触发器。
-- 1.9. qrtz_scheduler_state:调度器状态。
-- 1.10. qrtz_simple_triggers:简单触发器的信息。
-- 1.11. qrtz_trigger_listeners:触发器监听器。
-- 1.12. qrtz_triggers:触发器的基本信息。
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS;
CREATE TABLE QRTZ_JOB_DETAILS(
SCHED_NAME VARCHAR(120) NOT NULL,
JOB_NAME VARCHAR(190) NOT NULL,
JOB_GROUP VARCHAR(190) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
JOB_CLASS_NAME VARCHAR(250) NOT NULL,
IS_DURABLE VARCHAR(1) NOT NULL,
IS_NONCONCURRENT VARCHAR(1) NOT NULL,
IS_UPDATE_DATA VARCHAR(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
JOB_NAME VARCHAR(190) NOT NULL,
JOB_GROUP VARCHAR(190) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
NEXT_FIRE_TIME BIGINT(13) NULL,
PREV_FIRE_TIME BIGINT(13) NULL,
PRIORITY INTEGER NULL,
TRIGGER_STATE VARCHAR(16) NOT NULL,
TRIGGER_TYPE VARCHAR(8) NOT NULL,
START_TIME BIGINT(13) NOT NULL,
END_TIME BIGINT(13) NULL,
CALENDAR_NAME VARCHAR(190) NULL,
MISFIRE_INSTR SMALLINT(2) NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
REPEAT_COUNT BIGINT(7) NOT NULL,
REPEAT_INTERVAL BIGINT(12) NOT NULL,
TIMES_TRIGGERED BIGINT(10) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_CRON_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
CRON_EXPRESSION VARCHAR(120) NOT NULL,
TIME_ZONE_ID VARCHAR(80),
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_SIMPROP_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
STR_PROP_1 VARCHAR(512) NULL,
STR_PROP_2 VARCHAR(512) NULL,
STR_PROP_3 VARCHAR(512) NULL,
INT_PROP_1 INT NULL,
INT_PROP_2 INT NULL,
LONG_PROP_1 BIGINT NULL,
LONG_PROP_2 BIGINT NULL,
DEC_PROP_1 NUMERIC(13,4) NULL,
DEC_PROP_2 NUMERIC(13,4) NULL,
BOOL_PROP_1 VARCHAR(1) NULL,
BOOL_PROP_2 VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_BLOB_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
BLOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_CALENDARS (
SCHED_NAME VARCHAR(120) NOT NULL,
CALENDAR_NAME VARCHAR(190) NOT NULL,
CALENDAR BLOB NOT NULL,
PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
ENGINE=InnoDB;
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_FIRED_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
ENTRY_ID VARCHAR(95) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
INSTANCE_NAME VARCHAR(190) NOT NULL,
FIRED_TIME BIGINT(13) NOT NULL,
SCHED_TIME BIGINT(13) NOT NULL,
PRIORITY INTEGER NOT NULL,
STATE VARCHAR(16) NOT NULL,
JOB_NAME VARCHAR(190) NULL,
JOB_GROUP VARCHAR(190) NULL,
IS_NONCONCURRENT VARCHAR(1) NULL,
REQUESTS_RECOVERY VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,ENTRY_ID))
ENGINE=InnoDB;
CREATE TABLE QRTZ_SCHEDULER_STATE (
SCHED_NAME VARCHAR(120) NOT NULL,
INSTANCE_NAME VARCHAR(190) NOT NULL,
LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
CHECKIN_INTERVAL BIGINT(13) NOT NULL,
PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
ENGINE=InnoDB;
CREATE TABLE QRTZ_LOCKS (
SCHED_NAME VARCHAR(120) NOT NULL,
LOCK_NAME VARCHAR(40) NOT NULL,
PRIMARY KEY (SCHED_NAME,LOCK_NAME))
ENGINE=InnoDB;
CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
commit;
refer by
www.quartz-scheduler.org/