版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/longqicsdn/article/details/86583702
首先引入依赖包:
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
接着实现写spirng boot的quartz配置类 QuartzJobConfig ,具体如下:
package com.draco.bootdemo.common.config;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.draco.bootdemo.common.component.quartzjob.BaseJob;
import com.draco.bootdemo.common.component.quartzjob.BootDemoJobFactory;
import com.draco.bootdemo.model.TaskJobInfo;
import com.draco.bootdemo.service.TaskJobInfoService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Description 定时任务配置类
* @Author LongQi
* @CreateTime 2019/1/11 15:37
*/
@Slf4j
@Configuration
public class QuartzJobConfig {
public static final List<BaseJob> JOB_LIST = new ArrayList<>();
@Autowired
private BootDemoJobFactory bootDemoJobFactory;
@Autowired
private DataSource dataSource;
@Autowired
private TaskJobInfoService taskInfoService;
@Bean(destroyMethod = "destroy",autowire = Autowire.NO)
public SchedulerFactoryBean schedulerFactoryBean(){
SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();
initJobAndTrigger(factoryBean);
factoryBean.setJobFactory(bootDemoJobFactory);
//factoryBean.setDataSource(dataSource);
//factoryBean.setConfigLocation(new ClassPathResource("/quartz.properties"));
factoryBean.setAutoStartup(true);
factoryBean.setOverwriteExistingJobs(true);
return factoryBean;
}
private void initJobAndTrigger(SchedulerFactoryBean schedulerFactoryBean) {
QueryWrapper<TaskJobInfo> taskQuery = new QueryWrapper<>();
taskQuery.in("STATUS",1,2); //未开始和进行中的job
taskQuery.orderByAsc("NAME");
List<TaskJobInfo> tasks = taskInfoService.list(taskQuery);
Map<String,List<String>> jobCronMap = new HashMap<>();
for(TaskJobInfo task : tasks){
if(jobCronMap.keySet().contains(task.getName())){
jobCronMap.get(task.getName()).add(task.getCronExpression());
}else{
List<String> cronList = new ArrayList<>();
cronList.add(task.getCronExpression());
jobCronMap.put(task.getName(), cronList);
}
}
JobDetail[] jobDetails = new JobDetail[JOB_LIST.size()];
Trigger[] triggers = new Trigger[tasks.size()];
int triggerCount = 0;
for (int i=0;i<JOB_LIST.size();i++) {
String jobName = JOB_LIST.get(i).getClass().getName();
JobDetail jobDetail = JobBuilder.newJob(JOB_LIST.get(i).getClass())
.withIdentity(jobName, "jobGroup")
.storeDurably(true)
.requestRecovery(true)
.build();
List<String> cronList = jobCronMap.get(jobName);
if(cronList !=null && !cronList.isEmpty()){
jobDetails[i] = jobDetail;
for(int j=0;j<cronList.size();j++){
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(jobName + ".Trigger"+j, "triGroup")
.forJob(jobName, "jobGroup")
.withSchedule(CronScheduleBuilder.cronSchedule(cronList.get(j)))
//.withSchedule(CronScheduleBuilder.cronSchedule(cronList.get(j)).withMisfireHandlingInstructionFireAndProceed())
.build();
triggers[triggerCount] = trigger;
triggerCount ++;
}
}
}
schedulerFactoryBean.setJobDetails(jobDetails);
schedulerFactoryBean.setTriggers(triggers);
}
}
接着配置SpringBeanJobFactory,用于spring容器注入job
/**
* @Description job注入使用
* @Author LongQi
* @CreateTime 2019/1/21 12:43
*/
@Component("bootDemoJobFactory")
public class BootDemoJobFactory extends SpringBeanJobFactory {
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object jobInstance = super.createJobInstance(bundle);
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
job的基本父类如下:
/**
* @Description job抽象类,自定义job只要继承该类并实现run()即可
* @Author LongQi
* @CreateTime 2019/1/12 12:52
*/
@Slf4j
public abstract class BaseJob implements Job{
@PostConstruct
public void init(){
QuartzJobConfig.JOB_LIST.add(this);
}
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
Long beginTime = System.currentTimeMillis();
log.info(this.getClass().getName()+"开始运行任务...");
run(jobExecutionContext);
log.info(this.getClass().getName()+"结束运行任务。总耗时:"+(System.currentTimeMillis()-beginTime)+"ms!");
}
/**
* 实现job运行的业务逻辑
* @param jobExecutionContext
*/
public abstract void run(JobExecutionContext jobExecutionContext);
}
具体job类如下:
package com.draco.bootdemo.common.component.quartzjob.job;
import com.draco.bootdemo.common.component.quartzjob.BaseJob;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.stereotype.Component;
/**
* @Description 定时任务
* @Author LongQi
* @CreateTime 2019/1/12 14:43
*/
@Component
public class DemoJob extends BaseJob {
@Override
public void run(JobExecutionContext context) {
System.out.println("执行job,此次对应的cron表达式为:"+context.getTrigger().getKey());
}
}
写完上面几个类后,数据库里建立如下表:
##quartz - job 业务job表
/*==============================================================*/
/* DBMS name: MySQL 5.0 */
/* Created on: 2019/1/21 20:42:33 */
/*==============================================================*/
drop table if exists TASK_JOB_INFO;
/*==============================================================*/
/* Table: TASK_JOB_INFO */
/*==============================================================*/
create table TASK_JOB_INFO
(
ID bigint comment '主键ID',
NAME varchar(150) comment 'JOB名称(一般是job的class名称)',
CRON_EXPRESSION varchar(50) comment 'CRON表达式',
TRIGGER_TIME datetime comment '触发时间',
STATUS tinyint comment '状态(1:未开始 2:进行中 3:已结束 )',
CREATOR bigint comment '创建人',
MODIFIER bigint comment '修改人',
CREATE_TIME datetime comment '创建时间',
MODIFY_TIME datetime comment '修改时间'
);
alter table TASK_JOB_INFO comment '任务Job表';
最上面的taskInfoService是TASK_JOB_INFO表对应的表接口,用于查询要进行的任务