spring boot 使用quartz实现动态定时器

例子可以实现在项目启动时通过页面完成对定时任务的增删改查,并将任务配置存入数据表中,完成项目启动时开启定时任务

<quartz.version>2.2.3</quartz.version>

通过注解实例化任务工厂
@Component
public class JobFactory extends AdaptableJobFactory {
    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        //调用父类的方法
        Object jobInstance = super.createJobInstance(bundle);
        return jobInstance;
    }
}

通过注解实例化调度器
@Component
public class JobSchedulerFactoryBean extends SchedulerFactoryBean {
    @Autowired
    private JobFactory jobFactory;
    public JobSchedulerFactoryBean(){
        super.setJobFactory(jobFactory);
    }
}

任务管理类
@Service
public class QuartzManager {

    @Resource(name = "jobSchedulerFactoryBean")
    private Scheduler sched;

    /**
     * 增加一个job
     * @param jobClass 任务实现类
     * @param jobName 任务名称
     *  @param jobGroupName 任务组名
     * @param jobTime 时间表达式 (如:0/5 * * * * ? )
     */
    public void addJob(Class<? extends Job> jobClass, String jobName, String jobGroupName, String jobTime ,String jobParam) {
        try {
            //创建jobDetail实例,绑定Job实现类  
            //指明job的名称,所在组的名称,以及绑定job类
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName)//任务名称和组构成任务key
                    .build();
            jobDetail.getJobDataMap().put("param",jobParam);
            //定义调度触发规则  
            //使用cornTrigger规则 
            Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
                    //触发器key
                    .startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND)).withSchedule(CronScheduleBuilder.cronSchedule(jobTime))
                    .startNow().build();
            //把作业和触发器注册到任务调度中
            sched.scheduleJob(jobDetail, trigger);
            // 启动
            if (!sched.isShutdown()) {
                sched.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 增加一个job
     * @param jobClass  任务实现类
     * @param jobName  任务名称
     * @param jobGroupName 任务组名
     * @param jobTime  时间表达式 (这是每隔多少秒为一次任务)
     */
    public void addJob(Class<? extends Job> jobClass, String jobName, String jobGroupName, int jobTime, String jobParam) {
        addJob(jobClass, jobName, jobGroupName, jobTime, -1, jobParam);
    }

    /**
     * 增加一个job
     * @param jobClass 任务实现类
     * @param jobName  任务名称
     * @param jobGroupName 任务组名
     * @param jobTime  时间表达式 (这是每隔多少秒为一次任务)
     * @param jobTimes  运行的次数 (<0:表示不限次数)
     */
    public void addJob(Class<? extends Job> jobClass, String jobName, String jobGroupName, int jobTime, int jobTimes, String jobParam) {
        try {
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName)//任务名称和组构成任务key
                    .build();
            //使用simpleTrigger规则
            Trigger trigger = null;
            if (jobTimes < 0) {
                trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)
                        .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1).withIntervalInSeconds(jobTime)).startNow().build();
            } else {
                trigger = TriggerBuilder
                        .newTrigger()
                        .withIdentity(jobName, jobGroupName)
                        .withSchedule(
                            SimpleScheduleBuilder.repeatSecondlyForever(1).withIntervalInSeconds(jobTime).withRepeatCount(jobTimes))
                        .startNow().build();
            }
            sched.scheduleJob(jobDetail, trigger);
            if (!sched.isShutdown()) {
                sched.start();
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 修改 一个job的 时间表达式
     * @param jobName
     * @param jobGroupName
     * @param jobTime
     */
    public void updateJob(String jobName, String jobGroupName, String jobTime) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
            CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).build();
            //重启触发器
            sched.rescheduleJob(triggerKey, trigger);
            if (!sched.isShutdown()) {
                sched.start();
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除任务一个job
     * @param jobName 任务名称
     * @param jobGroupName 任务组名
     */
    public void deleteJob(String jobName, String jobGroupName) {
        try {
            sched.deleteJob(new JobKey(jobName, jobGroupName));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 暂停一个job
     * @param jobName
     * @param jobGroupName
     */
    public void pauseJob(String jobName, String jobGroupName) {
        try {
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            sched.pauseJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 恢复一个job
     * @param jobName
     * @param jobGroupName
     */
    public void resumeJob(String jobName, String jobGroupName) {
        try {
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            sched.resumeJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 立即执行一个job
     * @param jobName
     * @param jobGroupName
     */
    public void runAJobNow(String jobName, String jobGroupName) {
        try {
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            sched.triggerJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取所有计划中的任务列表
     * @return
     */
    public List<Map<String, Object>> queryAllJob() {
        List<Map<String, Object>> jobList = null;
        try {
            GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
            Set<JobKey> jobKeys = sched.getJobKeys(matcher);
            jobList = new ArrayList<Map<String, Object>>();
            for (JobKey jobKey : jobKeys) {
                List<? extends Trigger> triggers = sched.getTriggersOfJob(jobKey);
                for (Trigger trigger : triggers) {
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("jobName", jobKey.getName());
                    map.put("jobGroupName", jobKey.getGroup());
                    map.put("description", "触发器:" + trigger.getKey());
                    Trigger.TriggerState triggerState = sched.getTriggerState(trigger.getKey());
                    map.put("jobStatus", triggerState.name());
                    if (trigger instanceof CronTrigger) {
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        String cronExpression = cronTrigger.getCronExpression();
                        map.put("jobTime", cronExpression);
                    }
                    jobList.add(map);
                }
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return jobList;
    }
    /**
     * 获取所有计划中的任务列表
     * @return
     */
    public Map<String,HashMap<String, Object>> queryAllJobMap() {
        Map<String,HashMap<String, Object>> jobList = null;
        try {
            GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
            Set<JobKey> jobKeys = sched.getJobKeys(matcher);
            jobList = new HashMap<String,HashMap<String, Object>>();
            for (JobKey jobKey : jobKeys) {
                List<? extends Trigger> triggers = sched.getTriggersOfJob(jobKey);
                for (Trigger trigger : triggers) {
                    HashMap<String, Object> map = new HashMap<String, Object>();
                    map.put("jobName", jobKey.getName());
                    map.put("jobGroupName", jobKey.getGroup());
                    map.put("description", "触发器:" + trigger.getKey());
                    Trigger.TriggerState triggerState = sched.getTriggerState(trigger.getKey());
                    map.put("jobStatus", triggerState.name());
                    if (trigger instanceof CronTrigger) {
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        String cronExpression = cronTrigger.getCronExpression();
                        map.put("jobTime", cronExpression);
                    }
                    jobList.put(jobKey.getName()+","+jobKey.getGroup(),map);
                }
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return jobList;
    }

    /**
     * 获取所有正在运行的job
     * @return
     */
    public List<Map<String, Object>> queryRunJon() {
        List<Map<String, Object>> jobList = null;
        try {
            List<JobExecutionContext> executingJobs = sched.getCurrentlyExecutingJobs();
            jobList = new ArrayList<Map<String, Object>>(executingJobs.size());
            for (JobExecutionContext executingJob : executingJobs) {
                Map<String, Object> map = new HashMap<String, Object>();
                JobDetail jobDetail = executingJob.getJobDetail();
                JobKey jobKey = jobDetail.getKey();
                Trigger trigger = executingJob.getTrigger();
                map.put("jobName", jobKey.getName());
                map.put("jobGroupName", jobKey.getGroup());
                map.put("description", "触发器:" + trigger.getKey());
                Trigger.TriggerState triggerState = sched.getTriggerState(trigger.getKey());
                map.put("jobStatus", triggerState.name());
                if (trigger instanceof CronTrigger) {
                    CronTrigger cronTrigger = (CronTrigger) trigger;
                    String cronExpression = cronTrigger.getCronExpression();
                    map.put("jobTime", cronExpression);
                }
                jobList.add(map);
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return jobList;
    }
}
设置项目启动,开始定时任务框架不同需要自行更改

@Component
public class JobApplicationArguments implements ApplicationRunner {
    @Autowired
    private QuartzManager quartzManager;
    @Autowired
    private JobConfigureService jobConfigureService;
    @Override
    public void run(ApplicationArguments applicationArguments) throws Exception {
        JobConfigure jobConfigureParam = new JobConfigure();
        jobConfigureParam.setJobStatus("1");
        List<JobConfigure> jobConfigures = jobConfigureService.findList(jobConfigureParam);
        if(jobConfigures!=null){
            for(JobConfigure jobConfigure : jobConfigures){
                String className = jobConfigure.getJobClass();
                String clockStr = jobConfigure.getJobTask();
                String jobName = jobConfigure.getJobName();
                String jobGroup = jobConfigure.getJobGroup();
                String jobParam = jobConfigure.getJobParam();
                Class<? extends Job> jobTest = null;
                try {
                    jobTest = (Class<? extends Job>) Class.forName(className)
                            .newInstance().getClass();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                quartzManager.addJob(jobTest, jobName, jobGroup, clockStr, jobParam);
                System.out.println("启动"+jobName+"任务成功");
            }
        }
    }
}
定时任务配置service

/**
 * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
 */
package com.jeesite.modules.jobconfigure.service;

import com.jeesite.common.entity.Page;
import com.jeesite.common.job.quartzmanager.QuartzManager;
import com.jeesite.common.lang.StringUtils;
import com.jeesite.common.service.CrudService;
//import com.jeesite.modules.dsstrategy.entity.DsStrategy;
import com.jeesite.modules.jobconfigure.dao.JobConfigureDao;
import com.jeesite.modules.jobconfigure.entity.JobConfigure;
import org.quartz.Job;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 任务配置Service
 * @author 杨凯
 * @version 2018-05-11
 */
@Service
@Transactional(readOnly=true)
public class JobConfigureService extends CrudService<JobConfigureDao, JobConfigure> {
   private final String jobClass = "com.jeesite.common.job.quartzmanager.JobStrategy";
   @Autowired
   private QuartzManager quartzManager;
   /**
    * 获取单条数据
    * @param jobConfigure
    * @return
    */
   @Override
   public JobConfigure get(JobConfigure jobConfigure) {
      return super.get(jobConfigure);
   }
   
   /**
    * 查询分页数据
    * @param page 分页对象
    * @param jobConfigure
    * @return
    */
   @Override
   public Page<JobConfigure> findPage(Page<JobConfigure> page, JobConfigure jobConfigure) {
      return super.findPage(page, jobConfigure);
   }
   
   /**
    * 保存数据(插入或更新)
    * @param jobConfigure
    */
   @Override
   @Transactional(readOnly=false)
   public void save(JobConfigure jobConfigure) {
      Map<String, HashMap<String, Object>> currentStartJob = quartzManager
            .queryAllJobMap();
      String jobName = jobConfigure.getJobName();
      String jobTask = jobConfigure.getJobTask();
      String groupName = jobConfigure.getJobGroup();
      String jobStatus = jobConfigure.getJobStatus();
      String jobClassName = jobConfigure.getJobClass();
      String jobParam = jobConfigure.getJobParam();
      Class<? extends Job> jobClass = null;

      try {
         jobClass = (Class<? extends Job>) Class.forName(jobClassName)
               .newInstance().getClass();
      } catch (Exception e) {
         // TODO Auto-generated catch block
         jobConfigure.setJobStatus("0");
         e.printStackTrace();
      }
      Map<String, Object> currentJob = currentStartJob.get(jobName + ","
            + groupName);
      String id = jobConfigure.getId();
      // id为空则为新增任务
      if (StringUtils.isEmpty(id)) {
         setJob(jobName, jobTask, groupName, jobStatus, jobParam, jobClass,
               currentJob);
      } else {
         updateJob(currentStartJob, jobName, jobTask, groupName, jobStatus,
               jobParam, jobClass, id);
      }
      super.save(jobConfigure);
   }
   
   /**
    * 更新状态
    * @param jobConfigure
    */
   @Override
   @Transactional(readOnly=false)
   public void updateStatus(JobConfigure jobConfigure) {
      super.updateStatus(jobConfigure);
   }
   
   /**
    * 删除数据
    * @param jobConfigure
    */
   @Override
   @Transactional(readOnly=false)
   public void delete(JobConfigure jobConfigure) {
      Map<String, HashMap<String, Object>> currentStartJob = quartzManager
            .queryAllJobMap();
      String jobName = jobConfigure.getJobName();
      String groupName = jobConfigure.getJobGroup();
      String jobClassName = jobConfigure.getJobClass();
      Class<? extends Job> jobClass = null;
      try {
         jobClass = (Class<? extends Job>) Class.forName(jobClassName)
               .newInstance().getClass();
      } catch (Exception e) {
         // TODO Auto-generated catch block
         jobConfigure.setJobStatus("0");
         e.printStackTrace();
      }
      Map<String, Object> currentJob = currentStartJob.get(jobName + ","
            + groupName);
      if (currentJob != null) {
         quartzManager.deleteJob(jobName, groupName);
      }
      super.delete(jobConfigure);
   }
   private void setJob(String jobName, String jobTask, String groupName,
                  String jobStatus, String jobParam, Class<? extends Job> jobClass,
                  Map<String, Object> currentJob) {
      // 如果状态为1则证明是设定为启动状态
      if ("1".equals(jobStatus)) {
         // 如果当前任务中不存在该任务则添加任务
         if (currentJob == null) {
            quartzManager.addJob(jobClass, jobName, groupName, jobTask,
                  jobParam);
         } else {
            // 删除并重新设定触发器
            quartzManager.deleteJob(jobName, groupName);
            quartzManager.addJob(jobClass, jobName, groupName, jobTask,
                  jobParam);
         }
      } else {
         if (currentJob != null) {
            quartzManager.deleteJob(jobName, groupName);
         }
      }
   }
   private void updateJob(
         Map<String, HashMap<String, Object>> currentStartJob,
         String jobName, String jobTask, String groupName, String jobStatus,
         String jobParam, Class<? extends Job> jobClass, String id) {
      JobConfigure oldJobConfigure = get(id);
      if (oldJobConfigure != null) {
         String oldJobName = oldJobConfigure.getJobName();
         String oldJobGroup = oldJobConfigure.getJobGroup();
         Map<String, Object> oldJob = currentStartJob.get(oldJobName + ","
               + oldJobGroup);
         if ("1".equals(jobStatus)) {
            // 如果当前任务中不存在该任务则添加任务
            if (oldJob == null) {
               quartzManager.addJob(jobClass, jobName, groupName, jobTask,
                     jobParam);
            } else {
               // 删除旧任务添加新任务
               quartzManager.deleteJob(oldJobName, oldJobGroup);
               quartzManager.addJob(jobClass, jobName, groupName, jobTask,
                     jobParam);
            }
         } else {
            if (oldJob != null) {
               quartzManager.deleteJob(oldJobName, oldJobGroup);
            }
         }
      }
   }
// /**
//  * 根据策略保存任务信息
//  *
//  * @param strategy
//  */
// @Transactional(readOnly = false)
// public void saveJob(DsStrategy strategy) {
//    // 先判断是否存在任务
//    //JobConfigure jobConfigure = null;
////      List<JobConfigure> list = jobConfigureDao.findByProperty("jobParam",
////            strategy.getId());
//    JobConfigure jobConfigure = new JobConfigure();
//    jobConfigure.setJobParam(strategy.getId());
//    List<JobConfigure> list = super.findList(jobConfigure);
//    if (list != null && list.size() > 0) {
//       jobConfigure = list.get(0);
//       jobConfigure.setJobGroup(strategy.getSendType()); // 发送或接收
//       jobConfigure.setJobTask(strategy.getCron()); // 先写固定值
//       jobConfigure.setJobStatus(strategy.getState());
//       this.save(jobConfigure);
//    } else {
//       jobConfigure = new JobConfigure();
//       jobConfigure.setJobClass(jobClass);
//       jobConfigure.setJobParam(strategy.getId());
//       jobConfigure.setJobName(strategy.getId());
//       jobConfigure.setJobGroup(strategy.getSendType()); // 发送或接收
//       jobConfigure.setJobTask(strategy.getCron()); // 先写固定值
//       jobConfigure.setJobStatus(strategy.getState());
//       this.save(jobConfigure);
//    }
// }
   // 根据策略ID删除并取消任务
   @Transactional(readOnly = false)
   public void deleteByStrategyId(String id) {
      JobConfigure jobConfigure = new JobConfigure();
      jobConfigure.setJobParam(id);
      List<JobConfigure> list = super.findList(jobConfigure);
      for (JobConfigure jobConfigureTemp : list) {
         this.delete(jobConfigureTemp);
      }
   }
}
任务配置实体
public class JobConfigure extends DataEntity<JobConfigure> {
   
   private static final long serialVersionUID = 1L;
   private String jobClass;      // 任务类路径
   private String jobParam;      // 任务传参
   private String jobName;       // 任务名称
   private String jobGroup;      // 任务组名称
   private String jobTask;       // 任务定时字符串
   private String jobStatus;     // job_status
   
   public JobConfigure() {
      this(null);
   }

   public JobConfigure(String id){
      super(id);
   }
   
   @NotBlank(message="任务类路径不能为空")
   @Length(min=0, max=500, message="任务类路径长度不能超过 500 个字符")
   public String getJobClass() {
      return jobClass;
   }

   public void setJobClass(String jobClass) {
      this.jobClass = jobClass;
   }
   
   @NotBlank(message="任务传参不能为空")
   @Length(min=0, max=3000, message="任务传参长度不能超过 3000 个字符")
   public String getJobParam() {
      return jobParam;
   }

   public void setJobParam(String jobParam) {
      this.jobParam = jobParam;
   }
   
   @NotBlank(message="任务名称不能为空")
   @Length(min=0, max=300, message="任务名称长度不能超过 300 个字符")
   public String getJobName() {
      return jobName;
   }

   public void setJobName(String jobName) {
      this.jobName = jobName;
   }
   
// @NotBlank(message="任务组名称不能为空")
   @Length(min=0, max=20, message="任务组名称长度不能超过 20 个字符")
   public String getJobGroup() {
      return jobGroup;
   }

   public void setJobGroup(String jobGroup) {
      this.jobGroup = jobGroup;
   }
   
   @NotBlank(message="任务定时字符串不能为空")
   @Length(min=0, max=3000, message="任务定时字符串长度不能超过 3000 个字符")
   public String getJobTask() {
      return jobTask;
   }

   public void setJobTask(String jobTask) {
      this.jobTask = jobTask;
   }
   
   @NotBlank(message="job_status不能为空")
   @Length(min=0, max=10, message="job_status长度不能超过 10 个字符")
   public String getJobStatus() {
      return jobStatus;
   }

   public void setJobStatus(String jobStatus) {
      this.jobStatus = jobStatus;
   }
   测试任务类

public class TestJobParam implements Job {
   private JobConfigureService jobConfigureService = SpringContextHolder.getBean(JobConfigureService.class);
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        Object param = jobExecutionContext.getJobDetail().getJobDataMap().get("param");
        System.out.println(jobConfigureService.findList(new JobConfigure()));
        System.out.println(String.valueOf(param));
    }
}

动态管理页面截图

spring boot 使用quartz实现动态定时器