这个作业属于哪个课程 | 福大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进行时间规定的时候遇到了困难,这边推荐两个博客,很好的解决了我的疑问
四、总结
总的来说,quartz是个很强大的定时任务框架,springboot的原生定时任务注解不能很好的管理定时任务,但是quartz框架会帮助你管理好定时任务的线程池,比较方便地进行定时任务的增删改查,只要将小问题解决了,就尽管编写业务逻辑代码,并进行定时任务的发布与管理即可,是相当强大的一个框架。
五、参考文献
corn表达式的使用方法 作者:西班牙乞丐
java中的时间和时间戳 作者:小小舍
SpringBoot2.1 - Quartz自动化配置集成 yml方式配置免配置类和properties 作者:ataopro