看了一些网上的文章,都不太合我意,集众家之长,来个自己的版本。原理和介绍就不搬来搬去了,直接上代码吧。
目录
一.POM文件
二.application-quartz.properties
三.java文件
3.1 Application
3.2 QuartzSchedulerConfig配置一下,类名自己随便改
3.3 StartApplicationListener应用启动时调用一下QuartzTasks添加定时任务
3.4 QuartzTasks用来启动时添加或更新所有定时任务,类名自己随便改
3.5 Job1用来实现具体的任务逻辑,类名自己随便改,每个任务创建一个类
3.6 IXXXService的接口和Service实现类这里不做记载了,直接按自己的业务逻辑来
四.创建quartz的表
org.springframework.boot
spring-boot-starter-quartz
这里只记载了quartz的依赖,其他部分根据自己需要去弄吧。因为我的spring-boot-starter-parent采用的版本是2.3.3.RELEASE,所以对应的spring-boot-starter-quartz的版本也是2.3.3.RELEASE,quartz的版本是2.3.2
################ quartz集群配置
# 设置quartz任务的数据持久化方式,默认是内存方式,配置JDBC以使用数据库方式持久化任务
spring.quartz.job-store-type=jdbc
# 调度标识名 集群中每一个实例都必须使用相同的名称
spring.quartz.properties.org.quartz.scheduler.instanceName=ComplianceAuditQuartzScheduler
# ID设置为自动获取 每一个必须不同
spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO
spring.quartz.properties.org.quartz.scheduler.makeSchedulerThreadDaemon=true
# 线程池的实现类(一般使用SimpleThreadPool即可满足需求)
spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
# 指定在线程池里面创建的线程是否是守护线程
spring.quartz.properties.org.quartz.threadPool.makeThreadsDaemons=true
# 指定线程数,至少为1(无默认值)
spring.quartz.properties.org.quartz.threadPool.threadCount:10
# 设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1,默认为5)
spring.quartz.properties.org.quartz.threadPool.threadPriority:5
# 自创建父线程
spring.quartz.properties.org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true
# 数据保存方式为数据库持久化
spring.quartz.properties.org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
# 数据库代理类,一般org.quartz.impl.jdbcjobstore.StdJDBCDelegate可以满足大部分数据库
spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# 表的前缀,默认QRTZ_
spring.quartz.properties.org.quartz.jobStore.tablePrefix=QRTZ_
# 是否加入集群
spring.quartz.properties.org.quartz.jobStore.isClustered=true
# 检入到数据库中的频率(单位毫秒)。clusterChedkinInterval越小,Scheduler节点检查失败的 Scheduler实例就越频繁。默认值是 15000(即15秒)。
spring.quartz.properties.org.quartz.jobStore.clusterCheckinInterval=20000
# 设置调度引擎对触发器超时的忍耐时间 (单位毫秒)
spring.quartz.properties.org.quartz.jobStore.misfireThreshold=60000
我这里是单独放了个配置文件,也可以直接写在application.properties里。单独配置文件的时候,别忘了在application.properties里的spring.profiles.active里添加一下引用。我这里的引用是:"spring.profiles.active=jdbc,reids,log,system,quartz" 。如果没有这个配置文件,quartz默认启动为单机版。
在入口Application类上加上 @EnableScheduling的注解
package com.study.quartz.config;
import org.springframework.boot.autoconfigure.quartz.SchedulerFactoryBeanCustomizer;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
@Configuration
public class QuartzSchedulerConfig implements SchedulerFactoryBeanCustomizer {
@Override
public void customize(SchedulerFactoryBean schedulerFactoryBean) {
// 延时10s启动定时任务,避免系统未完全启动却开始执行定时任务的情况
schedulerFactoryBean.setStartupDelay(10);
// 自动启动
schedulerFactoryBean.setAutoStartup(true);
// 覆盖已存在的任务,用于Quartz集群,QuartzScheduler启动会更新已存在的Job
schedulerFactoryBean.setOverwriteExistingJobs(true);
}
}
package com.study.quartz.config;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import com.study.quartz.task.QuartzTasks;
@Configuration
public class StartApplicationListener implements ApplicationListener {
private static final Logger logger = LoggerFactory.getLogger(StartApplicationListener.class);
@Autowired
private QuartzTasks quartzTasks;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// 防止重复执行
if (event.getApplicationContext().getParent() == null) {
// 添加quartz定时任务
logger.info("开始-添加quartz定时任务");
try {
quartzTasks.addQuartzJobs();
} catch (SchedulerException e) {
logger.error("添加quartz定时任务失败", e);
}
logger.info("结束-添加quartz定时任务");
// 删除旧的不要的quartz定时任务
logger.info("开始-删除旧的不要的quartz定时任务");
try {
quartzTasks.deleteQuartzJobs();
} catch (SchedulerException e) {
logger.error("删除旧的不要的quartz定时任务失败", e);
}
logger.info("结束-删除旧的不要的quartz定时任务");
}
}
}
application-system.properties里配置一下任务定时的cron,我这里定义了"cronJob1=0 */2 * * * ?",每两分钟执行一次。
package com.study.quartz.task;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Component
@PropertySource("classpath:application-system.properties")
public class QuartzTasks {
/**
* 注入任务调度器
*/
@Autowired
private Scheduler scheduler;
/**
* 默认时区
*/
private static final TimeZone defaultTimeZone = TimeZone.getTimeZone("Asia/Shanghai");
/**
* 任务分组
*/
private static final String GROUP_A = "GroupA";
@Value("${cronJob1}")
private String cronJob1;
/**
* 添加定时任务
*
* @throws SchedulerException
*/
public void addQuartzJobs() throws SchedulerException {
// 添加定时任务:Job1
addJob(scheduler, Job1.class, GROUP_A , "Job1", cronJob1);
// 下面可以添加其他定时任务
//
}
/**
* 删除旧的不要的定时任务
*
* @param scheduler Quartz调度器
* @throws SchedulerException
*/
public void deleteQuartzJobs() throws SchedulerException {
// 删除旧的不要的定时任务
// deleteJob(scheduler, groupName, jobName);
}
/**
* 添加定时任务
*
* @param scheduler Quartz调度器
* @param jobClass 任务类
* @param groupName 任务分组
* @param jobName 任务名
* @param jobCron 任务定时cron
* @throws SchedulerException
*/
private void addJob(Scheduler scheduler, Class extends Job> jobClass, String groupName, String jobName,
String jobCron) throws SchedulerException {
JobDetail jobDetail = JobBuilder.newJob(jobClass)
// 任务名称和任务分组 组合成任务唯一标识
.withIdentity("Job" + jobName, "Job" + groupName)
// 无触发器指向时是否需要持久化
.storeDurably(false).build();
CronTrigger trigger = TriggerBuilder.newTrigger()
// 触发器名称和触发器分组 组合成触发器唯一标识
.withIdentity("Trigger" + jobName, "Trigger" + groupName)
// cron触发器时间设定
.withSchedule(CronScheduleBuilder.cronSchedule(jobCron).inTimeZone(defaultTimeZone))
.build();
TriggerKey triggerKey = TriggerKey.triggerKey("Trigger" + jobName, "Trigger" + groupName);
// 如果已经存在定时任务
if (scheduler.checkExists(triggerKey)) {
// 更新定时任务的cron
scheduler.rescheduleJob(triggerKey, trigger);
} else {
// 添加定时任务
scheduler.scheduleJob(jobDetail, trigger);
}
}
/**
* 删除定时任务
*
* @param scheduler Quartz调度器
* @param jobClass 任务类
* @param groupName 任务分组
* @param jobName 任务名
* @throws SchedulerException
*/
private void deleteJob(Scheduler scheduler, String groupName, String jobName) throws SchedulerException {
TriggerKey triggerKey = TriggerKey.triggerKey("Trigger" + jobName, "Trigger" + groupName);
// 如果已经存在定时任务
if (scheduler.checkExists(triggerKey)) {
// 删除触发器,如果对应的任务没有其他的触发器关联并且Durably=false的时候,同时删除对应的任务
scheduler.unscheduleJob(triggerKey);
}
}
}
package com.study.quartz.task;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import com.study.quartz.service.IXXXService;
//禁止并发执行(Quartz不要并发地执行同一个job定义(这里指一个job类的多个实例))
@DisallowConcurrentExecution
public class Job1 extends QuartzJobBean {
private static final Logger logger = LoggerFactory.getLogger(Job1.class);
@Autowired
private IXXXService iXXXService;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
logger.info("【定时任务】Job1 启动");
iXXXService.doSomething(null);//调用Service执行具体的逻辑
}
}
因为集群版的quartz是把任务存到数据库里,所以需要创建一下quartz的表。创建表的SQL来自于quartz的jar包里,搜索一下maven目录,我这里的是D:\Program Files\eclipse-maven\repository\org\quartz-scheduler\quartz\2.3.2\quartz-2.3.2.jar 。文件内路径quartz-2.3.2.jar\org\quartz\impl\jdbcjobstore 。根据自己的数据库选择sql文件,我这里用的tables_mysql_innodb.sql