1. Quartz介绍
Quartz是一个功能丰富的开源作业调度框架,可以集成到几乎任何Java应用程序中,从最小的独立应用程序到最大的电子商务系统。Quartz可以创建简单或复杂的调度,用于执行数十、数百甚至数万个作业;其Job被定义为标准的Java组件,可以执行任何指定的任务。Quartz调度程序包含许多企业级特性,例如对JTA事务和集群的支持。
Quartz有三个重要的核心元素,任务调度器(Scheduler),触发器(Trigger),任务(Job)。

2. Springboot整合Quartz
2.1 Springboot应用添加依赖
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
2.2 添加Quartz配置文件
resources资源文件夹下添加quartzConfig.properties文件内容如下:
# ===========================================================================
# Configure Main Scheduler Properties 调度器属性
# ===========================================================================
#调度器实例名称 集群中每一个实例都必须使用相同的名称
org.quartz.scheduler.instanceName=quartzClusterScheduler
#调度器实例编号自动生成
org.quartz.scheduler.instanceId=AUTO
#============================================================================
# ThreadPool
#============================================================================
#线程池的实现类(一般使用SimpleThreadPool即可满足几乎所有用户的需求)
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
#指定线程数,至少为1(无默认值)(一般设置为1-100直接的整数合适)
org.quartz.threadPool.threadCount = 25
#设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1,默认为5)
org.quartz.threadPool.threadPriority = 5
#============================================================================
# JobStore
#============================================================================
# 信息保存时间 默认值60秒
org.quartz.jobStore.misfireThreshold = 1000
#数据保存方式为数据库持久化
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreCMT
#数据库代理类
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#JobDataMaps是否都为String类型
org.quartz.jobStore.useProperties = false
#表的前缀,默认QRTZ_
org.quartz.jobStore.tablePrefix = QRTZ_
#开启分布式部署
org.quartz.jobStore.isClustered = true
#分布式节点有效性检查时间间隔,单位:毫秒
org.quartz.jobStore.clusterCheckinInterval = 20000
2.3 Quartz配置类
Quartz配置类读取配置文件信息,配置数据源,注入bean:schedulerFactoryBean,quartzProperties,scheduler实例。此外,在配置类中job,trigger,scheduler创建并主测监听器。
/**
* job工厂
*
* @author xingnana
* @create 2020-01-10
*/
@Component("jobFactory")
public class JobFactory extends AdaptableJobFactory {
//AutowireCapableBeanFactory 可以将一个对象添加到SpringIOC容器中,并且完成该对象注入
@Autowired
private AutowireCapableBeanFactory autowireCapableBeanFactory;
/**
*
* 将实例化的任务对象手动添加到Spring容器中,完成对象的注入,否则程序会报空指针异常
* @param bundle
* @return
* @throws Exception
*/
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object jobInstance=super.createJobInstance(bundle);
this.autowireCapableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
2.4 Quartz监听器
Quartz的监听器用于当任务调度中你所关注事件发生时,能够及时获取这一事件的通知。类似于任务执行过程中的邮件、短信类的提醒。Quartz监听器主要有JobListener、TriggerListener、SchedulerListener三种,顾名思义,分别表示任务、触发器、调度器对应的监听器。
三者的使用方法类似,在开始介绍三种监听器之前,需要明确两个概念:全局监听器与非全局监听器,二者的区别在于:全局监听器能够接收到所有的Job/Trigger的事件通知,而非全局监听器只能接收到在其上注册的Job或Trigger的事件,不在其上注册的Job或Trigger则不会进行监听。关于全局与非全局的监听器的使用,在本文中会做一介绍。
/**
* Job 监听器
*
* @author xingnana
* @create 2020-01-17
*/
@Slf4j
public class JobMonitorListener extends JobListenerSupport {
/**
* 获取该JobListener的名称
* @return
*/
@Override
public String getName() {
String name = getClass().getSimpleName();
log.info("Job监听器名字:{}",name);
return name;
}
/**
* Job将要被执行
* @param jobExecutionContext
*/
@Override
public void jobToBeExecuted(JobExecutionContext jobExecutionContext) {
JobDetail jobDetail=jobExecutionContext.getJobDetail();
JobKey jobKey=jobDetail.getKey();
Trigger trigger=jobExecutionContext.getTrigger();
log.info("Job将要被执行, jobName: {}, jobGroup: {}, jobDetail: {}, trigger: {}",jobKey.getName(),jobKey.getGroup(),
JSON.toJSONString(jobDetail), JSON.toJSONString(trigger));
}
/**
* Job被拒绝执行
* @param jobExecutionContext
*/
@Override
public void jobExecutionVetoed(JobExecutionContext jobExecutionContext) {
JobDetail jobDetail=jobExecutionContext.getJobDetail();
JobKey jobKey=jobDetail.getKey();
log.info("Job被TriggerListener拒绝执行, jobName: {}, jobGroup: {}, jobDetail: {}",jobKey.getName(),jobKey.getGroup(), JSON.toJSONString(jobDetail));
}
/**
* Job执行后
* @param jobExecutionContext
* @param e
*/
@Override
public void jobWasExecuted(JobExecutionContext jobExecutionContext, JobExecutionException e) {
JobDetail jobDetail=jobExecutionContext.getJobDetail();
JobKey jobKey=jobDetail.getKey();
log.info("Job执行完成, jobName: {}, jobGroup: {}, jobDetail: {}",jobKey.getName(),jobKey.getGroup(), JSON.toJSONString(jobDetail));
}
}
2.5 实现定时任务执行类
实现定时任务执行类,该类实现Job接口。方法execute是job被触发后执行的方法。如每天下午6点发送邮件。则在下午6点时,该类中的方法execute被触发调用,然后执行发邮件的操作。
/**
* 定时任务执行
*
* @author xingnana
* @create 2020-02-28
*/
@Slf4j
@Service("timerTaskRunService")
public class TimerTaskRunService implements Job {
public static String QUARTZ_AUTO_RUN = "quartz-auto-run";
// 定时任务运行类
public static String TIMER_TASK_RUN_CLASS = "com.tuya.ci.testbook.service.task.TimerTaskRunService";
@Resource
private IAsyncService asyncService;
/**
* 执行job
*
* @param jobExecutionContext
* @throws JobExecutionException
*/
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
Scheduler scheduler = jobExecutionContext.getScheduler();
JobKey jobKey = jobExecutionContext.getJobDetail().getKey();
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
log.info("调度器instanceId: {}, instanceName: {}, 当前执行线程: {}", scheduler.getSchedulerInstanceId(), scheduler.getSchedulerName(), Thread.currentThread());
if (jobExecutionContext.isRecovering()) {
log.info("作业被恢复:jobName: {}, jobGroup: {}, recovering at {}", jobKey.getName(), jobKey.getGroup(), sdf.format(new Date()));
} else {
log.info("作业被执行:jobName: {}, jobGroup: {}, starting at {}", jobKey.getName(), jobKey.getGroup(), sdf.format(new Date()));
}
// todo 异步 查询待执行定时任务 & 并执行测试任务
} catch (SchedulerException e) {
log.warn("调度器异常,无法运行测试任务, jobName: {}, jobGroup: {}, SchedulerException异常信息: \n{}",
jobKey.getName(), jobKey.getGroup(), com.tuya.ci.testbook.service.util.StringUtil.getStackTraceAsString(e));
} catch (Exception e) {
log.warn("调度器异常,无法运行测试任务, jobName: {}, jobGroup: {}, Exception异常信息: \n{}",
jobKey.getName(), jobKey.getGroup(), com.tuya.ci.testbook.service.util.StringUtil.getStackTraceAsString(e));
}
}
}
7302



被折叠的 条评论
为什么被折叠?



