个人技术总结——关于springboot的定时任务框架quartz

这个作业属于哪个课程 福大20春软工S班
这个作业要求在哪里 个人作业——软件工程实践总结&个人技术博客
这个作业的目标 个人技术总结
作业正文 正文
其他参考文献 百度 CSDN博客

一、技术概述

1、 该技术的用处在于规范的发布springboot的定时任务,并能方便地对定时任务进行增删改查。

2、 学习quartz框架的难点在于,springboot的自动注入需要编写quartz的配置类才能完成,这导致我一开始无法自动注入,不能在定时任务类中使用dao层代码,定时任务还运用了corn格式,还有线程池,这些都是难点。

二、技术详述

在maven中引入springboot的quartz框架
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
 </dependency>
import org.quartz.Scheduler;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

/**
 * @author: ak
 * @date: 2020/5/6 19:00
 * @description:编写quartz的配置类,这样才能在quartz相关的代码中运用springboot的自动注入
 */
@Configuration
public class JobFactory extends SpringBeanJobFactory {

    @Autowired
    private AutowireCapableBeanFactory beanFactory;

    @Autowired
    private JobFactory jobFactory;

    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        Object jobInstance = super.createJobInstance(bundle);
        beanFactory.autowireBean(jobInstance);
        return jobInstance;
    }

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() {
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        schedulerFactoryBean.setJobFactory(jobFactory);
        return schedulerFactoryBean;
    }

    @Bean(name = "scheduler")
    public Scheduler scheduler() {
        return schedulerFactoryBean().getScheduler();
    }
}

import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/**
     * quartz写定时任务业务逻辑的代码,需要继承quartz框架提供的接口job类
     *
     */
@Component
public class TaskJob implements Job {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void execute(JobExecutionContext jobExecutionContext) {
        JobDataMap jobDataMap = jobExecutionContext.getMergedJobDataMap();
        String[] key = jobDataMap.getKeys();
        //获取要进行统分的评分表id,以下皆为定时任务要实行的业务逻辑
        int kid = Integer.parseInt(jobDataMap.getString(key[0]));
        System.out.println("正在统分....");
        statEvaluationOuter(kid);
        statEvaluationInner(kid);
        System.out.println("任务结束...");
    }
/**
     * quartz用于发布定时任务的代码
     *
     * @param cron      任务周期
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param tableDataKey   指定定时任务的ID
     * @param tableData   指定定时任务需要的数据
     */
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

    @Autowired
    Scheduler scheduler;

    public void publishTask(String cron, long startTime, long endTime, String tableDataKey, String tableData) throws SchedulerException {
        try {
            Scheduler scheduler = this.scheduler;
            //创建JobDetail实例,并与TaskJob类绑定(Job执行内容),TaskJob类代码在上面
            JobDetail jobDetail = JobBuilder.newJob(TaskJob.class)
                    .withIdentity("job-" + tableDataKey, "group-" + tableDataKey).build();
            //指定周期性定时任务
            CronTrigger cronTrigger = TriggerBuilder.newTrigger()
                    .withIdentity("trigger-" + tableDataKey, "triggerGroup-" + tableDataKey)
                    .usingJobData(tableDataKey, tableData)
                    .startNow()//立即生效
                    .startAt(new Date(startTime))
                    .endAt(new Date(endTime))
                    .withSchedule(CronScheduleBuilder.cronSchedule(cron))
                    .build();

            //执行
            scheduler.scheduleJob(jobDetail, cronTrigger);
            System.out.println("--------定时任务发布成功 ! ------------");
            System.out.println(cronTrigger.getJobDataMap().get(tableDataKey));
            System.out.println("当前任务key:" + tableDataKey);
            scheduler.start();

        } catch (SchedulerException e) {
            throw e;
        }
    }

通过编写上述的Job类和发布任务的方法,只要使用publishTask方法,就可以对定时任务进行发布了,当然quartz还能进行任务的修改,删除和查找,使用方法就像数据库一样,很相似,在这里就不过多赘述,想看的可以看github上的代码:

定时任务的增删改查代码

三、遇到的困难和解决

1、 首先是springboot的自动注入问题,quartz框架由于发布定时任务的时候会在springboot注入容器之前,所以如果不编写配置类会发现自动注入的对象是null的情况。我的定时任务中要对数据库进行修改,但是在定时任务的Job类中自动注入的dao层代码一直是null,导致我无法在Job类中对数据库进行操作。最终我查阅资料,知道了要编写quartz框架的配置类,解决办法就是增加配置类代码,代码在第二点技术详述里面有。

2、对于corn和时间戳的使用。一开始我不懂corn和时间戳都是什么,在使用quartz进行时间规定的时候遇到了困难,这边推荐两个博客,很好的解决了我的疑问

corn表达式的使用方法

java中的时间和时间戳

四、总结

总的来说,quartz是个很强大的定时任务框架,springboot的原生定时任务注解不能很好的管理定时任务,但是quartz框架会帮助你管理好定时任务的线程池,比较方便地进行定时任务的增删改查,只要将小问题解决了,就尽管编写业务逻辑代码,并进行定时任务的发布与管理即可,是相当强大的一个框架。

五、参考文献

corn表达式的使用方法 作者:西班牙乞丐

java中的时间和时间戳 作者:小小舍

SpringBoot2.1 - Quartz自动化配置集成 yml方式配置免配置类和properties 作者:ataopro

猜你喜欢

转载自www.cnblogs.com/bkmemory/p/13162806.html