spring-boot-Quartz-配置动态定时任务

10次阅读

共计 6563 个字符,预计需要花费 17 分钟才能阅读完成。

好,直接进入主题


  • 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();
    }
}

`

正文完
 0