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

时间:2022-12-29 17:33:40

什么是动态配置定时任务?

首先说下这次主题,动态配置。没接触过定时任务的同学可以先看下此篇:JAVA定时任务实现的几种方式

定时任务实现方式千人千种,不过基础的无外乎 1、JDK 的Timer类 2、Quartz 3、SpringTask  。生产上三种方式我都有使用过。但是使用过程中用的最多的便是xml配置的方式,这种方式最简单,无代码侵入,也比较好理解。
但是却有个致命的缺点,比如你要改某个任务的触发时间,亦或是你要新增一个任务,暂停一个任务。怎么做?
停应用!改XML配置!重新启动!
是不是很致命。最近重新研究了下Quartz的配置,实现了不停机添加、暂停、删除、立即触发任务的方法,在本篇分享出来,其实也不算是完全的研究,在上家公司已经有大佬实现了,这次是也是基于大佬的理解重新实现下。

国际惯例~先看效果图   ps:文末有彩蛋哦~~

管理界面:

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

效果图:实在不知道该跑什么了,每隔十秒打一段话吧

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

技术实现

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 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;

实现步骤

①启动项目,启动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,这里仅介绍一些常用的,想要了解更多可以稍后看下彩蛋部分。

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):

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

第三步:根据任务调度运行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 implements Job{ @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);
}

彩蛋部分~

好了,正文部分基本上就这些,不多废话了,本文没有太多的讲解原理,只是简单的应用,水平不够还望大家见谅。

看了上面的效果图是不是还是有种看的见摸不着的感觉,老爷爷这里也做了个线上的实例供大家体验~有兴趣的同学可以亲自试验一下。

实例地址:http://www.laoyeye.net/management/index  账号/密码:test/123456  菜单:系统设置/计划任务

当然了还有最重要的源码和API文档我也不会忘的。

源码地址:https://github.com/allanzhuo/yyblog

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

最后的最后,看都看了,码字不易,顺手点个赞白~^_^

Quartz实现JAVA定时任务的动态配置的更多相关文章

  1. Quartz 在 Spring 中如何动态配置时间--转

    原文地址:http://www.iteye.com/topic/399980 在项目中有一个需求,需要灵活配置调度任务时间,并能*启动或停止调度. 有关调度的实现我就第一就想到了Quartz这个开源 ...

  2. Springboot自带定时任务实现动态配置Cron参数

    同学们,我今天分享一下SpringBoot动态配置Cron参数.场景是这样子的:后台管理界面对定时任务进行管理,可动态修改执行时间,然后保存入库,每次任务执行前从库里查询时间,以达到动态修改Cron参 ...

  3. Springboot定时任务实现动态配置Cron参数&lpar;从外部数据库获取&rpar;

    https://blog.csdn.net/qq_35992900/article/details/80429245 我们主要讲解它的动态配置使用方法. 在刚开始使用的时候,我们更改一个任务的执行时间 ...

  4. Spring 3整合Quartz 2实现定时任务:动态添加任务

    先展示一下后台管理定时任务效果图: 1.新增任务页面: 2.列表页(实现任务的禁用启用) 3.数据库脚本: -- ------------------------------ Table struct ...

  5. Quartz实现分布式可动态配置的定时任务

    关键词: 1. 定时任务 2. 分布式 3. 可动态配置触发时间 一般通过Quartz实现定时任务很简单.如果实现分布式定时任务需要结合分布式框架选择master节点触发也可以实现.但我们有个实际需求 ...

  6. springboot整合Quartz实现动态配置定时任务

    前言 在我们日常的开发中,很多时候,定时任务都不是写死的,而是写到数据库中,从而实现定时任务的动态配置,下面就通过一个简单的示例,来实现这个功能. 一.新建一个springboot工程,并添加依赖 & ...

  7. spring boot 整合 quartz 集群环境 实现 动态定时任务配置【原】

    最近做了一个spring boot 整合 quartz  实现 动态定时任务配置,在集群环境下运行的 任务.能够对定时任务,动态的进行增删改查,界面效果图如下: 1. 在项目中引入jar 2. 将需要 ...

  8. Quartz动态配置表达的方法

    在项目中有一个需求,需要灵活配置调度任务时间,并能*启动或停止调度.有关调度的实现我就第一就想到了Quartz这个开源调度组件,因为很多项目使用过,Spring结合Quartz静态配置调度任务时间, ...

  9. Spring 与 Quartz 动态配置(数漫江湖)

    因为项目的需求,需要有动态配置计划任务的功能.本文在 Quartz JobBean 中获取配置的 Quartz cronExpression 时间表达式及 Spring Bean 的对象名.方法名并运 ...

随机推荐

  1. js无参数对象

    <script type="text/javascript"> var o={ a : function(){ for (var i = arguments.lengt ...

  2. Theano:LSTM源码解析

    最难读的Theano代码 这份LSTM代码的作者,感觉和前面Tutorial代码作者不是同一个人.对于Theano.Python的手法使用得非常娴熟. 尤其是在两重并行设计上: ①LSTM各个门之间并 ...

  3. CSAPP Lab2&colon; Binary Bomb

    著名的CSAPP实验:二进制炸弹 就是通过gdb和反汇编猜测程序意图,共有6关和一个隐藏关卡 只有输入正确的字符串才能过关,否则会程序会bomb终止运行 隐藏关卡需要输入特定字符串方会开启 实验材料下 ...

  4. 观察者模式与Boost&period;Signals

      1)  观察者模式定义 略,各种设计模式的书上都有定义. 2)  观察者模式一般实现 观察者模式一般实现,都是“被观察者”保存一个“观察者”的列表,循环这个列表来通知“观察者”.代码,其中使用了b ...

  5. &lpar;汉化改进作品&rpar;BruteXSS:Xss漏洞扫描脚本

    今天给大家进行汉化改进的事一款脚本工具:BruteXSS,这款脚本能自动进行插入XSS,而且可以自定义攻击载荷. 该脚本也同时提供包含了一些绕过各种WAF(Web应用防护系统)的语句.   0×01简 ...

  6. Oracle问题整合

    1.安装Oracle和ado.net连接Oracle 在“环境变量”的“系统变量”中[必须添加]: ORACLE_HOME = C:\instantclient_11_2 TNS_ADMIN = C: ...

  7. TensorFlow总结

    第一 基础 1. 定义变量 #定义维度为[2,3], 平均值为·1, 标准差为1,类型为float32,名称为w1的服从正态分布的变量 w1 = tf.Variable(tf.random_norma ...

  8. CF 573B

    Bear and Blocks time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...

  9. linux常用命令:ls命令

    ls命令是linux下最常用的命令.ls命令就是list的缩写,缺省下ls用来打印出当前目录的清单,如果ls指定其他目录那么就会显示指定目录里的文件及文件夹清单. 通过ls 命令不仅可以查看linux ...

  10. makefile基本操作

    多数内容copy自youtube的一个视频:https://www.youtube.com/watch?v=E1_uuFWibuM 执行环境:原作者是在Linux下做的视频,而我使用的是win10,w ...