• Springboot集成Quartz


    Quartz 是一个完全由 Java 编写的开源作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制。该文章不过多介绍Quartz的概念,主要做一个封装的记录。

    功能点

    1. 添加CRON、固定间隔定时
    2. 修改定时的触发器
    3. 修改定时参数
    4. 暂停定时
    5. 启动暂停的定时
    6. 获取所有定时
    7. 启动所有定时
    8. 停止定时

    0. 创建项目

    创建一个简单的SpringBoot项目,pom如下:

    
    
        4.0.0
        
            org.springframework.boot
            spring-boot-starter-parent
            2.6.1
             
        
        org.demo
        quartz
        0.0.1-SNAPSHOT
        quartz
        Demo project for Spring Boot
        
            11
        
        
            
                org.springframework.boot
                spring-boot-starter
            
    
            
                org.springframework.boot
                spring-boot-starter-test
                test
            
    
            
                org.springframework.boot
                spring-boot-starter-quartz
            
    
            
                org.projectlombok
                lombok
            
        
    
        
            
                
                    org.springframework.boot
                    spring-boot-maven-plugin
                
            
        
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    1. 定时类型

    Quartz可以通过org.quartz.Trigger.class去拓展定时类型的,目前需求需要支持CRON和固定间隔两种定时类型,后期需要支持跳过节假日、周一~周五、周末等需求,所以需要让定时类型支持拓展。

    1.1定时类型

    package org.demo.quartz.mode;
    
    /**
     * @author Xiaohan.Yuan
     * @version 1.0.0
     * @ClassName TimingTriggerType.java
     * @Description 定时类型触发器类型
     * @createTime 2021年12月16日
     */
    public enum TriggerType {
        CRON("标准CRON支持"),
        INTERVAL_MILLISECOND("固定间隔毫秒"),
        INTERVAL_SECOND("固定间隔秒"),
        INTERVAL_MINUTE("固定间隔分钟"),
        INTERVAL_HOUR("固定间隔小时"),
        WEEKDAYS("工作日,跳过节假日"),
        HOLIDAY("节假日")
        ;
    
    
        private String describe;
    
        TriggerType(String describe) {
            this.describe = describe;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    1.2 构建定时任务的抽象类

    我们需要构建不同的定时类型,不同的定时类型需要的参数也是不同的,因此我们需要抽象出定时的公用参数,将不同的参数多态实现。

    package org.demo.quartz.mode;
    
    import lombok.Getter;
    import lombok.Setter;
    import org.demo.quartz.task.QuartzTaskJob;
    
    import java.util.Map;
    
    /**
     * @author Xiaohan.Yuan
     * @version 1.0.0
     * @ClassName TimingModel.java
     * @Description 构建定时的model
     * @createTime 2021年12月16日
     */
    @Getter
    @Setter
    public class TimingModel {
        /**
         * 该定时的任务处理器
         */
        private Class taskClass;
    
        /**
         * 任务名
         */
        private String taskName;
        /**
         * 任务组名
         * */
        private String groupName;
    
        /**
         * 任务描述
         * */
        private String description;
    
    
        /**
         * 任务类型
         */
        private TriggerType type;
    
    
        /**
         * 任务参数,可在具体的QuartzTaskJob实现中获取这些参数
         * */
        private Map param;
    
        /**
         * 任务状态
         * */
        private String taskStatus;
    
        public TimingModel(Class taskClass, String taskName, String groupName, String description, TriggerType type, Map param) {
            this.taskClass = taskClass;
            this.taskName = taskName;
            this.groupName = groupName;
            this.description = description;
            this.type = type;
            this.param = param;
        }
    
        public TimingModel(Class taskClass, String taskName, String groupName, String description, TriggerType type) {
            this.taskClass = taskClass;
            this.taskName = taskName;
            this.groupName = groupName;
            this.description = description;
            this.type = type;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    1.3 用以构建CRON定时任务

    package org.demo.quartz.mode;
    
    import lombok.Getter;
    import lombok.Setter;
    import org.demo.quartz.task.QuartzTaskJob;
    
    import java.util.Map;
    
    /**
     * @author Xiaohan.Yuan
     * @version 1.0.0
     * @ClassName CronTimingModel.java
     * @Description cron触发器model
     * @createTime 2021年12月16日
     */
    @Getter
    @Setter
    public class CronTimingModel extends TimingModel{
        /**
         * cron表达式
         * */
        private String cronExpression;
    
        public CronTimingModel(Class taskClass, String taskName, String groupName, String description, Map param,String cronExpression) {
            super(taskClass, taskName, groupName, description, TriggerType.CRON, param);
            this.cronExpression = cronExpression;
        }
    
        public CronTimingModel(Class taskClass, String taskName, String groupName, String description,String cronExpression) {
            super(taskClass, taskName, groupName, description, TriggerType.CRON);
            this.cronExpression = cronExpression;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    1.4 用以构建固定间隔定时任务

    package org.demo.quartz.mode;
    
    import lombok.Getter;
    import lombok.Setter;
    import org.demo.quartz.exception.TimingException;
    import org.demo.quartz.task.QuartzTaskJob;
    
    import java.util.Map;
    
    /**
     * @author Xiaohan.Yuan
     * @version 1.0.0
     * @ClassName IntervalTimingMode.java
     * @Description
     * @createTime 2021年12月16日
     */
    @Getter
    @Setter
    public class IntervalTimingMode extends TimingModel {
    
        /**
         * 事件间隔,根据TriggerType确定单位,除了数值为毫秒,该数值必须在-2^32~2^31   (-2147483648 ~ 2147483647)
         * */
        private Long interval;
    
        /**
         * 重复次数,会执行该数值+1次,为空无限重复
         * */
        private Integer repeatCount;
    
        public IntervalTimingMode(Class taskClass, String taskName, String groupName, String description, TriggerType type, Map param, Long interval,Integer repeatCount) {
            super(taskClass, taskName, groupName, description, type, param);
            if (type != TriggerType.INTERVAL_MILLISECOND){
                if (interval<(-2^32)||interval>(2^31)){
                    throw new TimingException("interval超出范围,除了类型为INTERVAL_MILLISECOND的数据间隔定时的interval范围必须在-2^32~2^31   (-2147483648 ~ 2147483647)");
                }
            }
            this.interval = interval;
            this.repeatCount = repeatCount;
        }
    
        public IntervalTimingMode(Class taskClass, String taskName, String groupName, String description, TriggerType type, Long interval,Integer repeatCount) {
            super(taskClass, taskName, groupName, description, type);
            if (type != TriggerType.INTERVAL_MILLISECOND){
                if (interval<(-2^32)||interval>(2^31)){
                    throw new TimingException("interval超出范围,除了类型为INTERVAL_MILLISECOND的数据间隔定时的interval范围必须在-2^32~2^31   (-2147483648 ~ 2147483647)");
                }
            }
            this.interval = interval;
            this.repeatCount = repeatCount;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    2.抽象任务类

    package org.demo.quartz.task;
    
    import org.quartz.Job;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    
    /**
     * @author Xiaohan.Yuan
     * @version 1.0.0
     * @ClassName QuartzTaskJob.java
     * @Description
     * @createTime 2021年12月16日
     */
    public interface QuartzTaskJob extends Job {
        @Override
        void execute(JobExecutionContext context) throws JobExecutionException;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2.1 实现一个测试任务

    package org.demo.quartz.task;
    
    import lombok.extern.slf4j.Slf4j;
    import org.quartz.JobDataMap;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.quartz.SimpleTrigger;
    import org.springframework.stereotype.Component;
    
    @Component
    @Slf4j
    public class TestQuartz implements QuartzTaskJob {
    
        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            // 获取参数
            JobDataMap jobDataMap = context.getTrigger().getJobDataMap();
            // 获取任务名
            String name = context.getJobDetail().getJobBuilder().build().getKey().getName();
            // 获取任务分组
            String group = context.getJobDetail().getJobBuilder().build().getKey().getGroup();
            // 获取任务描述
            String description = context.getJobDetail().getDescription();
            if (context.getTrigger() instanceof SimpleTrigger){
                // 运行次数
                System.out.println(((SimpleTrigger)context.getTrigger()).getTimesTriggered());
            }
            log.info("----------------------" +
                    "
    任务组:{}
    任务名:{}
    任务描述:{}
    获取参数paramKey:{}
    " +
                    "----------------------"
                    ,name,group,description,jobDataMap.getString("paramKey"));
    
            try {
    //            QuartzJobManager.getInstance().jobdelete(this.getClass().getSimpleName(),"ah");//执行完此任务就删除自己
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    3. 构建触发器的不同实现

    3.1 抽象触发器实现

    package org.demo.quartz.trigger;
    
    import org.demo.quartz.mode.TriggerType;
    import org.demo.quartz.mode.TimingModel;
    import org.quartz.Trigger;
    
    /**
     * @author Xiaohan.Yuan
     * @version 1.0.0
     * @ClassName TriggerHandler.java
     * @Description 触发器工厂
     * @createTime 2021年12月16日
     */
    public interface ITriggerFactory {
    
        /**
         * 判断是否为该类型的触发器
         *
         * @param triggerType 触发器类型
         * @return boolean 如果是该类型的触发器返回true 否则返回false
         * @author YuanXiaohan
         * @date 2021/12/16 2:33 下午
         */
        public boolean check(TriggerType triggerType);
    
    
        public Trigger build(TimingModel timingModel);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    3.2 CRON触发器

    package org.demo.quartz.trigger.factory;
    
    import org.demo.quartz.exception.TimingException;
    import org.demo.quartz.mode.CronTimingModel;
    import org.demo.quartz.mode.TriggerType;
    import org.demo.quartz.mode.TimingModel;
    import org.demo.quartz.trigger.ITriggerFactory;
    import org.quartz.CronScheduleBuilder;
    import org.quartz.Trigger;
    import org.quartz.TriggerBuilder;
    import org.springframework.stereotype.Component;
    
    /**
     * @author Xiaohan.Yuan
     * @version 1.0.0
     * @ClassName CronTrigger.java
     * @Description
     * @createTime 2021年12月16日
     */
    @Component
    public class CronTrigger implements ITriggerFactory {
        @Override
        public boolean check(TriggerType triggerType) {
            return triggerType==TriggerType.CRON;
        }
    
        @Override
        public Trigger build(TimingModel timingModel) {
            if (!(timingModel instanceof CronTimingModel)){
                throw new TimingException("构建类型为CRON定时必须传入CronTimingModel.class的实现类");
            }
            //按新的cronExpression表达式构建一个新的trigger
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(((CronTimingModel) timingModel).getCronExpression());
            return TriggerBuilder.newTrigger().withIdentity(timingModel.getTaskName(), timingModel.getTaskName())
                    .withSchedule(scheduleBuilder).build();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    3.3 固定间隔触发器

    package org.demo.quartz.trigger.factory;
    
    import org.demo.quartz.exception.TimingException;
    import org.demo.quartz.mode.IntervalTimingMode;
    import org.demo.quartz.mode.TimingModel;
    import org.demo.quartz.mode.TriggerType;
    import org.demo.quartz.trigger.ITriggerFactory;
    import org.quartz.SimpleScheduleBuilder;
    import org.quartz.Trigger;
    import org.quartz.TriggerBuilder;
    import org.springframework.stereotype.Component;
    
    /**
     * @author Xiaohan.Yuan
     * @version 1.0.0
     * @ClassName IntervalTrigger.java
     * @Description
     * @createTime 2021年12月16日
     */
    @Component
    public class IntervalTrigger implements ITriggerFactory {
        @Override
        public boolean check(TriggerType triggerType) {
            return triggerType == TriggerType.INTERVAL_MINUTE || triggerType == TriggerType.INTERVAL_SECOND || triggerType == TriggerType.INTERVAL_MILLISECOND||triggerType == TriggerType.INTERVAL_HOUR;
        }
    
        @Override
        public Trigger build(TimingModel timingModel) {
            if (!(timingModel instanceof IntervalTimingMode)){
                throw new TimingException("构建类型为INTERVAL定时必须传入IntervalTimingMode.class的实现类");
            }
            //创建触发器
            SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule();
            Long interval = ((IntervalTimingMode) timingModel).getInterval();
            Integer repeatCount = ((IntervalTimingMode) timingModel).getRepeatCount();
            switch (timingModel.getType()){
                case INTERVAL_MINUTE:
                    simpleScheduleBuilder.withIntervalInMinutes(Math.toIntExact(interval));
                    break;
                case INTERVAL_HOUR:
                    simpleScheduleBuilder.withIntervalInHours(Math.toIntExact(interval));
                    break;
                case INTERVAL_SECOND:
                    simpleScheduleBuilder.withIntervalInSeconds(Math.toIntExact(interval));
                    break;
                case INTERVAL_MILLISECOND:
                    simpleScheduleBuilder.withIntervalInMilliseconds(interval);
                    break;
            }
            if (repeatCount==null){
                // 无限重复
                simpleScheduleBuilder.repeatForever();
            }else {
                simpleScheduleBuilder.withRepeatCount(repeatCount);
            }
            return TriggerBuilder.newTrigger().withIdentity(timingModel.getTaskName(), timingModel.getTaskName())
                    .withSchedule(simpleScheduleBuilder).build();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    3.4 构建触发器工厂

    package org.demo.quartz.trigger;
    
    import org.demo.quartz.mode.TimingModel;
    import org.quartz.Trigger;
    import org.springframework.stereotype.Component;
    
    import java.util.List;
    
    /**
     * @author Xiaohan.Yuan
     * @version 1.0.0
     * @ClassName TriggerManager.java
     * @Description 触发器管理器, 用来生成触发器
     * @createTime 2021年12月16日
     */
    @Component
    public class TriggerManager {
        private final List triggerFactories;
    
        public TriggerManager(List triggerFactories) {
            this.triggerFactories = triggerFactories;
        }
    
        /**
         * 生成对应的触发器
         *
         * @param timingModel 触发器model
         * @return org.quartz.Trigger
         * @author YuanXiaohan
         * @date 2021/12/16 2:53 下午
         */
        public Trigger build(TimingModel timingModel) {
            for (ITriggerFactory triggerFactory : triggerFactories) {
                if (triggerFactory.check(timingModel.getType())) {
                    return triggerFactory.build(timingModel);
                }
            }
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    3. 构建定时管理类

    该方法包含:

    1. 添加定时

    2. 更新定时触发器

    3. 更新任务参数

    4. 删除任务

    5. 暂停任务

    6. 将暂停的任务恢复执行

    7. 启动所有任务

    8. 关闭定时任务

    9. 获取所有任务

      package org.demo.quartz;

      import lombok.extern.slf4j.Slf4j;
      import org.demo.quartz.mode.CronTimingModel;
      import org.demo.quartz.mode.TimingModel;
      import org.demo.quartz.trigger.TriggerManager;
      import org.demo.quartz.exception.TimingException;
      import org.quartz.*;
      import org.quartz.impl.matchers.GroupMatcher;
      import org.springframework.context.annotation.Configuration;

      import java.lang.reflect.InvocationTargetException;
      import java.util.*;

      /**

      • @author Xiaohan.Yuan

      • @version 1.0.0

      • @ClassName QuartzTaskManager.java

      • @Description

      • @createTime 2021年12月16日
        */
        @Configuration
        @Slf4j
        public class QuartzTaskManager {

        private final Scheduler scheduler;

        private final Boolean initStatus;

        private final TriggerManager triggerManager;

        private static QuartzTaskManager taskManager;

        public QuartzTaskManager(Scheduler scheduler, TriggerManager triggerManager) {
        this.scheduler = scheduler;
        taskManager = this;
        boolean status = true;
        try {
        // 启动调度器
        scheduler.start();
        } catch (SchedulerException e) {
        log.error(“定时器调度器启动失败,定时器不可用!”, e);
        status = false;
        }
        initStatus = status;
        this.triggerManager = triggerManager;
        }

        public static QuartzTaskManager getInstance(){
        return taskManager;
        }

        /**

        • 添加定时任务

        • @param timingModel 任务model

        • @author YuanXiaohan

        • @date 2021/12/16 3:09 下午
          */
          public void addTask(TimingModel timingModel) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, SchedulerException {
          checkTimingInit();
          // 构建任务信息
          JobDetail jobDetail = JobBuilder.newJob(timingModel.getTaskClass().getDeclaredConstructor().newInstance().getClass())
          .withDescription(timingModel.getDescription())
          .withIdentity(timingModel.getTaskName(), timingModel.getGroupName())
          .build();

          // 构建触发器
          Trigger trigger = triggerManager.build(timingModel);
          // 将任务参数放入触发器中
          if (timingModel.getParam() != null && !timingModel.getParam().isEmpty()) {
          trigger.getJobDataMap().putAll(timingModel.getParam());
          }
          // 启动任务
          scheduler.scheduleJob(jobDetail, trigger);
          }

        /**

        • 更新任务,任务的标示(由taskName和groupName组成)不变,任务的触发器(触发频率)发生变化

        • @param timingModel 任务model

        • @author YuanXiaohan

        • @date 2021/12/16 3:15 下午
          */
          public void updateTask(TimingModel timingModel) throws SchedulerException {
          // 获取到任务
          TriggerKey triggerKey = TriggerKey.triggerKey(timingModel.getTaskName(), timingModel.getGroupName());

          // 构建触发器
          Trigger trigger = triggerManager.build(timingModel);
          // 将任务参数放入触发器中
          if (timingModel.getParam() != null && !timingModel.getParam().isEmpty()) {
          trigger.getJobDataMap().putAll(timingModel.getParam());
          }
          // 将新的触发器绑定到任务标示上重新执行
          scheduler.rescheduleJob(triggerKey, trigger);
          }

        /**

        • 更新任务参数

        • @param taskName 任务名

        • @param groupName 任务组名

        • @param param 参数

        • @author YuanXiaohan

        • @date 2021/12/16 3:20 下午
          */
          public void updateTask(String taskName, String groupName, Map param) throws SchedulerException {
          // 获取到任务
          TriggerKey triggerKey = TriggerKey.triggerKey(taskName, groupName);
          Trigger trigger = scheduler.getTrigger(triggerKey);

          //修改参数
          trigger.getJobDataMap().putAll(param);

          // 将新的触发器绑定到任务标示上重新执行
          scheduler.rescheduleJob(triggerKey, trigger);
          }

        /**

        • 删除任务
        • @param taskName 任务名
        • @param groupName 任务组
        • @author YuanXiaohan
        • @date 2021/12/16 3:23 下午
          */
          public void deleteTask(String taskName, String groupName) throws SchedulerException {
          // 暂停任务对应的触发器
          scheduler.pauseTrigger(TriggerKey.triggerKey(taskName, groupName));
          // 删除任务对应的触发器
          scheduler.unscheduleJob(TriggerKey.triggerKey(taskName, groupName));
          // 删除任务
          scheduler.deleteJob(JobKey.jobKey(taskName, groupName));
          }

        /**

        • 暂停任务
        • @param taskName 添加任务时timingMode中的taskName
        • @param groupName 添加任务时timingMode中的groupName
        • @author YuanXiaohan
        • @date 2021/12/16 3:11 下午
          */
          public void pauseTask(String taskName, String groupName) throws SchedulerException {
          scheduler.pauseJob(JobKey.jobKey(taskName, groupName));
          }

        /**

        • 将暂停的任务恢复执行
        • @param taskName 添加任务时timingMode中的taskName
        • @param groupName 添加任务时timingMode中的groupName
        • @author YuanXiaohan
        • @date 2021/12/16 3:13 下午
          */
          public void resumeTask(String taskName, String groupName) throws SchedulerException {
          scheduler.resumeJob(JobKey.jobKey(taskName, groupName));
          }

        /**

        • 启动所有任务
        • @author YuanXiaohan
        • @date 2021/12/16 3:25 下午
          */
          public void startAllTasks() {
          try {
          scheduler.start();
          } catch (Exception e) {
          throw new RuntimeException(e);
          }
          }

        /**

        • 关闭定时任务,回收所有的触发器资源
        • @author YuanXiaohan
        • @date 2021/12/16 3:26 下午
          */
          public void shutdownAllTasks() {
          try {
          if (!scheduler.isShutdown()) {
          scheduler.shutdown();
          }
          } catch (Exception e) {
          throw new RuntimeException(e);
          }
          }

        /**

        • 获取所有的任务,暂时无法获取到任务执行类和任务描述
        • @return java.util.List
        • @author YuanXiaohan
        • @date 2021/12/16 3:37 下午
          */
          public List getTaskList() throws SchedulerException {
          GroupMatcher matcher = GroupMatcher.anyJobGroup();
          Set jobKeys = scheduler.getJobKeys(matcher);
          List taskList = new ArrayList<>();
          for (JobKey jobKey : jobKeys) {
          List triggers = scheduler.getTriggersOfJob(jobKey);
          for (Trigger trigger : triggers) {
          TimingModel timingModel;
          if (trigger instanceof CronTrigger) {
          timingModel = new CronTimingModel(null, jobKey.getName(), jobKey.getGroup(), null, ((CronTrigger) trigger).getCronExpression());
          timingModel.setTaskStatus(scheduler.getTriggerState(trigger.getKey()).name());
          taskList.add(timingModel);
          } else {
          log.warn(“name:{},group:{}的定时任务类型未知,请拓展QuartzTaskManager.getTaskList的任务类型解析”, jobKey.getName(), jobKey.getGroup());
          }
          }
          }
          return taskList;
          }

        /**

        • 校验定时调度器是否初始化完成
        • @author YuanXiaohan
        • @date 2021/12/16 2:28 下午
          */
          private void checkTimingInit() {
          if (!initStatus) {
          throw new TimingException(“定时器未初始化,添加定时器失败!”);
          }
          }

      }

    4. Quartz注入到SpringBoot

    package org.demo.quartz.config;
    
    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 Xiaohan.Yuan
     * @version 1.0.0
     * @ClassName TaskJobFactory.java
     * @Description 将Quartz注入springboot
     * @createTime 2021年12月16日
     */
    
    @Component
    public class TaskJobFactory extends AdaptableJobFactory {
        private final AutowireCapableBeanFactory capableBeanFactory;
    
        public TaskJobFactory(AutowireCapableBeanFactory capableBeanFactory) {
            this.capableBeanFactory = capableBeanFactory;
        }
    
        @Override
        protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
            //调用父类的方法
            Object jobInstance = super.createJobInstance(bundle);
            //进行注入
            capableBeanFactory.autowireBean(jobInstance);
            return jobInstance;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    5. 执行

    package org.demo;
    
    import org.demo.quartz.QuartzTaskManager;
    import org.demo.quartz.mode.CronTimingModel;
    import org.demo.quartz.mode.IntervalTimingMode;
    import org.demo.quartz.mode.TriggerType;
    import org.demo.quartz.task.TestQuartz;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    import java.util.HashMap;
    
    @SpringBootApplication
    public class QuartzApplication implements CommandLineRunner {
    
        public static void main(String[] args) {
            SpringApplication.run(QuartzApplication.class, args);
        }
    
        @Override
        public void run(String... args) throws Exception {
            //构建CRON定时
            //CronTimingModel cronTimingModel = new CronTimingModel(TestQuartz.class, "测试名", "测试组", "测试描述", "*/1 * * * * ?");
            // 构建固定间隔定时
            IntervalTimingMode intervalTimingMode = new IntervalTimingMode(TestQuartz.class, "测试名", "测试组", "测试描述", TriggerType.INTERVAL_SECOND, 5L,null);
            HashMap param = new HashMap<>();
            param.put("paramKey","获取到参数了");
            intervalTimingMode.setParam(param);
            QuartzTaskManager.getInstance().addTask(intervalTimingMode);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    5.1 执行结果

      .   ____          _            __ _ _
     /\ / ___'_ __ _ _(_)_ __  __ _    
    
    • 1
    • 2

    ( ( )___ | '_ | '| | ’ / ` |
    / )| |)| | | | | || (| | ) ) ) )
    ’ |
    | .__|| ||| |, | / / / /
    =========|
    |==============|
    /=///_/
    :: Spring Boot :: (v2.6.1)

    2021-12-16 18:46:55.763  INFO 46460 --- [           main] org.demo.QuartzApplication               : Starting QuartzApplication using Java 11.0.11 on xiaohandeiMac.local with PID 46460 (/Users/xiaohan/IdeaProjects/demo-quartz/target/classes started by xiaohan in /Users/xiaohan/IdeaProjects/demo-quartz)
    2021-12-16 18:46:55.764  INFO 46460 --- [           main] org.demo.QuartzApplication               : No active profile set, falling back to default profiles: default
    2021-12-16 18:46:56.089  INFO 46460 --- [           main] org.quartz.impl.StdSchedulerFactory      : Using default implementation for ThreadExecutor
    2021-12-16 18:46:56.095  INFO 46460 --- [           main] org.quartz.core.SchedulerSignalerImpl    : Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
    2021-12-16 18:46:56.095  INFO 46460 --- [           main] org.quartz.core.QuartzScheduler          : Quartz Scheduler v.2.3.2 created.
    2021-12-16 18:46:56.096  INFO 46460 --- [           main] org.quartz.simpl.RAMJobStore             : RAMJobStore initialized.
    2021-12-16 18:46:56.096  INFO 46460 --- [           main] org.quartz.core.QuartzScheduler          : Scheduler meta-data: Quartz Scheduler (v2.3.2) 'quartzScheduler' with instanceId 'NON_CLUSTERED'
      Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
      NOT STARTED.
      Currently in standby mode.
      Number of jobs executed: 0
      Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
      Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
    
    2021-12-16 18:46:56.096  INFO 46460 --- [           main] org.quartz.impl.StdSchedulerFactory      : Quartz scheduler 'quartzScheduler' initialized from an externally provided properties instance.
    2021-12-16 18:46:56.096  INFO 46460 --- [           main] org.quartz.impl.StdSchedulerFactory      : Quartz scheduler version: 2.3.2
    2021-12-16 18:46:56.096  INFO 46460 --- [           main] org.quartz.core.QuartzScheduler          : JobFactory set to: org.springframework.scheduling.quartz.SpringBeanJobFactory@2d6aca33
    2021-12-16 18:46:56.099  INFO 46460 --- [           main] org.quartz.core.QuartzScheduler          : Scheduler quartzScheduler_$_NON_CLUSTERED started.
    2021-12-16 18:46:56.147  INFO 46460 --- [           main] org.demo.QuartzApplication               : Started QuartzApplication in 0.589 seconds (JVM running for 6.058)
    1
    2021-12-16 18:46:56.156  INFO 46460 --- [eduler_Worker-1] org.demo.quartz.task.TestQuartz          : ----------------------
    任务组:测试名
    任务名:测试组
    任务描述:测试描述
    获取参数paramKey:获取到参数了
    ----------------------
    2
    2021-12-16 18:47:01.155  INFO 46460 --- [eduler_Worker-2] org.demo.quartz.task.TestQuartz          : ----------------------
    任务组:测试名
    任务名:测试组
    任务描述:测试描述
    获取参数paramKey:获取到参数了
    ----------------------
    3
    2021-12-16 18:47:06.151  INFO 46460 --- [eduler_Worker-3] org.demo.quartz.task.TestQuartz          : ----------------------
    任务组:测试名
    任务名:测试组
    任务描述:测试描述
    获取参数paramKey:获取到参数了
    ----------------------
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    源码

    Gitee

  • 相关阅读:
    前端调式的一般方法
    HarmonyOS ArkUI滚动类组件-Scroll、Scroller
    一款C#开发的窗口文本提取开源软件
    【毕业设计】基于YOLO实现的口罩佩戴检测 - python opemcv 深度学习
    信号弹图像立体匹配算法研究
    [附源码]java毕业设计学生宿舍管理系统
    【nodejs秒杀】expressJWT req.body : undefined和 expressJWT is not a function 解决方法
    将 RDBMS 恐龙迁移到云端
    在 IDEA 里下个五子棋不过分吧?
    《深入理解计算机系统》(2):虚拟内存
  • 原文地址:https://blog.csdn.net/segegefe/article/details/126597006