springboot quartz 动态配置_springboot集成quartz实现动态任务调度

quartz是一个开源的作业调度框架,本文就是介绍下springboot框架下继承quartz的一些使用示例

首先我们需要添加quartz的spring-boot-starter-quartz依赖

org.springframework.bootspring-boot-starter-quartz

我们需要做一些配置。quartz提供了基于内存(MEMORY)和基于jdbc的两种任务存储方式。具体的配置可参考下面的示例

spring:  quartz:    jdbc:      initialize-schema: never    job-store-type: JDBC    properties:      org:        quartz:          scheduler:            instanceName: myQuartzCluster            instanceId: AUTO          jobstore:            class: org.quartz.impl.jdbcjobstore.JobStoreTX            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate            tablePrefix: qrtz_            isClustered: true            clusterCheckinInterval: 10000            useProperties: false          threadPool:            class: org.quartz.simpl.SimpleThreadPool            threadCount: 5            threadPriority: 5            threadsInheritContextClassLoaderOfInitializingThread: true

需要注意的是,如果是集群部署而且定时任务同时只能一个实例运行的话,需要配置成jdbc方式,这样就可以用到数据库的锁。MEMORY这种方式建议用于开发环境测试,不建议用于生产环境。

如果是使用jdbc的方式,quartz提供了不同数据库的建表语句。可以在quartz的jar包中找到

具体路径是org.quartz.impl.jdbcjobstore

913df608c2c1b3c382d4a685e5070e80.png

定时任务的类需要继承自QuartzJobBean并重写 executeInternal方法。

package com.xchaset.quartz.schedule.task;import com.xchaset.quartz.annotation.MyScheduled;import lombok.extern.slf4j.Slf4j;import org.quartz.DisallowConcurrentExecution;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.springframework.scheduling.quartz.QuartzJobBean;import org.springframework.stereotype.Service;@Service@Slf4j@DisallowConcurrentExecution@MyScheduled(name = "EmailTask",description = "email schedule task",cronExpression = "0 0/2 * * * ?")public class EmailTask extends QuartzJobBean {    @Override    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {        log.info("{} is execute!",this.getClass().getSimpleName());    }}

@DisallowConcurrentExecution注解可以控制我们的相同类的定时任务同时只有一个执行。通常的场景是如果定时任务实际执行时间大于设定的定时任务执行间隔时间,就会导致同时多个任务并行。

@MyScheduled是自定义的一个注解,主要用于应用启动时将定时任务注册。

package com.xchaset.quartz.annotation;import org.springframework.stereotype.Service;import java.lang.annotation.*;@Documented@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Servicepublic @interface MyScheduled {    String name() default "";    String description() default "";    String cronExpression() default "";    boolean enable() default true;}

获取注解类上的信息

package com.xchaset.quartz.utils;import com.xchaset.quartz.annotation.MyScheduled;import com.xchaset.quartz.schedule.JobBean;import org.springframework.core.annotation.AnnotationUtils;import org.springframework.scheduling.quartz.QuartzJobBean;import java.util.ArrayList;import java.util.List;import java.util.Map;public class MyAnnotationUtil {    public static List getAllMyScheduledTask(){        List jobBeans = new ArrayList<>();        Map beansOfType = SpringContextHolder.getBeansOfType(QuartzJobBean.class);        for (Map.Entry beanEntry : beansOfType.entrySet()) {            MyScheduled annotation = AnnotationUtils.findAnnotation(beanEntry.getValue().getClass(), MyScheduled.class);            QuartzJobBean value = beanEntry.getValue();            if (annotation == null) {                continue;            }            if (annotation.enable()) {                String name = annotation.name();                String description = annotation.description();                String cronExpression = annotation.cronExpression();                JobBean build = JobBean.builder().jobName(name)                        .groupName("myGroup")                        .cronExpression(cronExpression)                        .description(description)                        .quartzJobBean(value.getClass())                        .build();                jobBeans.add(build);            }        }        return jobBeans;    }}

启动时注册任务

package com.xchaset.quartz.schedule;import com.xchaset.quartz.utils.MyAnnotationUtil;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.CommandLineRunner;import org.springframework.stereotype.Component;import java.util.List;@Componentpublic class ScheduleCommandLine implements CommandLineRunner {    @Autowired    private QuartzService quartzService;    @Override    public void run(String... args) throws Exception {        List allMyScheduledTask = MyAnnotationUtil.getAllMyScheduledTask();        for (JobBean jobBean : allMyScheduledTask) {            quartzService.deleteJob(jobBean.getGroupName(),jobBean.getJobName());            quartzService.addJob(jobBean.getQuartzJobBean(),jobBean.getGroupName(),jobBean.getJobName(),jobBean.getCronExpression(),null);        }    }}

对于怎么做到动态的添加、暂停、删除、恢复、执行一个任务呢? quartz提供了这样的API。我们只需要稍微做一下封装。以接口的形式提供出去就可以了。

package com.xchaset.quartz.schedule;import org.quartz.*;import org.quartz.impl.matchers.GroupMatcher;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.scheduling.quartz.QuartzJobBean;import org.springframework.stereotype.Service;import javax.annotation.PostConstruct;import java.util.*;@Servicepublic class QuartzService {    @Autowired    private Scheduler scheduler;    @PostConstruct    public void startScheduler() {        try {            scheduler.start();        } catch (SchedulerException e) {            e.printStackTrace();        }    }    /**     * 添加一个任务     * @param jobClass     * @param jobGroup     * @param jobName     * @param jobTime     * @param jobMap     * @throws SchedulerException     */    public void addJob(Class extends QuartzJobBean> jobClass, String jobGroup, String jobName, String jobTime, Map jobMap) throws SchedulerException {        JobDetail build = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroup).build();        if (jobMap != null && jobMap.size() > 0) {            build.getJobDataMap().putAll(jobMap);        }        Trigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroup)                .startAt(DateBuilder.futureDate(1, DateBuilder.IntervalUnit.SECOND))                .withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).startNow().build();        scheduler.scheduleJob(build, cronTrigger);    }    /**     * 更新任务时间表达式     * @param jobGroup     * @param jobName     * @param jobTime     * @throws SchedulerException     */    public void updateJob(String jobGroup, String jobName, String jobTime) throws SchedulerException {        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);        CronTrigger trigger = (CronTrigger)scheduler.getTrigger(triggerKey);        trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)                .withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).build();        scheduler.rescheduleJob(triggerKey,trigger);    }    /**     * 删除任务     * @param jobGroup     * @param jobName     * @throws SchedulerException     */    public void deleteJob(String jobGroup,String jobName) throws SchedulerException {        scheduler.deleteJob(new JobKey(jobName,jobGroup));    }    public void pauseJob(String jobGroup,String jobName) throws SchedulerException {        scheduler.pauseJob(new JobKey(jobName,jobGroup));    }    /**     * 恢复任务     * @param jobGroup     * @param jobName     * @throws SchedulerException     */    public void resumeJob(String jobGroup,String jobName) throws SchedulerException {        scheduler.resumeJob(new JobKey(jobName,jobGroup));    }    /**     * 立刻执行一个任务     * @param jobGroup     * @param jobName     * @throws SchedulerException     */    public void runAJobNow(String jobGroup,String jobName) throws SchedulerException {        scheduler.triggerJob(new JobKey(jobName,jobGroup));    }    /**     * 查询所有的任务     * @return     * @throws SchedulerException     */    public List queryAllJob() throws SchedulerException {        GroupMatcher anyJobGroup = GroupMatcher.anyJobGroup();        Set jobKeys = scheduler.getJobKeys(anyJobGroup);        List result = getJobDetailsBeans(jobKeys);        return result;    }    private List getJobDetailsBeans(Collection jobKeys) throws SchedulerException {        List result = new ArrayList<>();        for (JobKey jobKey : jobKeys) {            List extends Trigger> triggersOfJob = scheduler.getTriggersOfJob(jobKey);            for (Trigger trigger : triggersOfJob) {                String group = jobKey.getGroup();                String name = jobKey.getName();                String className = jobKey.getClass().getName();                String description = trigger.getDescription();                JobDataMap jobDataMap = trigger.getJobDataMap();                Date nextFireTime = trigger.getNextFireTime();                Date previousFireTime = trigger.getPreviousFireTime();                Trigger.TriggerState triggerState = scheduler.getTriggerState(TriggerKey.triggerKey(name, group));                String cronExpression = "";                if (trigger instanceof CronTrigger) {                    cronExpression = ((CronTrigger) trigger).getCronExpression();                }                JobDetailsBean build = JobDetailsBean.builder().className(className).groupName(group).jobName(name).description(description)                        .cronExpression(cronExpression).jobDataMap(jobDataMap).nextFireTime(nextFireTime).previousFireTime(previousFireTime)                        .triggerState(triggerState.name()).build();                result.add(build);            }        }        return result;    }    /**     * 查询正在执行的任务     * @return     * @throws SchedulerException     */    public List queryCurrentExecutingJob() throws SchedulerException {        List result = new ArrayList<>();        List currentlyExecutingJobs = scheduler.getCurrentlyExecutingJobs();        for (JobExecutionContext currentlyExecutingJob : currentlyExecutingJobs) {            Trigger trigger = currentlyExecutingJob.getTrigger();            JobDataMap jobDataMap = trigger.getJobDataMap();            JobKey jobKey = trigger.getJobKey();            String group = jobKey.getGroup();            String name = jobKey.getName();            String className = jobKey.getClass().getName();            Date nextFireTime = trigger.getNextFireTime();            String description = trigger.getDescription();            Date previousFireTime = trigger.getPreviousFireTime();            Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());            String cronExpression = "";            if (trigger instanceof CronTrigger) {                cronExpression = ((CronTrigger) trigger).getCronExpression();            }            JobDetailsBean build = JobDetailsBean.builder().className(className).groupName(group).jobName(name).description(description)                    .cronExpression(cronExpression).jobDataMap(jobDataMap).nextFireTime(nextFireTime).previousFireTime(previousFireTime)                    .triggerState(triggerState.name()).build();            result.add(build);        }        return result;    }}

我们可以在上面代码的基础上,对外提供接口,这样就可以通过可视化的界面来动态的对任务进行调度了。

以上就是springboot集成quartz的简单使用了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/244169.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sql server cdc 清理_基于CDC技术的ElasticSearch索引同步机制

概述ElasticSearch作为一个基于Lucene的搜索引擎被广泛应用于各种应用系统&#xff0c;比如电商、新闻类、咨询类网站。在使用ElasticSearch开发应用的过程中&#xff0c;一个非常重要的过程是将数据导入到ElasticSearch索引中建立文档。在一开始系统规模比较小时&#xff0c;我…

mysql 8.0数据备份恢复_MySQL 8.0 增强逻辑备份恢复工具介绍-爱可生

作者&#xff1a;杨涛涛资深数据库专家&#xff0c;专研 MySQL 十余年。擅长 MySQL、PostgreSQL、MongoDB 等开源数据库相关的备份恢复、SQL 调优、监控运维、高可用架构设计等。目前任职于爱可生&#xff0c;为各大运营商及银行金融企业提供 MySQL 相关技术支持、MySQL 相关课…

android 字体竖直居中_问下弹性盒内不知道高度的时候想让字体垂直居中代码要怎么写...

[Asm] 纯文本查看 复制代码自适应圣杯布局* {margin: 0;padding: 0;}body,html {height: 100%;}body {display: flex;flex-direction: column;}.header {width: 100%;flex: 1;background-color: #dcdcdc;}.main {width: 100%;flex: 6;display: flex;}.left-container {flex: 1;…

mysql数据库优化清理_mysql 数据库优化整理

内连接 -- inner join内连接在不加on的情况下, 也是去求笛卡尔乘积. 不加on的用法并不推荐使用, 容易造成内存溢出的情况. 加on的时候, 在连表的时候, 就会对数据进行筛选, 以此来缩减有效数据范围。select * from A inner join B; select * from A,B; //交叉连接 -- 笛卡尔乘…

python38怎么用_Python基础练习实例38(数组操作)

题目&#xff1a;有一个已经排好序的数组。现输入一个数&#xff0c;要求按原来的从小到大顺序将它插入数组中。程序分析&#xff1a;首先判断此数是否大于最后一个数&#xff0c;然后再考虑插入中间的数的情况&#xff0c;插入后此元素之后的数&#xff0c;依次后移一个位置。…

python判断正数和负数教案_正数和负数 教学设计

《正数和负数 教学设计》由会员分享&#xff0c;可在线阅读&#xff0c;更多相关《正数和负数 教学设计(3页珍藏版)》请在人人文库网上搜索。1、1.1 正数与负数第一课时(一)概述课名是正数与负数&#xff0c;是义务教育课程标准实验教科书初中七年级的一堂数学课。本节课所需课…

修改pytho2安装插件的位置_office2016自定义安装以及修改安装位置

一、下载office2016专业增强版ed2k://|file|cn_office_professional_plus_2016_x86_x64_dvd_6969182.iso|2588266496|27EEA4FE4BB13CD0ECCDFC24167F9E01|/复制使用迅雷下载二、office2016部署工具部署工具地址​www.microsoft.com运行部署工具会生成setup.execonfiguration-Off…

vue 获取元素在浏览器的位置_前端开发JS获取页面元素的位置

1.网页的大小和浏览器窗口的大小一张网页的全部面积&#xff0c;就是它的大小。通常情况下&#xff0c;网页的大小由内容和document元素的clientHeight和clientWidth属性&#xff0c;就代表了网页的大小。function getViewport(){if (document.compatMode “BackCompat”){ret…

python 发送邮件不显示附件_python3发送邮件(无附件)

python3发送邮件代码&#xff1a;import smtplibfrom email.mime.text import MIMETextfrom email.utils import formatdate#设置服务器所需信息#163邮箱服务器地址mail_host smtp.163.com#163用户名mail_user h*****163.com#密码mail_pass h****password#邮件发送方邮箱地址…

小说是读者的艺术

小说的处境到了今天这个份上&#xff0c;该让我们的编辑和作家有点悔悟了&#xff0c;那就是光靠玩技巧和语言以及所有的花活唬不了读者&#xff0c;更救不了小说本身。我们知道一种艺术形式的存在很大程度上依赖于它的接受者的存在&#xff0c;所谓皮之不在&#xff0c;毛将存…

stright 在mysql_MySQL优化的奇技淫巧之STRAIGHT_JOIN

最近没怎么搞SQL优化&#xff0c;碰巧数据库被慢查询搞挂了&#xff0c;于是拿来练练手。问题通过「SHOW FULL PROCESSLIST」语句很容易就能查到问题SQL&#xff0c;如下&#xff1a;SELECT post.*FROM postINNER JOIN post_tag ON post.id post_tag.post_idWHERE post.status…

小说不“好看”,读者就给你“好看”

小说的病变和无可救药的衰竭是因为小说不好看 □主 持 人&#xff1a;兴 安 青年作家&#xff1a;丁 天 邱华栋 陆 涛 古清生 小说是什么&#xff1f;是“街谈巷议”———这是我们的老祖宗概括的&#xff0c;就是说它生于民间&#xff0c;是给更多的人看的&#x…

狗肉朋友

想想几年的圣诞聚会,朋友、哥们、同事、陌生人,每一年人走马灯似的变换,有的早在记忆中消失,如过眼烟云.而一直能保留下来的就那么几个朋友。 随着年龄的增长,自己在交往中纳新的能力和兴致越来越低,朋友的圈子越来越小,过去的那种结交天下豪杰的扩张心理没有了,守住故交,守住最…

mysql json坑_使用mysql innodb 使用5.7的json类型遇到的坑和解决办法

----------------------------------------------#查询JSON的某个字段select data -> ‘$.Host‘ from temp#创建虚拟列ALTER TABLE temp ADD host varchar(128) GENERATED ALWAYS AS (json_extract(data,‘$.Host‘)) VIRTUAL;#给虚拟列创建索引ALTER TABLE temp ADD INDEX…

恐怖小说之王——斯蒂芬·金 (转贴)

《宠物公墓》改编自斯蒂芬金的同名小说&#xff0c;在所有斯蒂芬金的恐怖小说里&#xff0c;恐怕就属这一部是最吓人的了。但斯蒂芬金的原著由于篇幅过长&#xff0c;难免有拖沓之感&#xff0c;当被改编成电影时&#xff0c;斯蒂芬金非常有效地压缩了与恐怖无关的枝节&#xf…

买了几张好碟

最喜欢的是《塔尔可夫斯基的全集》。以前有他零散的&#xff0c;几乎全了&#xff0c;可是看到整套的&#xff0c;包装又漂亮&#xff0c;声音又进化了5.1声道&#xff0c;确实没有理由不收啊。 《天下无贼》&#xff08;正版&#xff09;&#xff0c;《狂蟒之灾&#xff12;》…

mysql unix_timestamp 格式化_FROM_UNIXTIME 格式化MYSQL时间戳函数_MySQL

unix时间戳bitsCN.com函数&#xff1a;FROM_UNIXTIME作用&#xff1a;将MYSQL中以INT(11)存储的时间以”YYYY-MM-DD”格式来显示。语法&#xff1a;FROM_UNIXTIME(unix_timestamp,format)返回表示 Unix 时间标记的一个字符串&#xff0c;根据format字符串格式化。format可以包含…

酒喝高了,歌听多了

我常常忘记自己是蒙古人。昨天去了达尔汗蒙古风情餐吧&#xff0c;参加了蒙古的同乡会。AA制。好久没有参加这样的活动了&#xff0c;见到了些老面孔&#xff0c;大多是新面孔。有的胖了&#xff0c;有的老了&#xff0c;有的单身了&#xff0c;有的成双了&#xff0c;有的叫不…

抚摸斯蒂芬·金 (图)

<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />最近翻到一本美国恐怖小说大师斯蒂芬金的自传《抚摸恐怖——我的创作生涯》&#xff0c;珠海出版社2002年5月出版。书中披露了斯蒂芬金很多不为人知的写作经历以及对恐怖小说的看…

mysql设置定位慢查询_mysql优化——定位慢查询

1.定位慢查询1、show status 命令命令使用方式&#xff1a;show [session|global] status like slow_queries如果你不写 [session|global] 默认是session 会话&#xff0c;指取出当前窗口的执行&#xff0c;如果你想看所有(从mysql 启动到现在&#xff0c;则应该 global)执行s…