调度计划由作业(JobDetail)和触发器(Trigger)构成。 Scheduler的scheduleJob方法可以向调度程序中添加新的作业和触发器。
工作流程
- 创建调度程序Scheduler
SchedulerFactoryBean factory = new SchedulerFactoryBean();
// 创建Scheduler实例
Scheduler scheduler = factory.getScheduler();
- 启动调度程序
scheduler.start();
- 创建调度程序执行类 继承 Job接口
public class ExecuteJob implements Job {
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
logger.info("定时任务开始执行,作业名=" + jobExecutionContext.getMergedJobDataMap().get("key"););
}
}
- 创建作业和触发器
// 创建作业
JobDetail jobDetail = JobBuilder.newJob(ExecuteJob.class)
.withIdentity(作业名, 作业组).build();
jobDetail.getJobDataMap().put("key", 作业名);
// 创建计划
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron表达式).withMisfireHandlingInstructionDoNothing();
// 创建触发器绑定计划
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(触发器名, 触发器组)
.withSchedule(scheduleBuilder).build();
- 添加调度作业
scheduler.scheduleJob(jobDetail, trigger);
开发步骤
-
pom.xml 引入maven包
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.3.0</version>
</dependency>
-
创建quartz.properties
#============================================================================
# 配置 Scheduler Properties
#org.quartz.scheduler.instanceName 程序名
#org.quartz.scheduler.instanceId 程序id 必须唯一
#org.quartz.threadPool.class 是要使用的ThreadPool实现的名称。Quartz附带的线程池是“org.quartz.simpl.SimpleThreadPool
#org.quartz.threadPool.threadCount 线程数 可用于并发执行作业的线程数
#org.quartz.threadPool.threadPriority 现成优先级 1-10
#org.quartz.jobStore.class RAMJobStore用于存储内存中的调度信息
#============================================================================
org.quartz.scheduler.instanceName = DOLPHIN
org.quartz.scheduler.instanceId = AUTO
#============================================================================
# Configure ThreadPool
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 25
org.quartz.threadPool.threadPriority = 5
#============================================================================
# Configure RAMJobStore
#============================================================================
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
-
创建Scheduler配置类 构建Scheduler实例
package com.dolphin.sigle.root.config.quartz;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import java.io.IOException;
import java.util.Properties;
/**
* 开发公司:青岛海豚数据技术有限公司
* 版权:青岛海豚数据技术有限公司
* <p>
* QuartzConfig
*
* @author 刘志强
* @created Create Time: 2019/1/31
*/
@Configuration
@EnableScheduling
public class SchedulerConfig {
// Bean注入构建调度工厂实例 依赖注入Properties
@Bean(name = "schedulerFactory")
public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setQuartzProperties(quartzProperties());
return factory;
}
// Bean注入构建Properties
@Bean
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}
/**
* 通过SchedulerFactoryBean获取Scheduler的实例并启动调度程序
*/
@Bean(name = "scheduler")
public Scheduler scheduler() throws IOException, SchedulerException {
Scheduler scheduler = schedulerFactoryBean().getScheduler();
scheduler.start();
return scheduler;
}
}
-
常见调度实体类
package com.dolphin.sigle.root.config.quartz;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 开发公司:青岛海豚数据技术有限公司
* 版权:青岛海豚数据技术有限公司
* <p>
* SchedulingPlan
* 调度计划实体类
*
* @author 刘志强
* @created Create Time: 2019/1/31
*/
@Data
@ApiModel(description = "计划信息")
public class SchedulingPlan {
/**
* 计划id
*/
@ApiModelProperty(value = "作业/触发器id", name = "id")
private Long id;
/**
* 计划名称
*/
@ApiModelProperty(value = "作业/触发器名称", name = "name")
private String name;
/**
* 计划组
*/
@ApiModelProperty(value = "作业/触发器组", name = "group")
private String group;
/**
* Cron表达式
*/
@ApiModelProperty(value = "Cron表达式", name = "CronExpressions")
private String CronExpressions;
/**
* 开启关闭状态 0开启 1暂停 2删除
*/
@ApiModelProperty(value = "开启关闭状态", name = "status")
private Integer status;
}
-
创建调度程序执行类
package com.dolphin.sigle.root.config.quartz;
import com.dolphin.common.tool.DateUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* 开发公司:青岛海豚数据技术有限公司
* 版权:青岛海豚数据技术有限公司
* <p>
* ExecuteJob
*
* @author 刘志强
* @created Create Time: 2019/1/31
*/
@Component
public class ExecuteJob implements Job {
private static final Logger logger = LogManager.getLogger(ExecuteJob.class.getName());
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SchedulingPlan schedulingPlan = (SchedulingPlan) jobExecutionContext.getMergedJobDataMap().get("key");
logger.info("定时任务开始执行,任务名称[" + schedulingPlan.getName() + "]::::::执行时间" + DateUtils.formatDateTime(new Date()));
}
}
-
创建调度处理接口和实现类
package com.dolphin.sigle.root.config.quartz;
import org.quartz.*;
/**
* 开发公司:青岛海豚数据技术有限公司
* 版权:青岛海豚数据技术有限公司
* <p>
* SchedulerService
*
* @author 刘志强
* @created Create Time: 2019/1/31
*/
public interface SchedulerService {
/**
* 添加调度计划
* @param schedulingPlan 计划信息
*/
public int addSchedulingPlan(SchedulingPlan schedulingPlan);
}
package com.dolphin.sigle.root.config.quartz;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
*withMisfireHandlingInstructionIgnoreMisfires(所有misfire的任务会马上执行)
* 如 原调度计划是1秒执行一次,,暂停10秒,当调度计划恢复时 会先执行10次
*
*withMisfireHandlingInstructionDoNothing(所有的misfire不管,执行下一个周期的任务)
* 如 原调度计划是1秒执行一次,,暂停10秒,当调度计划恢复时 会在下个周期在执行(中间暂停的10次会放弃)
*
*withMisfireHandlingInstructionFireAndProceed(会合并部分的misfire,正常执行下一个周期的任务)
* 当修改计划时,会先执行一次计划
* 恢复计划时,会执行一次
*/
/**
* 开发公司:青岛海豚数据技术有限公司
* 版权:青岛海豚数据技术有限公司
* <p>
* QuartzHandle
*
* @author 刘志强
* @created Create Time: 2019/1/31
*/
@Service
public class SchedulerImpl implements SchedulerService {
@Autowired
public Scheduler scheduler;
private static final Logger logger = LogManager.getLogger(SchedulerImpl.class.getName());
/**
* 添加调度计划
* @param schedulingPlan 计划信息
*/
public int addSchedulingPlan(SchedulingPlan schedulingPlan) {
logger.info("开始向任务调度中添加定时任务---" + schedulingPlan.getName());
try {
JobDetail jobDetail = JobBuilder.newJob(ExecuteJob.class)
.withIdentity(schedulingPlan.getName(), schedulingPlan.getGroup()).build();
jobDetail.getJobDataMap().put("key", schedulingPlan);
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(schedulingPlan.getCronExpressions()).withMisfireHandlingInstructionDoNothing();
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(schedulingPlan.getName(), schedulingPlan.getGroup())
.withSchedule(scheduleBuilder).build();
scheduler.scheduleJob(jobDetail, trigger);
logger.info("成功向任务调度中添加定时任务---" + schedulingPlan.getName());
return 200;
} catch (Exception e) {
logger.error("向任务调度中添加定时任务异常!---" + schedulingPlan.getName(), e);
return 500;
}
}
}