帝国网站模板下载,国家示范校建设网站,什么做电子书下载网站好,四秒网站建设动态配置Quartz。没接触过定时任务的同学可以先看下此篇#xff1a;JAVA定时任务实现的几种方式 文章目录一、需求背景1. 问题现象2. 问题分析3. 解决方案二、需求背景2.1. maven依赖2.2. 创建一个任务表2.3. 实现步骤三、代码逻辑3.1. Quartz配置3.2. 启动项目#xff0c;加… 动态配置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的API4.1. 新增一个job4.2. 暂停一个job4.2. 删除一个job4.3. 暂停一个job4.4. 立即执行一个job4.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 --
dependencygroupIdorg.quartz-scheduler/groupIdartifactIdquartz/artifactIdversion2.2.1/version
/dependency
dependencygroupIdorg.springframework/groupIdartifactIdspring-context-support/artifactId
/dependency2.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)
) ENGINEMyISAM AUTO_INCREMENT32 DEFAULT CHARSETutf8;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();}// 创建scheduleBean(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 {// 这里获取任务信息数据ListTaskDO 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 gitgitee.com:gb_90/yyblog.git5.3. 项目运行
#1.进入下载的项目目录
cd yyblog
#2.切换分支到1.0
git checkout 1.0
#3.初始化数据库(sql在lib下面)
#4.修改数据库连接(application.yml)
#5.启动项目
链接http://localhost:8080
账号admin
密码123456Quartz文档地址https://github.com/allanzhuo/yyblog/tree/master/doc