SpringBoot实现quartz定时任务可视化管理功能


Posted in Java/Android onAugust 30, 2021

前言

在实际框架或产品开发过程中,springboot中集成quarzt方式基本是以job和trigger的bean对象方式直接硬编码完成的,例如以下代码示例。对于系统内定义的所有定时任务类型,具体执行类,执行策略,运行状态都没有一个动态全局的管理,所有决定将quartz做成可视化配置管理,便于统一管理,也降低了使用门槛,只需要关心job类的实现即可

@Bean
    public JobDetail SMSJobDetail() {
        return JobBuilder.newJob(SMSJob.class).withIdentity("SMSJob").storeDurably().build();
    }

    // 把jobDetail注册到trigger上去
    @Bean
    public Trigger myJobTrigger() {
        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(1).repeatForever();

        return TriggerBuilder.newTrigger()
                .forJob(SMSJobDetail())
                .withIdentity("myJobTrigger")
                .withSchedule(scheduleBuilder)
                .build();
    }

表结构

用于存储quartz配置

DROP TABLE IF EXISTS `f_quartztask`;
CREATE TABLE `f_quartztask` (
  `TaskID` varchar(50) NOT NULL,
  `TaskName` varchar(200) DEFAULT NULL,
  `TaskType` int(11) DEFAULT NULL,
  `TaskTag` varchar(100) DEFAULT NULL,
  `JobClassPath` varchar(200) DEFAULT NULL,
  `ExecutePeroid` int(11) DEFAULT NULL,
  `ExecuteUnit` int(11) DEFAULT NULL,
  `CornExpress` varchar(200) DEFAULT NULL,
  `Enviroment` varchar(50) DEFAULT NULL,
  `TaskStatus` int(11) DEFAULT NULL,
  `SortNum` int(11) DEFAULT NULL,
  `Remark` varchar(500) DEFAULT NULL,
  PRIMARY KEY (`TaskID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

枚举类

public class QuartzEnum {
    public enum TaskType implements IConvertEnumToCodeItem {
        Cycle(10, "循环任务"), Corn(20, "Corn表达式任务");
        private int _value;
        private String _name;

        private TaskType(int value, String name) {
            set_value(value);
            set_name((name));
        }

        public int get_value() {
            return _value;
        }

        public void set_value(int _value) {
            this._value = _value;
        }

        public String get_name() {
            return _name;
        }

        public void set_name(String _name) {
            this._name = _name;
        }

        @Override
        public String toString() {
            return _name;
        }

        @Override
        public String getCodeName() {
            return "Quartz任务类别";
        }
    }

    public enum ExecuteUnit implements IConvertEnumToCodeItem {
        Second(10, "秒"), Minute(20, "分"), Hour(30, "时");
        private int _value;
        private String _name;

        private ExecuteUnit(int value, String name) {
            set_value(value);
            set_name((name));
        }

        public int get_value() {
            return _value;
        }

        public void set_value(int _value) {
            this._value = _value;
        }

        public String get_name() {
            return _name;
        }

        public void set_name(String _name) {
            this._name = _name;
        }

        @Override
        public String toString() {
            return _name;
        }

        @Override
        public String getCodeName() {
            return "Quartz间隔单位";
        }
    }


    public enum TaskStatus implements IConvertEnumToCodeItem {
        Open(10, "开启"), Close(20, "关闭");
        private int _value;
        private String _name;

        private TaskStatus(int value, String name) {
            set_value(value);
            set_name((name));
        }

        public int get_value() {
            return _value;
        }

        public void set_value(int _value) {
            this._value = _value;
        }

        public String get_name() {
            return _name;
        }

        public void set_name(String _name) {
            this._name = _name;
        }

        @Override
        public String toString() {
            return _name;
        }

        @Override
        public String getCodeName() {
            return "Quartz任务状态";
        }
    }

    public enum TaskEnviroment implements IConvertEnumToCodeItem {
        All("全部", "全部"), Dev("dev", "开发环境"), Pro("pro", "正式环境");
        private String _value;
        private String _name;

        private TaskEnviroment(String value, String name) {
            set_value(value);
            set_name((name));
        }

        public String get_value() {
            return _value;
        }

        public void set_value(String _value) {
            this._value = _value;
        }

        public String get_name() {
            return _name;
        }

        public void set_name(String _name) {
            this._name = _name;
        }

        @Override
        public String toString() {
            return _name;
        }

        @Override
        public String getCodeName() {
            return "Quartz任务执行环境";
        }
    }
}

QuartzFactory

支持Job类注bean入对象

@Component
public class QuartzFactory extends AdaptableJobFactory {
    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;

    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        // 调用父类的方法
        Object jobInstance = super.createJobInstance(bundle);
        // 进行注入
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;

    }
}

QuartzConfig

注入QuartzFactory对象

@Configuration
public class QuartzConfig {
    @Autowired
    private QuartzFactory quartzFactory;

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(){
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        schedulerFactoryBean.setJobFactory(quartzFactory);
        //将job实例化,能够操作进行Spring 注入
        return schedulerFactoryBean;
    }
}

QuartzUtil

定时任务动态添加/删除操作类,initQuartzTask方法在系统启动时执行,根据配置自动开启相关符合条件的任务

@Component
public class QuartzUtil {
    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;
    @Autowired
    private F_QuartzTaskService quartzTaskService;
    @Value("${spring.profiles.active}")
    private String active;
    private static String JOB_GROUP_NAME = "DEFAULT_JOB_GROUP_NAME";
    private static String TRIGGER_GROUP_NAME = "DEFAULT_TRIGGER_GROUP_NAME";


    public void initQuartzTask() {
        List<F_QuartzTaskDO> openTaskList = quartzTaskService.selectAllList();
        if(openTaskList.size()>0){
            openTaskList = openTaskList.stream().filter(a -> a.getTaskStatus() == QuartzEnum.TaskStatus.Open.get_value() &&
                    (a.getEnviroment().equals(QuartzEnum.TaskEnviroment.All.get_name()) || a.getEnviroment().equals(active))).collect(Collectors.toList());
        }
        for (F_QuartzTaskDO taskDO : openTaskList) {
            try {
                Class<Job> jobClass = (Class<Job>) Class.forName(taskDO.getJobClassPath());
                if (taskDO.getTaskType() == QuartzEnum.TaskType.Cycle.get_value()) {
                    addIntervalJob(taskDO.getTaskTag(), jobClass, taskDO.getExecutePeroid(), taskDO.getExecuteUnit());
                } else {
                    addCornJob(taskDO.getTaskTag(), jobClass, taskDO.getCornExpress());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (openTaskList.size() > 0) {
            System.out.println("扫描并初始化开启quartz定时任务成功,任务数量:" + openTaskList.size() + "个");
        }
    }

    public void startTask( F_QuartzTaskDO taskDO){
        try {
            Class<Job> jobClass = (Class<Job>) Class.forName(taskDO.getJobClassPath());
            if (taskDO.getTaskType() == QuartzEnum.TaskType.Cycle.get_value()) {
                addIntervalJob(taskDO.getTaskTag(), jobClass, taskDO.getExecutePeroid(), taskDO.getExecuteUnit());
            } else {
                addCornJob(taskDO.getTaskTag(), jobClass, taskDO.getCornExpress());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //增加定时任务任务
    public void addIntervalJob(String jobName, Class<? extends Job> cls, int peroid, int timeUnit) {
        try {
            SimpleScheduleBuilder scheduleBuilder = null;
            if (timeUnit == QuartzEnum.ExecuteUnit.Second.get_value()) {
                scheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(peroid).repeatForever();
            } else if (timeUnit == QuartzEnum.ExecuteUnit.Minute.get_value()) {
                scheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInMinutes(peroid).repeatForever();
            } else if (timeUnit == QuartzEnum.ExecuteUnit.Hour.get_value()) {
                scheduleBuilder = SimpleScheduleBuilder.simpleSchedule().withIntervalInHours(peroid).repeatForever();
            }
            Scheduler sched = schedulerFactoryBean.getScheduler();
            JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(jobName, JOB_GROUP_NAME).storeDurably().build();
            Trigger trigger = TriggerBuilder.newTrigger().forJob(jobDetail).withIdentity(jobName, TRIGGER_GROUP_NAME).withSchedule(scheduleBuilder).build();

            sched.scheduleJob(jobDetail, trigger);
            if (!sched.isShutdown()) {
                sched.start();        // 启动
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    //增加corn表达式任务
    public void addCornJob(String jobName, Class<? extends Job> cls, String cornExpress) {
        try {
            Scheduler sched = schedulerFactoryBean.getScheduler();
            JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(jobName, JOB_GROUP_NAME).build();
            CronTrigger trigger = (CronTrigger) TriggerBuilder
                    .newTrigger()
                    .withIdentity(jobName, TRIGGER_GROUP_NAME)
                    .withSchedule(CronScheduleBuilder.cronSchedule(cornExpress))
                    .build();
            sched.scheduleJob(jobDetail, trigger);
            if (!sched.isShutdown()) {
                sched.start();        // 启动
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    //停止任务
    public void deleteJob(String jobName) {
        try {
            Scheduler sched = schedulerFactoryBean.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, TRIGGER_GROUP_NAME);
            JobKey jobKey = JobKey.jobKey(jobName, JOB_GROUP_NAME);
            sched.pauseTrigger(triggerKey); // 停止触发器
            sched.unscheduleJob(triggerKey);// 移除触发器
            sched.deleteJob(jobKey);        // 删除任务
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

界面展示

SpringBoot实现quartz定时任务可视化管理功能

SpringBoot实现quartz定时任务可视化管理功能

到此这篇关于SpringBoot实现quartz定时任务可视化管理的文章就介绍到这了,更多相关SpringBoot 定时任务可视化内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Java/Android 相关文章推荐
ConstraintValidator类如何实现自定义注解校验前端传参
Jun 18 Java/Android
SpringBoot集成Redis,并自定义对象序列化操作
Jun 22 Java/Android
使用feign服务调用添加Header参数
Jun 23 Java/Android
深入理解java.lang.String类的不可变性
Jun 27 Java/Android
浅谈Python魔法方法
Jun 28 Java/Android
Spring中bean的生命周期之getSingleton方法
Jun 30 Java/Android
java如何实现socket连接方法封装
Sep 25 Java/Android
Java中的随机数Random
Mar 17 Java/Android
MybatisPlus EntityWrapper如何自定义SQL
Mar 22 Java/Android
Android自定义双向滑动控件
Apr 19 Java/Android
Android 界面一键变灰 深色主题工具类
Apr 28 Java/Android
volatile保证可见性及重排序方法
Aug 05 Java/Android
logback 实现给变量指定默认值
Aug 30 #Java/Android
SpringMVC 整合SSM框架详解
Aug 30 #Java/Android
使用logback实现按自己的需求打印日志到自定义的文件里
Aug 30 #Java/Android
logback如何自定义日志存储
Aug 30 #Java/Android
idea以任意顺序debug多线程程序的具体用法
Aug 30 #Java/Android
Logback 使用TurboFilter实现日志级别等内容的动态修改操作
Aug 30 #Java/Android
Java SSM配置文件案例详解
Aug 30 #Java/Android
You might like
PHP远程连接MYSQL数据库非常慢的解决方法
2008/07/05 PHP
PHP开发者常犯的10个MySQL错误更正剖析
2012/01/30 PHP
解析MySql与Java的时间类型
2013/06/22 PHP
PHP搭建大文件切割分块上传功能示例
2017/01/04 PHP
PHPstorm启用自动换行的方法详解(IDE)
2020/09/17 PHP
记录几个javascript有关的小细节
2007/04/02 Javascript
jquery HotKeys轻松搞定键盘事件代码
2008/08/30 Javascript
jQuery中setTimeout的几种使用方法小结
2013/04/07 Javascript
常用的JavaScript WEB操作方法分享
2015/02/28 Javascript
解决jquery无法找到其他父级子集问题的方法
2016/05/10 Javascript
nodejs如何获取时间戳与时间差
2016/08/03 NodeJs
基于input框覆盖掉数字英文的实例讲解
2017/07/21 Javascript
JavaScript实现新年倒计时效果
2018/11/17 Javascript
Vue.js特性Scoped Slots的浅析
2019/02/20 Javascript
在layui下对元素进行事件绑定的实例
2019/09/06 Javascript
JavaScrip如果基于url实现图片下载
2020/07/03 Javascript
python计算时间差的方法
2015/05/20 Python
Python实现二叉堆
2016/02/03 Python
Django中cookie的基本使用方法示例
2018/02/03 Python
基于Python中numpy数组的合并实例讲解
2018/04/04 Python
Django 使用Ajax进行前后台交互的示例讲解
2018/05/28 Python
python 去除txt文本中的空格、数字、特定字母等方法
2018/07/24 Python
Python中print和return的作用及区别解析
2019/05/05 Python
Python定时任务APScheduler的实例实例详解
2019/07/22 Python
PyCharm使用Docker镜像搭建Python开发环境
2019/12/26 Python
django 取消csrf限制的实例
2020/03/13 Python
复古服装:RetroStage
2019/05/10 全球购物
德国家用电器购物网站:Premiumshop24
2019/08/22 全球购物
linux面试题参考答案(9)
2015/01/07 面试题
英语专业毕业生求职简历的自我评价
2013/10/24 职场文书
应届行政管理专业个人自我评价
2013/12/28 职场文书
国庆促销活动总结
2014/08/29 职场文书
学校运动会报道稿
2014/09/23 职场文书
《蜜蜂引路》教学反思
2016/02/22 职场文书
话题作文之诚信
2019/11/28 职场文书
VUE递归树形实现多级列表
2022/07/15 Vue.js