背景:在前端页面新建定时任务,将任务存入数据库,包含触发时间及触发模式
数据库表触发时间字段如下:
一、Quartz的介绍
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,是完全由java开发的一个开源的任务日程管理系统,“任务进度管理器”就是一个在预先确定(被纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统。
Quartz用一个小Java库发布文件(.jar文件),这个库文件包含了所有Quartz核心功能。这些功能的主要接口(API)是Scheduler接口。它提供了简单的操作,例如:将任务纳入日程或者从日程中取消,开始/停止/暂停日程进度。
不了解Quartz的可以查看下面的相关文章:
https://www.cnblogs.com/wangjiming/p/10027439.html
二、将Quartz引入Spring Boot以及使用
1、导入依赖的jar包:
org.springframework.boot spring-boot-starter-quartz
版本直接由spring boot控制
2、新建一个任务类,并实现Job接口,此接口只有一个方法void execute(JobExecutionContext jobExecutionContext)
public class MyJob implements Job {
private static IDutyService dutyService;
static {
dutyService = SpringUtil.getBean(IDutyService.class);
}
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
DutyDefEntity dutyDef = (DutyDefEntity) jobExecutionContext.getJobDetail().getJobDataMap().get("dutyDef");// 获取定义任务数据
Boolean success = this.dutyService.saveDuty(dutyDef);// 实现发布任务的业务接口
if (success) {
System.out.println("发布例行任务成功");
}
}
}
3、接下来新建一个工厂类,创建定时任务
@Service
@Component
public class MySchedulerFactory {
@Autowired
SchedulerFactoryBean schedulerFactoryBean;
// 获取scheduler
private Scheduler getScheduler(){
return schedulerFactoryBean.getScheduler();
}
// 项目启动 开启任务
public void startJob(DutyDefEntity dutyDefEntity) throws SchedulerException, ClassNotFoundException {
Scheduler scheduler = getScheduler(); // 获取scheduler
JobKey jobKey = JobKey.jobKey(Func.toStr(dutyDefEntity.getId()), "group1");//根据唯一标识符获取任务
Class extends Job> clazz = (Class extends Job>) Class.forName("org.springblade.modules.time.MyJob");
JobDetail jobDetail1 = scheduler.getJobDetail(jobKey);
String cron = "";
// 发布模式:隔天interval,指定日期specify
if (dutyDefEntity.getAutoMode().equals("interval")) {// 隔天interval
String[] time = dutyDefEntity.getAutoTime().toString().split(":");// 时分秒(数据库存的是时分秒)
// 如:每隔2天,在12点34分发布
// cron = "0 34 12 */2"
cron = "0 " + time[1] + " " + time[0] + " */" + dutyDefEntity.getAutoInterval();
}
if (dutyDefEntity.getAutoMode().equals("specify")) {// 指定日期specify
String[] time = dutyDefEntity.getAutoTime().toString().split(":");// 时分秒
// dutyDefEntity.getAutoMouth() 多个月份必须以英文逗号隔开
// 如:在4月和6月的23号,12点34分发布
// cron = "0 34 12 23 4,6 ? *"
cron = "0 " + time[1] + " " + time[0] + " " + dutyDefEntity.getAutoDay() + " " + dutyDefEntity.getAutoMouth() + " ? *";
}
if (jobDetail1==null){// 不存在就新建定时任务
JobDetail jobDetail = JobBuilder.newJob(clazz)
.withIdentity(Func.toStr(dutyDefEntity.getId()), "group1").build();
jobDetail.getJobDataMap().put("dutyDef", dutyDefEntity);// 将要发布的任务传递到任务的实现类MyJob中
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(Func.toStr(dutyDefEntity.getId()), "group1")
.withSchedule(scheduleBuilder).build();
scheduler.scheduleJob(jobDetail, cronTrigger);
}else {// 存在就修改触发时间
TriggerKey triggerKey = new TriggerKey(Func.toStr(dutyDefEntity.getId()), "group1");
CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
String oldTime = cronTrigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(cron)) {
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cron);
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(Func.toStr(dutyDefEntity.getId()), "group1")
.withSchedule(cronScheduleBuilder).build();
scheduler.rescheduleJob(triggerKey, trigger);
}
}
}
}
JobDetail是任务的定义,而Job是任务的执行逻辑。在JobDetail里会引用一个Job Class定义。每一个JobDetail都会有一个JobDataMap。JobDataMap本质就是一个Map的扩展类,只是提供了一些更便捷的方法,比如getString()之类的。
4、新建监听器类
@Configuration public class StartSchedulerListener implements ApplicationListener{ @Autowired public MySchedulerFactory mySchedulerFactory; // springboot 启动监听 @Override public void onApplicationEvent(ContextRefreshedEvent event) { } //注入SchedulerFactoryBean @Bean public SchedulerFactoryBean schedulerFactoryBean() { SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean(); return schedulerFactoryBean; } }
其实可以不用建立这个类,可以将SchedulerFactoryBean直接在MySchedulerFactory 中注入bean,代码如下:
@Resource privite SchedulerFactoryBean schedulerFactoryBean;
OK,现在需要去调用startJob方法,执行定时任务
5、利用springboot自带的定时器,每隔10分钟从数据库中获取最新的数据,并启动定时任务
@Component
@EnableScheduling
public class StartJob {
@Resource
private IDutyDefService dutyDefService;
@Autowired
public MySchedulerFactory mySchedulerFactory;
@Scheduled(initialDelay=1000, fixedDelay=600000) // 第一次延迟1秒执行,然后在上一次执行完毕时间点10分钟秒再次执行;
public void startTaskTimerByTenMin() {
try {
// 获取例行任务定义
QueryWrapper wrapper = new QueryWrapper<>();
List list = dutyDefService.list(wrapper);
if (Func.isNotEmpty(list)) {
for (DutyDefEntity dutyDefEntity : list) {
mySchedulerFactory.startJob(dutyDefEntity);// 开启定时任务,将要发布的任务传递进去
}
}
} catch (Exception e) {
}
}
}
完成!!!!!



