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 相关文章推荐
Java实现斗地主之洗牌发牌
Jun 14 Java/Android
解决SpringBoot跨域的三种方式
Jun 26 Java/Android
Spring Boot 实现敏感词及特殊字符过滤处理
Jun 29 Java/Android
Java中多线程下载图片并压缩能提高效率吗
Jul 01 Java/Android
看完这篇文章获得一些java if优化技巧
Jul 15 Java/Android
mybatis 获取无数据的字段不显示的问题
Jul 15 Java/Android
idea 在springboot中使用lombok插件的方法
Aug 02 Java/Android
IDEA2021.2配置docker如何将springboot项目打成镜像一键发布部署
Sep 25 Java/Android
关于maven依赖 ${xxx.version}报错问题
Jan 18 Java/Android
Java8 CompletableFuture 异步回调
Apr 28 Java/Android
Android开发EditText禁止输入监听及InputFilter字符过滤
Jun 10 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
thinkphp3.0输出重复两次的解决方法
2014/12/19 PHP
PHP实现的XML操作类【XML Library】
2016/12/29 PHP
PHP模型Model类封装数据库操作示例
2019/03/14 PHP
php使用filter_var函数判断邮箱,url,ip格式示例
2019/07/06 PHP
javascript实现划词标记+划词搜索功能
2007/03/06 Javascript
关于取不到由location.href提交而来的上级页面地址的解决办法
2009/07/30 Javascript
cnblogs csdn 代码运行框实现代码
2009/11/02 Javascript
查找Oracle高消耗语句的方法
2014/03/22 Javascript
AngularJS 日期格式化详解
2015/12/23 Javascript
Bootstrap开发实战之第一次接触Bootstrap
2016/06/02 Javascript
微信小程序 Toast自定义实例详解
2017/01/20 Javascript
JS实现的走迷宫小游戏完整实例
2017/07/19 Javascript
nodejs调取微信收货地址的方法
2017/12/20 NodeJs
在vue中解决提示警告 for循环报错的方法
2018/09/28 Javascript
jQuery动态生成的元素绑定事件操作实例分析
2019/05/04 jQuery
基于Taro的微信小程序模板消息-获取formId功能模块封装实践
2019/07/15 Javascript
javascript中的this作用域详解
2019/07/15 Javascript
vue使用svg文件补充-svg放大缩小操作(使用d3.js)
2020/09/22 Javascript
python如何通过twisted实现数据库异步插入
2018/03/20 Python
解决pytorch GPU 计算过程中出现内存耗尽的问题
2019/08/19 Python
python getpass实现密文实例详解
2019/09/24 Python
Python跑循环时内存泄露的解决方法
2020/01/13 Python
python打印文件的前几行或最后几行教程
2020/02/13 Python
OpenCV读取与写入图片的实现
2020/10/13 Python
python基于pexpect库自动获取日志信息
2021/02/01 Python
纯CSS3实现的8种Loading动画效果
2014/07/05 HTML / CSS
html通过canvas转成base64的方法
2019/07/18 HTML / CSS
OnePlus加拿大官网:中国国际化手机品牌
2020/10/13 全球购物
追悼会主持词
2014/03/20 职场文书
岗位职责说明书模板
2014/07/30 职场文书
酒店温馨提示语
2015/07/14 职场文书
2019通用版劳动合同范本!
2019/07/11 职场文书
选择比努力更重要?这是长期以来对“努力”的最大误解
2019/07/12 职场文书
python如何正确使用yield
2021/05/21 Python
python状态机transitions库详解
2021/06/02 Python
动漫APP软件排行榜前十名,半次元上榜,第一款由腾讯公司推出
2022/03/18 杂记