好,直接进入主题
- maven 依赖
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
</dependency>
-
配置
首先重写一下 QuartJob 工厂,解决注入问题public class QuartJobFactory extends AdaptableJobFactory { @Autowired private AutowireCapableBeanFactory capableBeanFactory; @Override protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { // 调用父类的方法 Object jobInstance = super.createJobInstance(bundle); // Spring 注入 capableBeanFactory.autowireBean(jobInstance); return jobInstance; } }
重写 listener
public class QuartJobSchedulingListener implements ApplicationListener<ContextRefreshedEvent> {private static final Logger log = LoggerFactory.getLogger(QuartJobSchedulingListener.class); @Override public void onApplicationEvent(ContextRefreshedEvent event) { try {if (event.getApplicationContext().getParent() == null) {log.debug("onApplicationEvent"); ApplicationContext applicationContext = event.getApplicationContext(); addDbBatchs(applicationContext); //addDynamicJobs(applicationContext); } } catch (Exception e) {log.error("", e); } } private void addDbBatchs(ApplicationContext applicationContext) {SchedulerFactoryBean schedulerFactoryBean = applicationContext.getBean(SchedulerFactoryBean.class); BatchTaskService taskService = applicationContext.getBean(BatchTaskService.class); List<SysBatch> list = taskService.getAllBatch(); for (SysBatch batch : list) { try {QuartJobUtil.addScheduler(schedulerFactoryBean, batch); } catch (Exception e) {log.error("", e); } } } }
请注意:List<SysBatch> list 这个获取到的是数据库中的记录封装成的实体,表结构如下
获取到的记录通过 QuartJobUtil 工具类的方法加载到定时中
管理定时工具类 QuartJobUtil
`
public class QuartJobUtil {private static final Log log = LogFactory.getLog(QuartJobUtil.class);
/**
* 追加定时
*
* @param schedulerFactoryBean
* @param sysBatch
* @throws SchedulerException
*/
public static void addScheduler(SchedulerFactoryBean schedulerFactoryBean, SysBatch sysBatch)
throws SchedulerException {if (schedulerFactoryBean == null) {return;}
Scheduler scheduler = schedulerFactoryBean.getScheduler();
String jobName = sysBatch.getBatchId();
String jobGroup = QuartzCron.JOB_GROUP_DYNAMIC;
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
JobDetail jobDetail = scheduler.getJobDetail(new JobKey(jobName, jobGroup));
// 获取 trigger
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
String cronExpression = sysBatch.getCron();
DateTime runTime = new DateTime();
runTime = runTime.plusMinutes(1);
// 不存在,创建一个
if (null == jobDetail) {JobDetailFactoryBean jobDetailFactory = new JobDetailFactoryBean();
jobDetailFactory.setName(jobName);
jobDetailFactory.setGroup(jobGroup);
jobDetailFactory.setJobClass(BatchJobCall.class);
jobDetailFactory.setDurability(true);
jobDetailFactory.afterPropertiesSet();
jobDetail = jobDetailFactory.getObject();
jobDetail.getJobDataMap().put(CommonConstants.JOB_DATA_KEY, sysBatch);
CronTriggerFactoryBean triggerFactory = new CronTriggerFactoryBean();
triggerFactory.setJobDetail(jobDetail);
triggerFactory.setName(jobName);
triggerFactory.setGroup(jobGroup);
triggerFactory.setCronExpression(cronExpression);
try {triggerFactory.afterPropertiesSet();
// 按新的 cronExpression 表达式构建一个新的 trigger
trigger = triggerFactory.getObject();
log.debug("增加批处理:");
log.debug(jobName + "-" + jobGroup);
log.debug(sysBatch.getName());
log.debug(cronExpression);
}
catch (ParseException e) {log.warn(sysBatch.getBatchId() + "_" + sysBatch.getCron(), e);
}
scheduler.scheduleJob(jobDetail, trigger);
}
else {
// 已存在,那么更新相应的设置
jobDetail.getJobDataMap().put(CommonConstants.JOB_DATA_KEY, sysBatch);
CronTriggerFactoryBean triggerFactory = new CronTriggerFactoryBean();
// 将最新的 Batch 添加到 Map 中
triggerFactory.getJobDataMap().put(CommonConstants.JOB_DATA_KEY, sysBatch);
triggerFactory.setJobDetail(jobDetail);
triggerFactory.setName(jobName);
triggerFactory.setGroup(jobGroup);
triggerFactory.setCronExpression(cronExpression);
//triggerFactory.setStartTime(runTime.toDate());
try {triggerFactory.afterPropertiesSet();
// 按新的 cronExpression 表达式构建一个新的 trigger
trigger = triggerFactory.getObject();
log.debug("修改批处理:");
log.debug(jobName + "-" + jobGroup);
log.debug(sysBatch.getName());
log.debug(cronExpression);
}
catch (ParseException e) {log.warn(e);
}
// 按新的 trigger 重新设置 job 执行
scheduler.rescheduleJob(triggerKey, trigger);
}
}
/**
* 删除批处理
*
* @param schedulerFactoryBean
* @param sysBatch
* @throws SchedulerException
*/
public static void deleteDocScheduler(SchedulerFactoryBean schedulerFactoryBean, SysBatch sysBatch)
throws SchedulerException {if (schedulerFactoryBean == null) {return;}
Scheduler scheduler = schedulerFactoryBean.getScheduler();
String jobName = sysBatch.getBatchId();
String jobGroup = QuartzCron.JOB_GROUP_DYNAMIC;
JobKey jobKey = new JobKey(jobName, jobGroup);
boolean result = scheduler.deleteJob(jobKey);
log.info("删除批处理:" + jobName);
log.info("删除结果:" + result);
}
}
`
这里面最重要的是
jobDetailFactory.setJobClass(BatchJobCall.class);
jobDetail.getJobDataMap().put(CommonConstants.JOB_DATA_KEY, sysBatch);
BatchJobCall.class 类是定时触发的响应类,CommonConstants.JOB_DATA_KEY 是一个常量,目的是在响应类中获取到 sysBatch 实体。
BatchJobCall
`
public class BatchJobCall extends QuartzJobBean {private static final Log log = LogFactory.getLog(BatchJobCall.class);
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
// 获取实体
SysBatch batch = (SysBatch) context.getJobDetail().getJobDataMap().get(CommonConstants.JOB_DATA_KEY);
String beanName = batch.getBeanName();
String beanMethod = batch.getBeanMethod();
String argument = batch.getArgument();
if (StringUtils.isNotEmpty(beanName) && StringUtils.isNotEmpty(beanMethod)) {SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss:SSS");
try {log.debug(batch.getBatchId() + "_" + batch.getName() + "- 定时任务开始执行具体方法:" + sdf.format(new Date()));
Class<?> printClass = Class.forName(beanName);
Object obj = printClass.newInstance();
capableBeanFactory.autowireBean(obj);
// 获取方法
Method printMethod = printClass.getMethod(beanMethod, String.class);
// 调用
printMethod.invoke(obj, argument);
log.debug(batch.getBatchId() + "_" + batch.getName() + "- 定时任务执行结束:" + sdf.format(new Date()));
}
catch (Exception e) {log.warn(batch.getBatchId() + "_" + batch.getName() + "- 定时任务调用失败" + sdf.format(new Date()));
throw new JobExecutionException(e);
}
}
}
}
`
在这里通过 反射机制 去调用表中 sysbatch 实体存的 类名以及方法名
最后配置 QuartzConfig
`
@Configuration
public class QuartzConfig {
@Bean
public QuartJobSchedulingListener quartJobSchedulingListener() {return new QuartJobSchedulingListener();
}
/**
* 获取定时任务工厂
*
* @return 获取定时任务工厂
*/
@Bean
public SchedulerFactoryBean schedulerFactoryBean() {SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
schedulerFactory.setJobFactory(jobFactory());
return schedulerFactory;
}
/**
* QuartJob 工厂,解决注入问题
*
* @return QuartJob 工厂
*/
@Bean
public JobFactory jobFactory() {QuartJobFactory factory = new QuartJobFactory();
return factory;
}
/**
* 调度
*
* @return BatchJobCall
*/
@Bean
public BatchJobCall getJobCall() {return new BatchJobCall();
}
}
`