Springboot2 Quartz实现JAVA定时任务的动态配置

动态配置Quartz。没接触过定时任务的同学可以先看下此篇:JAVA定时任务实现的几种方式

文章目录

          • 一、需求背景
            • 1. 问题现象
            • 2. 问题分析
            • 3. 解决方案
          • 二、需求背景
            • 2.1. maven依赖
            • 2.2. 创建一个任务表
            • 2.3. 实现步骤
          • 三、代码逻辑
            • 3.1. Quartz配置
            • 3.2. 启动项目,加载监听
            • 3.3. 读取数据库,加载scheduler调度器
            • 3.4. 添加任务到Quartz调度器
            • 3.5. 根据任务调度运行job类
            • 3.6. 实例化job类,注入要运行的service
          • 四、常见的Quartz的API
            • 4.1. 新增一个job
            • 4.2. 暂停一个job
            • 4.2. 删除一个job
            • 4.3. 暂停一个job
            • 4.4. 立即执行一个job
            • 4.5. 更新job表达式
          • 五、源码下载和运行
            • 5.1. 源码地址
            • 5.2. 源码下载
            • 5.3. 项目运行

一、需求背景
1. 问题现象

定时任务实现方式: 1.JDK 的Timer类 2.Quartz 3.SpringTask 。
生产上三种方式我都有使用过。但是使用过程中用的最多的便是xml配置的方式,这种方式最简单,无代码侵入,也比较好理解。但是却有个致命的缺点,比如你要改某个任务的触发时间,亦或是你要新增一个任务,暂停一个任务。怎么做?
停应用!改XML配置!重新启动!
怎样解决上述致命的问题现象呢?

2. 问题分析

请大家想一想:停应用、修改XML配置!重新启动是为了什么?
应该是首先修改Quartz的配置文件,然后,修改一些属性配置参数,最后重新启动项目加载配置文件,对吧!
哪怎样可以动态配置Quartz的配置文件的呢?

3. 解决方案

哪怎样动态配置Quartz的属性参数的呢?如果把Quartz需要的重点关键参数存到数据库,通过页面就可以修改Quartz的属性参数了,对吧!
那问题又来了,属性参数修改了,那有怎样让属性参数生效呢?
其实Quartz官方提供了一些日常操作的API接口方法,只需要咱们把需要的参数传递给对应的api接口即可,因此,咱们的思路,应该这样想,操作增增加定时任务就找Quartz的增加api,传参数,其他的一样,对吧!

既然思路有了,那咱们就应该提前去做以下几件事:
1.Quartz常见的api在哪?或者说在哪里可以找到
2.找出常见的Quartz的api
3.认真分析常见的Quartz的api需要怎样才能触发

温馨建议:
自己写一个demo或者main方法单元测试一下,效果最好,不断完善

举个例子:
增加定时任务,一般需要几个或者什么参数,提前弄明白
这样就可以动态不停应用通过Quartz实现了不停机添加、暂停、删除、立即触发任务的方法

二、需求背景
2.1. maven依赖
<!-- quartz -->
<dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.2.1</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId>
</dependency>
2.2. 创建一个任务表
CREATE TABLE `sys_task` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`job_name` varchar(255) DEFAULT NULL COMMENT '任务名',`description` varchar(255) DEFAULT NULL COMMENT '任务描述',`cron_expression` varchar(255) DEFAULT NULL COMMENT 'cron表达式',`bean_class` varchar(255) DEFAULT NULL COMMENT '任务执行时调用哪个类的方法 包名+类名',`job_status` varchar(255) DEFAULT NULL COMMENT '任务状态',`job_group` varchar(255) DEFAULT NULL COMMENT '任务分组',`create_user` varchar(64) DEFAULT NULL COMMENT '创建者',`create_time` datetime DEFAULT NULL COMMENT '创建时间',`update_user` varchar(64) DEFAULT NULL COMMENT '更新者',`update_time` datetime DEFAULT NULL COMMENT '更新时间',PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=32 DEFAULT CHARSET=utf8;
2.3. 实现步骤

①启动项目,启动task监听
②读取数据库,将开启的任务job和trigger加载到scheduler调度器
③根据任务调度运行job类
④每次运行利用AdaptableJobFactory实例化job类,以便注入要运行的service
听着是不是很简单,但却还是一头雾水,且听我慢慢道来~~

三、代码逻辑
3.1. Quartz配置

Springboot的配置方法,常规Spring项目可以在xml中配置

@Configuration
public class QuartzConfigration {@Autowiredprivate JobFactory jobFactory;@Beanpublic SchedulerFactoryBean schedulerFactoryBean() {SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();try {schedulerFactoryBean.setOverwriteExistingJobs(true);schedulerFactoryBean.setQuartzProperties(quartzProperties());schedulerFactoryBean.setJobFactory(jobFactory);} catch (Exception e) {e.printStackTrace();}return schedulerFactoryBean;}// 指定quartz.properties,可在配置文件中配置相关属性@Beanpublic Properties quartzProperties() throws IOException {PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();propertiesFactoryBean.setLocation(new ClassPathResource("/config/quartz.properties"));propertiesFactoryBean.afterPropertiesSet();return propertiesFactoryBean.getObject();}// 创建schedule@Bean(name = "scheduler")public Scheduler scheduler() {return schedulerFactoryBean().getScheduler();}
}
3.2. 启动项目,加载监听
@Component
@Order(value = 1)
public class ScheduleJobInitListener implements CommandLineRunner {@AutowiredTaskService scheduleJobService;@Overridepublic void run(String... arg0) throws Exception {try {scheduleJobService.initSchedule();} catch (Exception e) {e.printStackTrace();}}
}

CommandLineRunner类似Spring框架的ApplicationListener监听器。官方的解释是:
Interface used to indicate that a bean should run when it is contained within a SpringApplication. Multiple CommandLineRunner beans can be defined within the same application context and can be ordered using the Ordered interface or Order @Order annotation.
接口被用作将其加入spring容器中时执行其run方法。多个CommandLineRunner可以被同时执行在同一个spring上下文中并且执行顺序是以order注解的参数顺序一致。

3.3. 读取数据库,加载scheduler调度器
@Overridepublic void initSchedule() throws SchedulerException {// 这里获取任务信息数据List<TaskDO> jobList = taskMapper.list();for (TaskDO task : jobList) {if (JobStatusEnum.RUNNING.getCode().equals(task.getJobStatus())) {quartzManager.addJob(task);}}}
3.4. 添加任务到Quartz调度器
/*** 添加任务*/    @SuppressWarnings("unchecked")public void addJob(TaskDO task) {try {// 创建jobDetail实例,绑定Job实现类// 指明job的名称,所在组的名称,以及绑定job类Class<? extends Job> jobClass = (Class<? extends Job>) (Class.forName(task.getBeanClass()).newInstance().getClass());JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(task.getJobName(), task.getJobGroup())// 任务名称和组构成任务key.build();// 定义调度触发规则// 使用cornTrigger规则Trigger trigger = TriggerBuilder.newTrigger().withIdentity(task.getJobName(), task.getJobGroup())// 触发器key.startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND)).withSchedule(CronScheduleBuilder.cronSchedule(task.getCronExpression())).startNow().build();// 把作业和触发器注册到任务调度中scheduler.scheduleJob(jobDetail, trigger);// 启动if (!scheduler.isShutdown()) {scheduler.start();}} catch (Exception e) {e.printStackTrace();}}

Scheduler作为Quartz的核心调度器,有将近50多个API接口,包括任务的添加,暂停,恢复,删除等一系列的API,这里仅介绍一些常用的,想要了解更多可以稍后看下彩蛋部分。

1、start()方法:只有调用start()方法后,Scheduler线程才开始启动触发器trigger,运行job
2、pauseJob(JobKey jobKey) :根据指定的JobDetail key暂停job。
3、resumeJob(JobKey jobKey) :根据指定的key恢复一个job。
4、deleteJob(JobKey jobKey) :删除一个job
5、triggerJob(JobKey jobKey) :触发一个JobDetail(现在执行)。
6、rescheduleJob(TriggerKey triggerKey, Trigger newTrigger):

用给定的键删除触发器,并存储新的触发器,它必须与同一个作业相关联(新触发器必须具有指定的作业名和组)-然而,新触发器不必具有与旧触发器相同的名称。

3.5. 根据任务调度运行job类

其实这一步是不需要我们编写的,在我们将正确的JobDetail 和 Trigger 表达式加载到任务调度后,调度器会自动触发任务的执行

3.6. 实例化job类,注入要运行的service

工厂类

@Component
public class JobFactory extends AdaptableJobFactory {//这个对象Spring会帮我们自动注入进来,也属于Spring技术范畴.//为什么需要这个类呢,在我写的这个demo中,大家可以将此类删掉,发现程序也可以正确运行,可是我为什么还是加上呢。//大家可以看下我们的任务类,大家可以看到Job对象的实例化过程是在Quartz中进行的,这时候我们将spring的东西注入进来,肯定是行不通的,所以需要这个类@Autowiredprivate AutowireCapableBeanFactory capableBeanFactory;@Overrideprotected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {//调用父类的方法Object jobInstance = super.createJobInstance(bundle);//进行注入capableBeanFactory.autowireBean(jobInstance);return jobInstance;}
}

任务类

@DisallowConcurrentExecution //作业不并发
@Component
public class HelloWorldJob implements Job{@Overridepublic void execute(JobExecutionContext arg0) throws JobExecutionException {System.out.println("欢迎使用yyblog,这是一个定时任务  --小卖铺的老爷爷!"+ DateUtils.fullTime(new Date()));    }
}

好了,大功告成,一个简单的动态配置的定时任务已经完成。是不是so easy!
下面我们再来简单实现下其他的几种常用的api吧。

四、常见的Quartz的API
4.1. 新增一个job
 /*** 添加任务* * @param scheduleJob* @throws SchedulerException*/    @SuppressWarnings("unchecked")public void addJob(TaskDO task) {try {// 创建jobDetail实例,绑定Job实现类// 指明job的名称,所在组的名称,以及绑定job类Class<? extends Job> jobClass = (Class<? extends Job>) (Class.forName(task.getBeanClass()).newInstance().getClass());JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(task.getJobName(), task.getJobGroup())// 任务名称和组构成任务key.build();// 定义调度触发规则// 使用cornTrigger规则Trigger trigger = TriggerBuilder.newTrigger().withIdentity(task.getJobName(), task.getJobGroup())// 触发器key.startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND)).withSchedule(CronScheduleBuilder.cronSchedule(task.getCronExpression())).startNow().build();// 把作业和触发器注册到任务调度中scheduler.scheduleJob(jobDetail, trigger);// 启动if (!scheduler.isShutdown()) {scheduler.start();}} catch (Exception e) {e.printStackTrace();}}
4.2. 暂停一个job
 /*** 暂停一个job* * @param task* @throws SchedulerException*/public void pauseJob(TaskDO task) throws SchedulerException {JobKey jobKey = JobKey.jobKey(task.getJobName(), task.getJobGroup());scheduler.pauseJob(jobKey);}
4.2. 删除一个job
 /*** 删除一个job* * @param task* @throws SchedulerException*/public void deleteJob(TaskDO task) throws SchedulerException {JobKey jobKey = JobKey.jobKey(task.getJobName(), task.getJobGroup());scheduler.deleteJob(jobKey);}
4.3. 暂停一个job
在这里插入代码片
4.4. 立即执行一个job
/*** 立即执行job* * @param task* @throws SchedulerException*/public void runJobNow(TaskDO task) throws SchedulerException {JobKey jobKey = JobKey.jobKey(task.getJobName(), task.getJobGroup());scheduler.triggerJob(jobKey);}
4.5. 更新job表达式
/*** 更新job时间表达式* * @param task* @throws SchedulerException*/public void updateJobCron(TaskDO task) throws SchedulerException {TriggerKey triggerKey = TriggerKey.triggerKey(task.getJobName(), task.getJobGroup());CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(task.getCronExpression());trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();scheduler.rescheduleJob(triggerKey, trigger);}
五、源码下载和运行
5.1. 源码地址

https://gitee.com/gb_90/yyblog

5.2. 源码下载
git clone git@gitee.com:gb_90/yyblog.git
5.3. 项目运行
#1.进入下载的项目目录
cd yyblog
#2.切换分支到1.0
git checkout 1.0
#3.初始化数据库(sql在lib下面)
#4.修改数据库连接(application.yml)
#5.启动项目
链接:http://localhost:8080
账号:admin
密码:123456

Quartz文档地址:https://github.com/allanzhuo/yyblog/tree/master/doc

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

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

相关文章

IoT Studio + LoRa打造“又猛又持久”的智能厕所

概述 为了增加厕所使用效率&#xff0c;减少被味道“熏陶”的等待时间&#xff0c;同时也为了增加厕所的清洁效率&#xff0c;我们决定做一个非侵入式的智能厕所改造方案。它可以通过红外热释电检测每个坑位有没有人&#xff0c;在web/app上实时显示&#xff0c;方便如厕人员查…

分布式事务中间件Fescar—全局写排它锁解读

前言 一般&#xff0c;数据库事务的隔离级别会被设置成 读已提交&#xff0c;已满足业务需求&#xff0c;这样对应在Fescar中的分支&#xff08;本地&#xff09;事务的隔离级别就是 读已提交&#xff0c;那么Fescar中对于全局事务的隔离级别又是什么呢&#xff1f;如果认真阅…

萤石网络摄像头服务器稳定吗,萤石摄像头画面稳定性如何?

稳定性很好&#xff0c;体现在&#xff1a;1、C1S互联网摄像头提供400万像素的摄像头&#xff0c;拥有双向实时语音功能&#xff0c;包括内置温湿度传感器、内置备用电池以及“放大镜”功能。2、萤石爱家神器C2采用内置6块光学镜片的监控镜头&#xff0c;720P图像会保证视频画面…

GTC CHINA 2019 | 黄仁勋发表主题演讲,多项创新技术与合作全面助力 AI 加速落地

近日&#xff0c;NVIDIA 创始人兼首席执行官黄仁勋在中国苏州举办的 GTC China 大会上发表主题演讲&#xff0c;宣布多项创新技术与合作&#xff0c;并阐述了 NVIDIA 如何助力 AI 加速进入大规模应用。 GTC China 是 NVIDIA 每年在中国最重要的大会&#xff0c;今年更是吸引了 …

PMP考试必看的答题技巧分享

一. 控制答题和涂写速度 按顺序答题&#xff0c;遇到纠结题&#xff0c;按照第一印象选择&#xff0c;并标记&#xff0c;涂完200题后再回顾。 可以先在试卷上写选项&#xff0c;然后根据20题一涂&#xff0c;或者50题一涂&#xff0c;用途题的时间舒缓大脑。 端正心态&…

Kubernetes 调度器实现初探

Kubernetes 调度器 Kubernetes 是一个基于容器的分布式调度器&#xff0c;实现了自己的调度模块。 在Kubernetes集群中&#xff0c;调度器作为一个独立模块通过pod运行。从几个方面介绍Kubernetes调度器。 调度器工作方式 Kubernetes中的调度器&#xff0c;是作为单独组件运…

全民学后端快餐教程(1) - 只不过是写个Java程序

服务端程序本质上也只是个Java程序&#xff0c;它接收客户端的输入&#xff0c;然后将计算处理后的返回值返回给客户端。下面我们就以这个思路开始Java后端之旅吧。 引用Spring Boot库 处理HTTP请求之类的事情&#xff0c;我们需要库的帮助。所以第一步我们就把Spring Boot引…

NVIDIA发布先进的软件定义自主机器平台DRIVE AGX Orin

近日&#xff0c;NVIDIA发布了用于自动驾驶和机器人的高度先进的软件定义平台——NVIDIA DRIVE AGX Orin™。 该平台内置全新Orin系统级芯片。该芯片由170亿个晶体管组成&#xff0c;凝聚着NVIDIA团队为期四年的努力。Orin系统级芯片集成了NVIDIA新一代GPU架构和Arm Hercules C…

linux下删除目录及其子目录下某种类型文件

#. : 表示在当前目录下 find . -name "*.txt" -type f -print -exec rm -rf {} \; # find /root/2 -name "*.txt" -type f -print -exec rm -rf {} \; 符号说明.表示在当前目录下-name “*.txt”表示查找所有后缀为txt的文件-type f表示文件类型为一般正规…

OceanBase在蚂蚁金服的智能运维实践之路

OB君&#xff1a;蚂蚁金服资深技术专家虞舜将在本文为大家分享蚂蚁金服数据库所面对的业务挑战&#xff0c;解读OceanBase的自治数据库体系&#xff0c;解密OceanBase在天猫双11大促期间的稳定性解决方案&#xff0c;探索OceanBase在蚂蚁金服的智能运维实践之路。本文整理自Oce…

在Data Lake Analytics中使用视图

在Data Lake Analytics中使用视图 1. 概述 在Data Lake Analytics&#xff08;以下简称DLA&#xff09;中使用视图&#xff08;VIEW&#xff09;功能&#xff0c;可以大大简化对于重复SQL&#xff0c;特别是较为复杂的SQL语句的编写和维护。目前DLA中还不支持SQL视图的物化。…

aop记录轨迹

文章目录一、常用的场景1. 请求拦截2. 异步保存轨迹二、案例实战2.1. pom2.2. 自定义注解2.3. aop拦截2.4. 测试类2.5. 保存日志一、常用的场景 1. 请求拦截 通过aop 请求拦截&#xff0c;举个例子&#xff0c;第三方厂商请求平台接口&#xff0c;先去数据库查询该接口&#…

机器人技术大提升:NVIDIA为构建自主机器统一平台树立里程碑

近日&#xff0c;NVIDIA发布了全新版本Isaac软件开发套件&#xff08;SDK&#xff09;&#xff0c;为机器人提供更新的AI感知和仿真功能。 NVIDIA创始人兼首席执行官黄仁勋在NVIDIA最新的GPU技术会议&#xff08;GTC CHINA 2019&#xff09;上宣布了该消息。在建立统一的机器人…

DLA实现跨地域、跨实例的多AnalyticDB读写访问

1. 介绍 实时数据仓库ADB&#xff08;AnalyticDB&#xff09;云产品&#xff1a;https://www.aliyun.com/product/ads数据湖分析服务DLA&#xff08;Data Lake Analytics&#xff09;云产品&#xff1a;https://www.aliyun.com/product/datalakeanalytics数据湖分析DLA简介&am…

Data Lake Analytics: 以SQL方式查询Redis数据

Data Lake Analytics 作为云上数据处理的枢纽&#xff0c;最近加入了对于Redis 的支持, 这篇教程带你玩转 DLA 的 Redis 支持。 创建数据库 在 DLA 里面创建一个底层映射到 Redis 的数据库的语法如下: CREATE DATABASE redis_test WITH DBPROPERTIES (catalog redis,locati…

科创板注册获批,优刻得将成为“公有云第一股”

12月24日&#xff0c;证监会公告&#xff0c;同意优刻得科技股份有限公司&#xff08;以下简称“UCloud优刻得”&#xff09;科创板IPO注册&#xff1b;从今年4月提交招股书&#xff0c;历时8个月&#xff0c;4轮往返问询&#xff0c;中国领先的中立第三方云计算服务商&#xf…

一、项目管理框架【PMP 】

文章目录1. 项目的定义2. 项目的特性3. 项目和运营4. 项目管理最终要达成5. 新核心的三重约束6. 项目目标各维度顺序7. 项目集合项目组合的区别8. 指南的关键组成部分9. 项目和开发生命周期10. 项目管理的5大过程组合49个过程11. 项目管理商业文件12. 文件间的关系1. 项目的定义…

云上中国年,阿里云CDN猪年春节高峰流量再创新高

虽然科技拉近了时空距离&#xff0c;但是大部分中国人还是在春节前穿越了千山万水&#xff0c;为的就是能与家人吃一顿年夜饭&#xff0c;这是中国人不变的情结。 过春节&#xff0c;红包可是少不了的关键词&#xff0c;互联网赋予了红包更多元的意义。各大平台每年都会有新玩…

分布式事务中间件 Fescar—RM 模块源码解读

前言 在SOA、微服务架构流行的年代&#xff0c;许多复杂业务上需要支持多资源占用场景&#xff0c;而在分布式系统中因为某个资源不足而导致其它资源占用回滚的系统设计一直是个难点。我所在的团队也遇到了这个问题&#xff0c;为解决这个问题上&#xff0c;团队采用的是阿里开…