spring boot1.0 集成quartz 动态配置定时任务
转载自 https://www.imooc.com/article/36278
一、Quartz简介
了解 Quartz
Quartz 是一个完全由 Java 编写的开源作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制。
Quartz 可以与 J2EE 与 J2SE 应用程序相结合也可以单独使用。
Quartz 允许程序开发人员根据时间的间隔来调度作业。
Quartz 实现了作业和触发器的多对多的关系,还能把多个作业与不同的触发器关联。
Quartz 核心概念
Job 表示一个工作,要执行的具体内容。此接口中只有一个方法,如下:void execute(JobExecutionContext context)
JobDetail 表示一个具体的可执行的调度程序,Job 是这个可执行程调度程序所要执行的内容,另外 JobDetail 还包含了这个任务调度的方案和策略。
Trigger 代表一个调度参数的配置,什么时候去调。
Scheduler 代表一个调度容器,一个调度容器中可以注册多个 JobDetail 和 Trigger。当 Trigger 与 JobDetail 组合,就可以被 Scheduler 容器调度了。
集群Quartz应用
伸缩性
高可用性
负载均衡
Quartz可以借助关系数据库和JDBC作业存储支持集群。
Terracotta扩展quartz提供集群功能而不需要数据库支持
集成quartz,使用quartz,就要理解里面的声明
scheduler:任务调度器
trigger:任务触发器,用于定义任务调度时间规则
job:待执行的任务,即被调度的任务
misfire:没有启动,指本应该被执行但实际没有被执行的任务调度
1.1首先在pom文件加上quartz依赖,将下面maven依赖添加到 dependencies节点里面
<!-- quartz 使用了该jar包PlatformTransactionManager类 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<!-- 该依赖里面有spring对schedule的支持 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
2.2 配置定时器
一般spring常用的定时任务框架有:
2.2.1 Spring Schedule 这是spring自带的任务框架 优点就是配置简单,依赖少,缺点就是
同一个task,如果前一个还没跑完后面一个就不会触发,不同的task也不能同时运行。因为scheduler的默认线程数为1,配置pool-size为2的话,会导致同一个task前一个还没跑完后面又被触发的问题,不支持集群等。想了解的同学可以看下面代码
package com.imooc.quartz.task; import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import java.util.Date; /**
* spring自带任务框架,有弊端
*/
@Component
@EnableScheduling //必须加噢
public class SpringScheduleTask { /**
* 每分钟执行一次
*/
@Scheduled(cron = "0 0/1 * * * ?")
public void reptilian(){
System.out.println("执行调度任务:"+new Date());
}
}
2.2.2 Quartz 优点太多了,最主要有负载均衡,容错率高等特点,具体可以参考别人的分享
使首先先要创建一个任务调度器,触发器等
MethodInvokingJobDetailFactoryBean:此工厂主要用来制作一个jobDetail,即制作一个任务。由于我们所做的定时任务根本上讲其实就是执行一个方法。所以用这个工厂比较方便。
注意:其setTargetObject所设置的是一个对象而不是一个类。
CronTriggerFactoryBean:定义一个触发器。
注意:setCronExpression:是一个表达式,如果此表达式不合规范,即会抛出异常。
SchedulerFactoryBean:主要的管理的工厂,这是最主要的一个bean。quartz通过这个工厂来进行对各触发器的管理。
代码如下
package com.imooc.quartz.config; import com.imooc.quartz.task.QuartzTask;
import org.quartz.JobDetail;
import org.quartz.Trigger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean; /**
* 配置任务
*/
@Configuration
public class QuartzConfiguration { /**
* 配置任务
* @param quartzTask QuartzTask为需要执行的任务
* @return
*/
@Bean(name = "reptilianJob")
public MethodInvokingJobDetailFactoryBean detailFactoryBean(QuartzTask quartzTask) { MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean(); // 是否并发执行
jobDetail.setConcurrent(false); // 设置任务的名字
jobDetail.setName("reptilianJob"); // 设置任务的分组,在多任务的时候使用
jobDetail.setGroup("reptilianJobGroup"); // 需要执行的对象
jobDetail.setTargetObject(quartzTask); /*
* TODO 非常重要
* 执行QuartzTask类中的需要执行方法
*/
jobDetail.setTargetMethod("reptilian");
return jobDetail;
} /**
* 定时触发器
* @param reptilianJob 任务
* @return
*/
@Bean(name = "jobTrigger")
public CronTriggerFactoryBean cronJobTrigger(JobDetail reptilianJob){ CronTriggerFactoryBean tigger = new CronTriggerFactoryBean(); tigger.setJobDetail(reptilianJob); //cron表达式,每1分钟执行一次
tigger.setCronExpression("0 0/1 * * * ?");
tigger.setName("reptilianTrigger");
return tigger;
} /**
* 调度工厂
* @param jobTrigger 触发器
* @return
*/
@Bean(name = "scheduler")
public SchedulerFactoryBean schedulerFactory(Trigger jobTrigger) { SchedulerFactoryBean factoryBean = new SchedulerFactoryBean(); // 用于quartz集群,QuartzScheduler 启动时更新己存在的Job
factoryBean.setOverwriteExistingJobs(true); // 延时启动,应用启动1秒后
factoryBean.setStartupDelay(1); // 注册触发器
factoryBean.setTriggers(jobTrigger);
return factoryBean;
}
}
3创建需要执行的业务逻辑类
package com.imooc.quartz.task; import org.springframework.stereotype.Service; import java.util.Date; /**
* 使用quartz框架
*/
@Service
public class QuartzTask { /**
* 业务逻辑
*/
public void reptilian(){
System.out.println("执行业务处理逻辑:"+new Date());
}
}
4定时查询数据库,并更新任务
package com.example.demo.service; import com.example.demo.mapper.ConfigMapper;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import javax.annotation.Resource; /**
* 路径:com.example.demo.config
* 类名:
* 功能:定时产查询数据库,并更新任务
* 备注:
* 创建人:typ
* 创建时间:2018/10/10 14:15
* 修改人:
* 修改备注:
* 修改时间:
*/
@Slf4j
@Configuration
@EnableScheduling
@Component
public class ScheduleRefreshService { @Autowired
private ConfigMapper configMapper; @Resource(name = "jobDetail")
private JobDetail jobDetail; @Resource(name = "jobTrigger")
private CronTrigger cronTrigger; @Resource(name = "scheduler")
private Scheduler scheduler; /**
* 方法名:
* 功能:每隔10s查库,并根据查询结果决定是否重新设置定时任务
* 描述:
* 创建人:typ
* 创建时间:2018/10/10 14:19
* 修改人:
* 修改描述:
* 修改时间:
*/
@Scheduled(fixedRate = 10000)
public void scheduleUpdateCronTrigger() throws SchedulerException {
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(cronTrigger.getKey());
//当前Trigger使用的
String currentCron = trigger.getCronExpression();
log.info("currentCron Trigger:{}", currentCron);
//从数据库查询出来的
String searchCron = configMapper.findOne(1).getCron();
log.info("searchCron Trigger:{}", searchCron); if (currentCron.equals(searchCron)) {
// 如果当前使用的cron表达式和从数据库中查询出来的cron表达式一致,则不刷新任务
} else {
//表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(searchCron);
//按新的cronExpression表达式重新构建trigger
trigger = (CronTrigger) scheduler.getTrigger(cronTrigger.getKey());
trigger = trigger.getTriggerBuilder().withIdentity(cronTrigger.getKey()).withSchedule(scheduleBuilder).build();
// 按新的trigger重新设置job执行
scheduler.rescheduleJob(cronTrigger.getKey(), trigger);
currentCron = searchCron;
}
}
}
spring boot1.0 集成quartz 动态配置定时任务的更多相关文章
- Spring/Spring boot正确集成Quartz及解决@Autowired失效问题
周五检查以前Spring boot集成Quartz项目的时候,发现配置错误,因此通过阅读源码的方式,探索Spring正确集成Quartz的方式. 问题发现 检查去年的项目代码,发现关于QuartzJo ...
- Spring Boot2.0+中,自定义配置类扩展springMVC的功能
在spring boot1.0+,我们可以使用WebMvcConfigurerAdapter来扩展springMVC的功能,其中自定义的拦截器并不会拦截静态资源(js.css等). @Configur ...
- Django + Celery 实现动态配置定时任务
哈喽,今天给大家分享一篇Django+Celery实现动态配置定时任务,因为最近也是无意间看到一位大佬关于这块的文章,然后自己觉得不错,也想学习写一下,然后最终实现功能是在前端页面统一管理计划任务,大 ...
- Spring Cloud 整合 nacos 实现动态配置中心
上一篇文章讲解了Spring Cloud 整合 nacos 实现服务注册与发现,nacos除了有服务注册与发现的功能,还有提供动态配置服务的功能.本文主要讲解Spring Cloud 整合nacos实 ...
- 基于Django+celery二次开发动态配置定时任务 ( 二)
一.需求 结合上一篇,使用djcelery模块开发定时任务时,定时任务的参数都保存在djcelery_periodictask表的args.kwargs字段里,并且是json格式.那么,当定时任务多了 ...
- celery 动态配置定时任务
How to dynamically add or remove tasks to celerybeat? · Issue #3493 · celery/celery https://github.c ...
- springBoot集成 quartz动态定时任务
项目中需要用到定时任务,考虑了下java方面定时任务无非就三种: 用Java自带的timer类.稍微看了一下,可以实现大部分的指定频率的任务的调度(timer.schedule()),也可以实现关闭和 ...
- springboot整合Quartz实现动态配置定时任务
前言 在我们日常的开发中,很多时候,定时任务都不是写死的,而是写到数据库中,从而实现定时任务的动态配置,下面就通过一个简单的示例,来实现这个功能. 一.新建一个springboot工程,并添加依赖 & ...
- Spring 与 Quartz 动态配置(数漫江湖)
因为项目的需求,需要有动态配置计划任务的功能.本文在 Quartz JobBean 中获取配置的 Quartz cronExpression 时间表达式及 Spring Bean 的对象名.方法名并运 ...
随机推荐
- 检查 TCP 80 端口是否正常工作
检查 TCP 80 端口是否正常工作 2017-09-13 22:12:50 目录 Windows Server 2012 Windows Server 2008 CentOS 7.3 Ubuntu ...
- kolla queens on centos7.5 -all in one
目录 环境准备 开始配置 快照,快照,快照 pull镜像并部署 登录配置OpenStack 环境准备 我这里用workstation创建了一个虚拟机,安装centos7.5 mini系统,这台虚拟机上 ...
- package.json文件解析
1.用途:管理你所安装的npm包的依赖,在开发过程中能清楚的查询安装的包的版本以及项目中使用的包依赖,便于开发组成员共享. 2.创建:可以手动创建也可以通过npm init 自动创建. 3.配置项: ...
- spring boot 给返回值加状态 BaseData
JavaWeb开发中,需要给前端返回的数据加上一些头部的状态信息,来表示请求成功或失败的状态原因 一.数据添加状态信息 1.新建BaseData public class BaseData<T& ...
- MySQL(进阶部分)
视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,并可以将其当作表来使用. SELECT * FROM ( SEL ...
- python_装饰器
越来越觉得写一点技术博客是有多么重要了,明日复明日,现在就开始写吧! 1. 普通装饰器 装饰器的写法是一种语法糖,装饰器也还是一个函数而已,它接收一个函数对象作为参数,并返回一个新函数,主要是拓展原函 ...
- MongoDB(3)--Java 操作 MongoDB 的 API
引入mongoDb 依赖 <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-j ...
- Python第5天
今日学习的主要内容: 数据类型和变量的总结:(可变:列表,字典)(不可变:字符串,数字,元组) 引出集合概念:不同元素,无序,不可变类型 set方法—>集合 add添加:clear清空:pop删 ...
- PHP超全局变量$_SERVER分析
$_SERVER 是一个包含了诸如头信息(header).路径(path).以及脚本位置(script locations)等等信息的数组.这个数组中的项目由 Web 服务器创建.不能保证每个服务器都 ...
- 使用 nodeJs 开发微信公众号(配置服务器)
流程如下: 1. 申请微信公众号:企业号.服务号.订阅号(前两个要钱) 2. 配置微信公众号后台 选择基本配置,获得 AppId 和 AppSecret ,点击服务器配置 URL:你服务器地址,不能是 ...