SpringBoot 整合 Quartz 实现 JAVA 定时任务的动态配置
ccwgpt 2024-10-16 08:07 32 浏览 0 评论
★★★建议星标我们★★★
Java进阶架构师★“星标”!这样才不会错过每日进阶架构文章呀。
2020年Java原创面试题库连载中
【000期】Java最全面试题库思维导图
【020期】JavaSE系列面试题汇总(共18篇)
【028期】JavaWeb系列面试题汇总(共10篇)
【042期】JavaEE系列面试题汇总(共13篇)
【049期】数据库系列面试题汇总(共6篇)
【053期】中间件系列面试题汇总(共3篇)
【065期】数据结构与算法面试题汇总(共11篇)
【076期】分布式面试题汇总(共10篇)
【077期】综合面试题系列(一)
【078期】综合面试题系列(二)
【079期】综合面试题系列(三)
【080期】综合面试题系列(四)
【081期】综合面试题系列(五)
【082期】综合面试题系列(六)
【083期】综合面试题系列(七)
【084期】综合面试题系列(八)
【085期】综合面试题系列(九)
【086期】综合面试题系列(十)
【087期】综合面试题系列(十一)
【088期】综合面试题系列(十二)
【089期】综合面试题系列(十三)
更多内容,点击上面蓝字查看
作者:老爷爷的博客园
来源:https://www.cnblogs.com/laoyeye/p/9352002.html老爷爷的博客园
什么是动态配置定时任务?
首先说下这次主题,动态配置。没接触过定时任务的同学可以先看下此篇:JAVA定时任务实现的几种方式
定时任务实现方式千人千种,不过基础的无外乎 1、JDK 的Timer类 2、Quartz 3、SpringTask 。生产上三种方式我都有使用过。但是使用过程中用的最多的便是xml配置的方式,这种方式最简单,无代码侵入,也比较好理解。
但是却有个致命的缺点,比如你要改某个任务的触发时间,亦或是你要新增一个任务,暂停一个任务。怎么做?
停应用!改XML配置!重新启动!
是不是很致命。最近重新研究了下Quartz的配置,实现了不停机添加、暂停、删除、立即触发任务的方法,在本篇分享出来,其实也不算是完全的研究,在上家公司已经有大佬实现了,这次是也是基于大佬的理解重新实现下。
国际惯例~先看效果图
管理界面:
效果图:实在不知道该跑什么了,每隔十秒打一段话吧。
技术实现
maven依赖
使用springboot做框架支持。
<!-- 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>
数据表。
CREATE TABLE `sys_task` (
`id` bigint(20) NOT AUTO_INCREMENT,
`job_name` varchar(255) DEFAULT COMMENT '任务名',
`description` varchar(255) DEFAULT COMMENT '任务描述',
`cron_expression` varchar(255) DEFAULT COMMENT 'cron表达式',
`bean_class` varchar(255) DEFAULT COMMENT '任务执行时调用哪个类的方法 包名+类名',
`job_status` varchar(255) DEFAULT COMMENT '任务状态',
`job_group` varchar(255) DEFAULT COMMENT '任务分组',
`create_user` varchar(64) DEFAULT COMMENT '创建者',
`create_time` datetime DEFAULT COMMENT '创建时间',
`update_user` varchar(64) DEFAULT COMMENT '更新者',
`update_time` datetime DEFAULT COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=32 DEFAULT CHARSET=utf8;
实现步骤。
启动项目,启动task监听
读取数据库,将开启的任务job和trigger加载到scheduler调度器
根据任务调度运行job类
每次运行利用AdaptableJobFactory实例化job类,以便注入要运行的service
听着是不是很简单,但却还是一头雾水,且听我慢慢道来~~
代码逻辑。
第一步:启动项目,加载监听。
Quartz配置
Springboot的配置方法,常规Spring项目可以在xml中配置
@Configuration
public class QuartzConfigration {
@Autowired
private JobFactory jobFactory;
@Bean
public 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,可在配置文件中配置相关属性
@Bean
public 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;
}
}
监听器。
@Component
@Order(value = 1)
public class ScheduleJobInitListener implements CommandLineRunner {
@Autowired
TaskService scheduleJobService;
@Override
public 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注解的参数顺序一致。
?
第二步:读取数据库,加载scheduler调度器。
job方法。
@Override
public void initSchedule throws SchedulerException {
// 这里获取任务信息数据
List<TaskDO> jobList = taskMapper.list;
for (TaskDO task : jobList) {
if (JobStatusEnum.RUNNING.getCode.equals(task.getJobStatus)) {
quartzManager.addJob(task);
}
}
}
添加任务到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,这里仅介绍一些常用的,想要了解更多可以稍后看下彩蛋部分。
start方法:只有调用start方法后,Scheduler线程才开始启动触发器trigger,运行job
pauseJob(JobKey jobKey) :根据指定的JobDetail key暂停job。
resumeJob(JobKey jobKey) :根据指定的key恢复一个job。
deleteJob(JobKey jobKey) :删除一个job
triggerJob(JobKey jobKey) :触发一个JobDetail(现在执行)。
rescheduleJob(TriggerKey triggerKey, Trigger newTrigger):
用给定的键删除触发器,并存储新的触发器,它必须与同一个作业相关联(新触发器必须具有指定的作业名和组)-然而,新触发器不必具有与旧触发器相同的名称。
第三步:根据任务调度运行job类。
其实这一步是不需要我们编写的,在我们将正确的JobDetail 和 Trigger 表达式加载到任务调度后,调度器会自动触发任务的执行 。
第四步:实例化job类,注入要运行的service。
工厂类
@Component
public class JobFactory extends AdaptableJobFactory {
//这个对象Spring会帮我们自动注入进来,也属于Spring技术范畴.
//为什么需要这个类呢,在我写的这个demo中,大家可以将此类删掉,发现程序也可以正确运行,可是我为什么还是加上呢。
//大家可以看下我们的任务类,大家可以看到Job对象的实例化过程是在Quartz中进行的,这时候我们将spring的东西注入进来,肯定是行不通的,所以需要这个类
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
//调用父类的方法
Object jobInstance = super.createJobInstance(bundle);
//进行注入
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
任务类。
@DisallowConcurrentExecution //作业不并发
@Component
public class HelloWorldJob implementsJob{
@Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
System.out.println("欢迎使用yyblog,这是一个定时任务 --小卖铺的老爷爷!"+ DateUtils.fullTime(new Date));
}
}
好了,大功告成,一个简单的动态配置的定时任务已经完成。是不是so easy,下面我们再来简单实现下其他的几种常用的api吧。
暂停一个job。
public void pauseJob(TaskDO task) throws SchedulerException {
JobKey jobKey = JobKey.jobKey(task.getJobName, task.getJobGroup);
scheduler.pauseJob(jobKey);
}
恢复一个job
public void resumeJob(TaskDO task) throws SchedulerException {
JobKey jobKey = JobKey.jobKey(task.getJobName, task.getJobGroup);
scheduler.resumeJob(jobKey);
}
删除一个job
public void deleteJob(TaskDO task) throws SchedulerException {
JobKey jobKey = JobKey.jobKey(task.getJobName, task.getJobGroup);
scheduler.deleteJob(jobKey);
}
立即触发job
public void runJobNow(TaskDO task) throws SchedulerException {
JobKey jobKey = JobKey.jobKey(task.getJobName, task.getJobGroup);
scheduler.triggerJob(jobKey);
}
更新job表达式
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);
}
总结
正文部分基本上就这些,不多废话了,本文没有太多的讲解原理,只是简单的应用。
之前,给大家发过三份Java面试宝典,这次新增了一份,目前总共是四份面试宝典,相信在跳槽前一个月按照面试宝典准备准备,基本没大问题。
《java面试宝典5.0》(初中级)
《350道Java面试题:整理自100+公司》(中高级)
《资深java面试宝典-视频版》(资深)
《Java[BAT]面试必备》(资深)
分别适用于初中级,中高级,资深级工程师的面试复习。
内容包含java基础、javaweb、mysql性能优化、JVM、锁、百万并发、消息队列,高性能缓存、反射、Spring全家桶原理、微服务、Zookeeper、数据结构、限流熔断降级等等。
看到这里,证明有所收获
相关推荐
- 如何高效实现API接口的自动化测试?
-
实现API接口的自动化测试是一个多步骤的过程,涉及需求分析、测试用例设计、环境搭建、脚本编写、执行测试、结果分析和持续集成等多个环节。选择合适的工具和框架也是成功的关键。嘿,咱来聊聊实现API接口自动...
- 总结100+前端优质库,让你成为前端百事通
-
1年多时间,陆陆续续整理了一些常用且实用的开源项目,方便大家更高效地学习和工作.js相关库js常用工具类「lodash」一个一致性、模块化、高性能的JavaScript实用工具库。「xij...
- 混合开发到底怎么个混法?(混合开发rn)
-
引言最近几年混合开发越来越火,从PhoneGap到Cordova到Ionic,再到ReactNative,到Flutter。同时在搜索引擎中诸如IonicVSReactNativeRN和Weex+...
- 无所不能,将 Vue 渲染到嵌入式液晶屏
-
该文章转载自公众号@前端时刻,https://mp.weixin.qq.com/s/WDHW36zhfNFVFVv4jO2vrA前言之前看了雪碧大佬的将React渲染到嵌入式液晶屏觉得很有意思,R...
- 【直接收藏】前端 VUE 高阶面试题(一)
-
说说vue动态权限绑定渲染列表(权限列表渲染)首先请求服务器,获取当前用户的权限数据,比如请求this.$http.get("rights/list");获取到权限数据之后,在列表中...
- Vue采用虚拟DOM的目的是什么?(vue2 虚拟dom)
-
虚拟DOM更新其实效率并不像大家想象中的那么高,而且React官方也从来没说过虚拟DOM效率有多高,相反React虚拟DOM的实现也不是所有虚拟DOM产品中最好的。但是通过虚拟D...
- 什么是 JavaScript?(什么是党的旗帜)
-
本文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻,欢迎关注!作者|慕课网精英讲师然冬JavaScript(JS)是一种具有函数优先的轻量级,解释型或即时编译型的编程语言。(MDN...
- Weex在内涵发现页中的工程实践(weex唯客交易所官网)
-
React-Native和Weex是目前最为火热的两个客户端跨平台解决方案。从去年2016年9月份开始,IES在抖音产品中应用了ReactNative,中途遇到了很多的问题,尤其是长列表的性能问题一...
- 新恒汇:公司主要业务包括智能卡业务、蚀刻引线框架业务以及物联网eSIM芯片封测业务
-
证券日报网讯新恒汇7月3日在互动平台回答投资者提问时表示,公司主要业务包括智能卡业务、蚀刻引线框架业务以及物联网eSIM芯片封测业务。具体请关注公司公告和公开披露信息。(编辑王雪儿)...
- “移”科普——什么是物联网?(移动设备物联网物联网应用实例)
-
物联网(InternetofThings,简称IoT)是指通过互联网将物理世界与数字世界相连接,实现物与物之间的智能互联的网络。它是一种新型的信息通信技术,通过传感器、嵌入式系统、网络技术等手段,...
- 如何自己搭建一个物联网平台?(自建物联网云平台)
-
自己搭建一个物联网(IoT)平台需要涉及多个关键步骤,包括硬件设备的选择、软件开发、网络通信、安全性设计以及数据管理。以下是搭建物联网平台的基本流程:1.确定物联网平台架构一个完整的物联网平台通常包...
- 物联网数据接入篇-应用层 Modbus(5)
-
前四篇文章讲述的是TCP/IP模型中的网络接口层、网络层、传输层、应用层一,这里到了第四层应用层二。由于协议比较多,就分开篇来介绍。这篇讲Modbus协议,后面再讲MQTT协议、CoAP协议、...
- 乐鑫ESP32-C5全面量产:行业首款双频Wi-Fi 6的RISC-V SoC
-
IT之家5月2日消息,乐鑫信息科技4月30日宣布,ESP32-C5现已全面进入量产。ESP32-C5宣称是行业首款2.4&5GHz双频Wi-Fi6的RISC-...
- Vue Shop Admin:强大而易用的后台管理系统模板
-
VueShopAdmin是一个基于Vue.js框架的后台管理系统模板。它具有简洁、易用和美观的特点,非常适合开发人员用于快速构建各种类型的管理系统。这个模板使用了最新的技术,如Vue3、V...
- 基于Prometheus的自动化巡检(prometheus自动发现详解)
-
!!大家好,我是乔克,一个爱折腾的运维工程,一个睡觉都被自己丑醒的云原生爱好者。作者:乔克公众号:运维开发故事道路千万条,安全第一条。操作不规范,运维两行泪。前言目前,大部分公司都采用Promet...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- 框架图 (58)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- jpa框架 (47)
- springmvc框架 (49)
- 分布式事务框架 (65)
- scrapy框架 (56)
- shiro框架 (61)
- 定时任务框架 (56)
- java日志框架 (61)
- JAVA集合框架 (47)
- mfc框架 (52)
- abb框架断路器 (48)
- ui自动化框架 (47)
- beego框架 (52)
- java框架spring (58)
- grpc框架 (55)
- ppt框架 (48)
- 内联框架 (52)
- cad怎么画框架 (58)
- ps怎么画框架 (47)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)
- oracle提交事务 (47)