<!--任务调度相关依赖-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
任务工厂JobFactory
这里我们需要注意 我注入了一个 自定义的JobFactory ,然后 把其设置为SchedulerFactoryBean 的 JobFactory。其目的是因为我在具体的Job 中 需要Spring 注入一些Service。
所以我们要自定义一个jobfactory, 让其在具体job 类实例化时 使用Spring 的API 来进行依赖注入。
JobFactory具体实现:
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;
/**
* @Author: liangbl
* @Date: 2019/1/22 11:06
* @Description: 任务工厂JobFactory
* 解决SpringBoot不能在Quartz中注入Bean的问题
*/
@Component
public class JobFactory extends AdaptableJobFactory {
/**
* AutowireCapableBeanFactory接口是BeanFactory的子类,可以连接和填充那些生命周期不被Spring管理的已存在的bean实例
*/
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
/**
* 创建Job实例
* @param bundle
* @return
* @throws Exception
*/
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
// 实例化对象
Object jobInstance = super.createJobInstance(bundle);
// 进行注入(Spring管理该Bean)
capableBeanFactory.autowireBean(jobInstance);
//返回对象
return jobInstance;
}
}
新建一个QuartzConfig
添加 QuartzConfig 类 来声明相关Bean
import org.quartz.Scheduler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
/**
* @Author: liangbl
* @Date: 2019/1/22 11:06
* @Description: 任务调度器 Scheduler
*/
@Configuration
public class QuartzConfig {
private JobFactory jobFactory;
public QuartzConfig(JobFactory jobFactory){
this.jobFactory = jobFactory;
}
/**
* 配置SchedulerFactoryBean
* 将一个方法产生为Bean并交给Spring容器管理
* @return
*/
@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
// Spring提供SchedulerFactoryBean为Scheduler提供配置信息,并被Spring容器管理其生命周期
SchedulerFactoryBean factory = new SchedulerFactoryBean();
// 设置自定义Job Factory,用于Spring管理Job bean
factory.setJobFactory(jobFactory);
return factory;
}
@Bean(name = "scheduler")
public Scheduler scheduler() {
return schedulerFactoryBean().getScheduler();
}
}
新建一个QuartzScheduler
在其他类中调用本类中的addJob方法进行任务添加
import com.hellowin.b2c.base.SSHValidateHelper;
import com.hellowin.b2c.persistence.model.cron.CronTask;
import org.apache.log4j.Logger;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
/**
* @Author: liangbl
* @Date: 2019/1/21 13:51
* @Description: 任务调度处理
*/
@Service
public class QuartzScheduler {
public final Logger log = Logger.getLogger(this.getClass());
/**
* 任务调度
*/
@Autowired
private Scheduler scheduler;
/**
* 开始执行所有任务
*
* @throws SchedulerException
*/
public void startJob() throws SchedulerException {
startJob(scheduler);
}
/**
* 获取Job信息
*
* @param name
* @param group
* @return
* @throws SchedulerException
*/
public String getJobInfo(String name, String group) throws SchedulerException {
TriggerKey triggerKey = new TriggerKey(name, group);
CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
return String.format("time:%s,state:%s", cronTrigger.getCronExpression(),
scheduler.getTriggerState(triggerKey).name());
}
/**
* 修改某个任务的执行时间
*
* @param name
* @param group
* @param time
* @return
* @throws SchedulerException
*/
public boolean modifyJob(String name, String group, String time) throws SchedulerException {
Date date = null;
TriggerKey triggerKey = new TriggerKey(name, group);
CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
String oldTime = cronTrigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(time)) {
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(time);
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(name, group)
.withSchedule(cronScheduleBuilder).build();
date = scheduler.rescheduleJob(triggerKey, trigger);
}
return date != null;
}
/**
* 暂停所有任务
*
* @throws SchedulerException
*/
public void pauseAllJob() throws SchedulerException {
scheduler.pauseAll();
}
/**
* 暂停某个任务
*
* @param name
* @param group
* @throws SchedulerException
*/
public void pauseJob(String name, String group) throws SchedulerException {
JobKey jobKey = new JobKey(name, group);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if (jobDetail == null) {
return;
}
scheduler.pauseJob(jobKey);
}
/**
* 恢复所有任务
*
* @throws SchedulerException
*/
public void resumeAllJob() throws SchedulerException {
scheduler.resumeAll();
}
/**
* 恢复某个任务
*
* @param name
* @param group
* @throws SchedulerException
*/
public void resumeJob(String name, String group) throws SchedulerException {
JobKey jobKey = new JobKey(name, group);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if (jobDetail == null) {
return;
}
scheduler.resumeJob(jobKey);
}
/**
* 删除某个任务
*
* @param name
* @param group
* @throws SchedulerException
*/
public void deleteJob(String name, String group) throws SchedulerException {
JobKey jobKey = new JobKey(name, group);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if (jobDetail == null) {
return;
}
scheduler.deleteJob(jobKey);
}
/**
* 修改一个任务的触发时间
*
* @param triggerName 触发器名
* @param triggerGroupName 触发器组名
* @param cron 时间设置,参考quartz说明文档
*/
public void modifyJobTime(String triggerName, String triggerGroupName, String cron) {
try {
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (trigger == null) {
return;
}
String oldTime = trigger.getCronExpression();
if (!oldTime.equalsIgnoreCase(cron)) {
// 触发器
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
// 触发器名,触发器组
triggerBuilder.withIdentity(triggerName, triggerGroupName);
triggerBuilder.startNow();
// 触发器时间设定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
// 创建Trigger对象
trigger = (CronTrigger) triggerBuilder.build();
// 方式一 :修改一个任务的触发时间
scheduler.rescheduleJob(triggerKey, trigger);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 移除一个任务
*
* @param jobName 任务名
* @param jobGroupName 任务组名
* @param triggerName 触发器名
* @param triggerGroupName 触发器组名
*/
public void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
try {
TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
// 停止触发器
scheduler.pauseTrigger(triggerKey);
// 移除触发器
scheduler.unscheduleJob(triggerKey);
// 删除任务
scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 获取任务是否存在
* <p>
* STATE_BLOCKED 4 阻塞
* STATE_COMPLETE 2 完成
* STATE_ERROR 3 错误
* STATE_NONE -1 不存在
* STATE_NORMAL 0 正常
* STATE_PAUSED 1 暂停
*/
public Boolean notExists(String triggerName, String triggerGroupName) {
try {
return scheduler.getTriggerState(TriggerKey.triggerKey(triggerName, triggerGroupName)) == Trigger.TriggerState.NONE;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void startJob(Scheduler scheduler) throws SchedulerException {
// 通过JobBuilder构建JobDetail实例,JobDetail规定只能是实现Job接口的实例
// JobDetail 是具体Job实例
JobDetail jobDetail = JobBuilder.newJob(MyJob.class).withIdentity("job1", "group1").build();
// 基于表达式构建触发器
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/5 * * * * ?");
// CronTrigger表达式触发器 继承于Trigger
// TriggerBuilder 用于构建触发器实例
CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("job1", "group1")
.withSchedule(cronScheduleBuilder).build();
scheduler.scheduleJob(jobDetail, cronTrigger);
// 启动
if (!scheduler.isShutdown()) {
scheduler.start();
}
}
/**
* 添加一个定时任务
*
* @param jobName 任务名
* @param jobGroupName 任务组名
* @param triggerName 触发器名
* @param triggerGroupName 触发器组名
* @param jobClass 任务
* @param cron 时间设置,参考quartz说明文档
*/
public void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, String jobClass, String cron, Map<String, Object> params) {
try {
Class<? extends Job> aClass = (Class<? extends Job>) Class.forName(jobClass).newInstance().getClass();
// 任务名,任务组,任务执行类
JobDetail job = JobBuilder.newJob(aClass).withIdentity(jobName, jobGroupName).build();
// 任务参数
job.getJobDataMap().putAll(params);
// 触发器
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
// 触发器名,触发器组
triggerBuilder.withIdentity(triggerName, triggerGroupName);
triggerBuilder.startNow();
// 触发器时间设定
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
// 创建Trigger对象
CronTrigger trigger = (CronTrigger) triggerBuilder.build();
// 调度容器设置JobDetail和Trigger
scheduler.scheduleJob(job, trigger);
// 启动
if (!scheduler.isShutdown()) {
scheduler.start();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 以下方法把参数封装成了对象,方便传参
/**
* 添加一个定时任务
* @param task
*/
public void addJob(CronTask task) {
try {
// 创建jobDetail实例,绑定Job实现类
// 指明job的名称,所在组的名称,以及绑定job类
Class<? extends Job> jobClass = (Class<? extends Job>) (Class.forName(task.getBeanClass()).newInstance().getClass());
// 任务名称和组构成任务key
JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(task.getJobName(), task.getTypeName())
//参数
.usingJobData("parameter", task.getParameter())
.build();
//判断map参数是否有值
if (SSHValidateHelper.isNotEmptyMap(task.getParameterMap())) {
Set<String> set = task.getParameterMap().keySet();
if (SSHValidateHelper.isNotEmptyCollection(task.getParameterMap().keySet())) {
for (String key : set) {
jobDetail.getJobDataMap().put(key, task.getParameterMap().get(key));
}
}
}
// 定义调度触发规则、使用cornTrigger规则、触发器key
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(task.getJobName(), task.getTypeName()).startAt(DateBuilder.futureDate(1, DateBuilder.IntervalUnit.SECOND))
.withSchedule(CronScheduleBuilder.cronSchedule(task.getCronExpression())).startNow().build();
// 把作业和触发器注册到任务调度中
scheduler.scheduleJob(jobDetail, trigger);
// 启动
if (!scheduler.isShutdown()) {
scheduler.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取所有计划中的任务列表
*
* @return
* @throws SchedulerException
*/
public List<CronTask> getAllJob() throws SchedulerException {
GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
List<CronTask> jobList = new ArrayList<CronTask>();
for (JobKey jobKey : jobKeys) {
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
for (Trigger trigger : triggers) {
CronTask job = new CronTask();
job.setJobName(jobKey.getName());
job.setTypeName(jobKey.getGroup());
job.setDescription("触发器:" + trigger.getKey());
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
job.setTypeName(triggerState.name());
if (trigger instanceof CronTrigger) {
CronTrigger cronTrigger = (CronTrigger) trigger;
String cronExpression = cronTrigger.getCronExpression();
job.setCronExpression(cronExpression);
}
jobList.add(job);
}
}
return jobList;
}
/**
* 所有正在运行的job
*
* @return
* @throws SchedulerException
*/
public List<CronTask> getRunningJob() throws SchedulerException {
List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
List<CronTask> jobList = new ArrayList<CronTask>(executingJobs.size());
for (JobExecutionContext executingJob : executingJobs) {
CronTask job = new CronTask();
JobDetail jobDetail = executingJob.getJobDetail();
JobKey jobKey = jobDetail.getKey();
Trigger trigger = executingJob.getTrigger();
job.setJobName(jobKey.getName());
job.setTypeName(jobKey.getGroup());
job.setDescription("触发器:" + trigger.getKey());
Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
job.setJobStatus(Long.parseLong(triggerState.name()));
if (trigger instanceof CronTrigger) {
CronTrigger cronTrigger = (CronTrigger) trigger;
String cronExpression = cronTrigger.getCronExpression();
job.setCronExpression(cronExpression);
}
jobList.add(job);
}
return jobList;
}
/**
* 暂停一个job
*
* @param task
* @throws SchedulerException
*/
public void pauseJob(CronTask task) throws SchedulerException {
JobKey jobKey = JobKey.jobKey(task.getJobName(), task.getTypeName());
scheduler.pauseJob(jobKey);
}
/**
* 恢复一个job
*
* @param task
* @throws SchedulerException
*/
public void resumeJob(CronTask task) throws SchedulerException {
JobKey jobKey = JobKey.jobKey(task.getJobName(), task.getTypeName());
scheduler.resumeJob(jobKey);
}
/**
* 删除一个job
*
* @param task
* @throws SchedulerException
*/
public void deleteJob(CronTask task) throws SchedulerException {
JobKey jobKey = JobKey.jobKey(task.getJobName(), task.getTypeName());
scheduler.deleteJob(jobKey);
}
/**
* 立即执行job
*
* @param task
* @throws SchedulerException
*/
public void runJobNow(CronTask task) throws SchedulerException {
JobKey jobKey = JobKey.jobKey(task.getJobName(), task.getTypeName());
scheduler.triggerJob(jobKey);
}
/**
* 更新job时间表达式
*
* @param task
* @throws SchedulerException
*/
public void updateJobCron(CronTask task) throws SchedulerException {
TriggerKey triggerKey = TriggerKey.triggerKey(task.getJobName(), task.getTypeName());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(task.getCronExpression());
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
scheduler.rescheduleJob(triggerKey, trigger);
}
}
监听器QuartzJobListener
自定义一个监听类,Quartz的job在项目重启时,job都失效了,把每次启动的job都存放在数据库,然后项目启动时监听器读取数据库的job,然后添加job。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author: liangbl
* @Date: 2019/1/21 14:29
* @Description: 监听器
* Quartz的job在项目重启时,job都失效了,把每次启动的job都存放在数据库,然后项目启动时监听器读取数据库的job,然后添加job
*/
@Component
@Order(value = 1)
public class QuartzJobListener implements CommandLineRunner {
@Autowired
private QuartzScheduler quartzScheduler;
/**
* 初始启动quartz
* @param
*/
@Override
public void run(String... args) throws Exception {
try {
// quartzScheduler.startJob();
// 此处就不写获取数据库了,模拟一个集合遍历的数据
List<Map<String,Object>> listMap=new ArrayList<>();
Map<String, Object> map1= new HashMap<>(16);
map1.put("jobClass","com.hellowin.b2c.quartz.MyJob");
map1.put("jobName","job1");
map1.put("jobGroupName","job1");
map1.put("jobTime","0/5 * * * * ? ");
listMap.add(map1);
for (Map<String, Object> map : listMap) {
try {
quartzScheduler.addJob((String)map.get("jobName"),(String)map.get("jobGroupName"), (String)map.get("jobName"),(String)map.get("jobGroupName"),(String)map1.get("jobClass"),(String)map.get("jobTime"),new HashMap<>(16));
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("任务已经启动...");
} catch (Exception e) {
e.printStackTrace();
}
}
}
自定义定时任务类MyJob
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.text.SimpleDateFormat;
/**
* @Author: liangbl
* @Date: 2019/1/21 13:46
* @Description: 自定义定时任务类
*/
public class MyJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String jobName = jobExecutionContext.getJobDetail().getKey().toString();
System.out.println(jobName + "任务开始执行:" + dateformat.format(System.currentTimeMillis()));
// TODO 业务job1.job1
System.out.println(jobName + "任务执行完成:" + dateformat.format(System.currentTimeMillis()));
}
}