转载

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

好,直接进入主题

  • 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 这个获取到的是数据库中的记录封装成的实体,表结构如下

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

    获取到的记录通过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();
    }
}

`

原文  https://segmentfault.com/a/1190000020696869
正文到此结束
Loading...