前言
知识概念
一、什么是Quartz?
Quartz是一个完全由java编写的开源作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制。二、Quartz架构
Quartz架构有4个核心概念:Job 、JobDetail 、Trigger 、Scheduler
• Job:表示一个工作或任务,包含具体执行的内容。
• JobDetail:表示一个具体的可执行的调度程序,Job 是这个可执行程调度程序所要执行的内容,另外 JobDetail 还包含了这个任务调度的方案和策略。
• Trigger:表示触发器,包含可执行调度程序的时间参数配置,是可执行调度程序的时间执行策略
• Scheduler:代表一个调度容器,一个调度容器中可以注册多个JobDetail和Trigger,当JobDetail和Trigger组合,就可以被调度容器调度了
三、示例
框架:Springboot; (quartz官方Demo)
Pom.xml
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
</dependency>
quartz.properties
//Quartz
//线程调度器实例名
org.quartz.scheduler.instanceName = quartzScheduler
//如何存储任务和触发器等信息
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
//驱动代理
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
//表前缀
org.quartz.jobStore.tablePrefix = qrtz_
//数据源 must
org.quartz.jobStore.dataSource = quartzDataSource
//是否集群
org.quartz.jobStore.isClustered = false
org.quartz.dataSource.quartzDataSource.connectionProvider.class=com.alibaba.druid.support.quartz.DruidQuartzConnectionProvider
org.quartz.dataSource.quartzDataSource.driverClassName =com.mysql.jdbc.Driver
org.quartz.dataSource.quartzDataSource.Url=jdbc:mysql://localhost:3306/quartz?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
org.quartz.dataSource.quartzDataSource.username=root
org.quartz.dataSource.quartzDataSource.password=root
org.quartz.dataSource.quartzDataSource.validationQuery=SELECT 1 FROM DUAL
//线程池的线程数 must>0
org.quartz.threadPool.threadCount = 3
1、Job
public class BarrageJob implements Job{
private static Logger logger = Logger.getLogger(BarrageJob.class);
@Autowired
BarrageService barrageService;
@Autowired
QuartzService quartzService;
//任务的具体执行内容
@Override
public void execute(JobExecutionContext context)
throws JobExecutionException {
logger.info("BarrageJob开始执行");
Date date = new Date();
Timestamp time = new Timestamp(date.getTime());
Integer count = barrageService.getBarrageCount(time);
quartzService.insertJobData(new QrtzJobData(-1,context.getJobDetail().getKey().getName(),time,String.valueOf(count),BarrageJob.class.getName()));
logger.info("BarrageJob执行完毕");
}
}
注意:BarrageJob中的注解正常情况下是无效的,因为它没有被Spring容器管理,因此需要在下面手动注入到容器中。
2、JobDetail
JobDetail myjob = JobBuilder.newJob(BarrageJob.class).withIdentity(jobName, jobGroupName).build();
3、Trigger
Quartz提供了多个Trigger供我们选择(详情请查看相关源码),可以选择其一例如:CronTrigger
CronTrigger trigger = TriggerBuilder.newTrigger().
withSchedule(CronScheduleBuilder.cronSchedule(Cron表达式).withIdentity(triggerName, triggerGroup).startAt(开始时间).endAt(结束时间).build();
Cron表达式规则可以自行百度
4、Scheduler
ScheduleConfig:
@Configuration
public class ScheduleConfig {
//添加工作监听如不需要可注释
@Autowired
MyJobListener myJobListener;
//注册此工厂是为了使得在任务或工作即Job中也能使用Spring注解
@Autowired
MyJobFactory myJobFactory;
@Bean
public SchedulerFactoryBean getSchedulerFactoryBean(){
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setJobFactory(myJobFactory);
Properties quartzProperties = ReadResourceUtils.getProperties("quartz.properties");
//可以选择不加载自定义的properties文件,系统会加载默认的配置文件
if(null != quartzProperties)factory.setQuartzProperties(quartzProperties);
return factory;
}
@Bean(name="myScheduler")
public Scheduler getScheduler() throws SchedulerException{
//SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = getSchedulerFactoryBean().getScheduler();
scheduler.getListenerManager().addJobListener(myJobListener);
return scheduler;
}
}
MyJobFactory:
@Component
public class MyJobFactory extends AdaptableJobFactory{
@Autowired
private AutowireCapableBeanFactory factory;
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
// 调用父类的方法
Object jobInstance = super.createJobInstance(bundle);
// 进行注入
factory.autowireBean(jobInstance);
return jobInstance;
}
}
MyJobListener:
@Component
public class MyJobListener implements JobListener {
@Override
public String getName() {
return "myJobListener";
}
@Autowired
QuartzService quartzService;
@Override
public void jobToBeExecuted(JobExecutionContext context) {
System.out.println("start:jobToBeExecuted");
String jobName = context.getJobDetail().getKey().getName();
System.out.println("end:jobToBeExecuted");
}
@Override
public void jobExecutionVetoed(JobExecutionContext context) {
}
/**任务执行后更新任务状态*/
@Override
public void jobWasExecuted(JobExecutionContext context,
JobExecutionException jobException) {
System.out.println("start:jobWasExecuted");
String jobName = context.getJobDetail().getKey().getName();
System.out.println("end:jobWasExecuted");
}
}
5、绑定JobDetail和CronTrigger到scheduler容器中
因为上面scheduler配置的时候已经将scheduler交给Spring容器进行管理了此时只需要自动注入
就可以获得scheduler容器
//将JobDetail和CronTrigger绑定到scheduler容器中
scheduler.scheduleJob(JobDetail, CronTrigger);
//调度任务
scheduler.start();