1.先看效果
通过上图打印日志信息,我们可以知道,作业会经历一个这样的生命周期:触发器触发 -> 作业即将被执行 -> 作业被执行 -> 作业执行完成 -> 本次调度触发完成。
2.看项目结构
3.看关键类
3.1 StartRunner
StartRunner实现了ApplicationRunner,会随着Springboot启动被执行。该类主要作用是启动Quartz并读取配置文件中作业相关配置信息,将作业加入调度计划。
- 配置项:
system.job.classNameList=com.example.little.job.BusinessJob
system.job.cronList=0/30 ?
- StartRunner,注入了QzService
public class StartRunner implements ApplicationRunner {
@Autowired
private QzService qzService;
@Autowired
private JobInfoConfig jobInfoConfig;
@Override
public void run(ApplicationArguments args) throws Exception {
qzService.start();
log.info("我的日志: qz调度启动.");
String[] jobList = jobInfoConfig.getClassNameList();
String[] cronList = jobInfoConfig.getCronList();
for (int i = 0; i < jobList.length; i++) {
JobInfo jobInfo = new JobInfo();
jobInfo.setClassName(jobList[i].trim());
jobInfo.setCron(cronList[i].trim());
qzService.addJob(jobInfo);
}
}
}
3.2 QzService
具体实现类是QuartzServiceImpl,封装了Quartz的调度器Scheduler常用功能。示例中的调度启动start()方法,在启动时加入了各种类型的Listener;作业加入调度的addJob(),可将作业加入调度。当然Quartz还支持作业暂定、移除、恢复调度等很多的功能。此处仅做演示,代码如下:
@Service
public class QzServiceImpl implements QzService {
@Autowired
Scheduler scheduler;
@Override
public void start() throws Exception {
scheduler.getListenerManager().addJobListener(new JobListener());
scheduler.getListenerManager().addTriggerListener(new TriggerListener());
scheduler.getListenerManager().addSchedulerListener(new SchedulerListener());
scheduler.start();
}
@Override
public void addJob(JobInfo jobInfo) throws Exception {
Class clazz_ = Class.forName(jobInfo.getClassName());
JobDetail jobDetail = JobBuilder.newJob(clazz_).build();
Trigger trigger = TriggerBuilder.newTrigger().
withSchedule(CronScheduleBuilder.cronSchedule(jobInfo.getCron())).build();
scheduler.scheduleJob(jobDetail, trigger);
}
}
3.3 SchedulerListener
见名知意,是调度相关事件的监听器,这里仅实现了两个方法,作业加入调度时会通知jobAdd()方法,scheduler将job和trigger绑定的时候会通知jobScheduled()方法。代码如下:
@Slf4j
public class SchedulerListener extends SchedulerListenerSupport {
@Override
public void jobAdded(JobDetail jobDetail) {
super.jobAdded(jobDetail);
log.info("我的日志: job被加入调度 ,key {}", jobDetail.getKey());
}
@Override
public void jobScheduled(Trigger trigger) {
super.jobScheduled(trigger);
log.info("我的日志:作业开始被调度 ,key {}", trigger.getKey());
}
}
3.4.TriggerListener
trigger事件监听器,当trigger到达执行时间被触发时,会通知triggerFired()方法;当触发完成后,会通知triggerComplete()方法;当trigger错过调度时间时,会通知triggerMisfired()方法。
public class TriggerListener extends TriggerListenerSupport {
@Override
public String getName() {
return "little_trigger";
}
@Override
public void triggerFired(Trigger trigger, JobExecutionContext context) {
super.triggerFired(trigger, context);
log.info("我的日志: trigger触发开始 {}", trigger.getKey());
}
@Override
public void triggerComplete(Trigger trigger, JobExecutionContext context, Trigger.CompletedExecutionInstruction triggerInstructionCode) {
super.triggerComplete(trigger, context, triggerInstructionCode);
log.info("我的日志:trigger触发结束 {} ", trigger.getKey());
}
@Override
public void triggerMisfired(Trigger trigger) {
super.triggerMisfired(trigger);
log.info("我的日志,trigger错过触发 {} ", trigger.getKey());
}
}
3.5 JobListener
job的事件监听器,作业将要被执行时,会通知jobToBeExecuted()方法;作业执行完成时,会通知jobWasExecuted()方法。想一下,这里是不是可以在作业执行的前后做些什么?
比如日志、执行情况记录等等。
public class JobListener extends JobListenerSupport {
@Override
public String getName() {
return "little_job";
}
@Override
public void jobToBeExecuted(JobExecutionContext context) {
super.jobToBeExecuted(context);
log.info("我的日志: job将要被执行");
}
@Override
public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
super.jobWasExecuted(context, jobException);
log.info("我的日志:job执行完成");
}
}
相关概念
- Scheduler:Quartz的核心调度器,提供了调度器启动、终止、作业新增、暂定、移除、恢复调度等丰富的功能。
- Job(QuartzJobBean):QuartzJobBean是Spring对quartz的Job的包装,只有一个方法,用于实现真正要被调度的业务逻辑。
- Trigger:触发器,时间到达执行时间时会被触发,去触发Job的执行。
- 各类监听器:标准的观察者模式,可根据业务需要进行扩展,对于作业的全生命周期进行监控或者控制,比如本示例的日志打印。作业监听器JobListenerSupport,调度监听器SchedulerListenerSupport,触发器监听TriggerListenerSupport。
其他
1.示例中,通过配置文件+ApplicationRunner的方式来将作业加入quartz执行,可改为读取数据库方式,实现更加灵活的作业管控。
2.示例中,各类监听器,监听到事件时仅仅做了日志打印动作,实际可根据业务需要进行一些记录或者作业执行过程中的管控。