1.1 Quartz 概述

Quartz 是 OpenSymphony 开源组织在任务调度领域的一个开源项目,完全基于 Java 实现。该项目于 2009 年被 Terracotta 收购,目前是 Terracotta 旗下的一个项目。读者可以到 http://www.quartz-scheduler.org/站点下载 Quartz 的发布版本及其源代码。

1.2 Quartz特点

作为一个优秀的开源调度框架,Quartz 具有以下特点:

强大的调度功能,例如支持丰富多样的调度方法,可以满足各种常规及特殊需求;
灵活的应用方式,例如支持任务和调度的多种组合方式,支持调度数据的多种存储方式;
分布式和集群能力,Terracotta 收购后在原来功能基础上作了进一步提升。
另外,作为 Spring 默认的调度框架,Quartz 很容易与 Spring 集成实现灵活可配置的调度功能。

quartz调度核心元素:

  • Scheduler:任务调度器,是实际执行任务调度的控制器。在spring中通过SchedulerFactoryBean封装起来。
  • Trigger:触发器,用于定义任务调度的时间规则,有SimpleTrigger,CronTrigger,DateIntervalTrigger和NthIncludedDayTrigger,其中CronTrigger用的比较多,本文主要介绍这种方式。CronTrigger在spring中封装在CronTriggerFactoryBean中。
  • Calendar:它是一些日历特定时间点的集合。一个trigger可以包含多个Calendar,以便排除或包含某些时间点。
  • JobDetail:用来描述Job实现类及其它相关的静态信息,如Job名字、关联监听器等信息。在spring中有JobDetailFactoryBean和 MethodInvokingJobDetailFactoryBean两种实现,如果任务调度只需要执行某个类的某个方法,就可以通过MethodInvokingJobDetailFactoryBean来调用。
  • Job:是一个接口,只有一个方法void execute(JobExecutionContext context),开发者实现该接口定义运行任务,JobExecutionContext类提供了调度上下文的各种信息。Job运行时的信息保存在JobDataMap实例中。实现Job接口的任务,默认是无状态的,若要将Job设置成有状态的,在quartz中是给实现的Job添加@DisallowConcurrentExecution注解(以前是实现StatefulJob接口,现在已被Deprecated),在与spring结合中可以在spring配置文件的job detail中配置concurrent参数。

1.3 Quartz 集群配置

quartz集群是通过数据库表来感知其他的应用的,各个节点之间并没有直接的通信。只有使用持久的JobStore才能完成Quartz集群。
数据库表:以前有12张表,现在只有11张表,现在没有存储listener相关的表,多了QRTZ_SIMPROP_TRIGGERS表:

  • 建表sql 点这里
    如果没有积分可以留言,我发给你哦。只是可能会比较晚

    QRTZ_LOCKS就是Quartz集群实现同步机制的行锁表,包括以下几个锁:CALENDAR_ACCESS 、JOB_ACCESS、MISFIRE_ACCESS 、STATE_ACCESS 、TRIGGER_ACCESS。

动手

记得要先新建数据库,新建默认创建的11 张表哦

导入maven 依赖

 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--quartz--><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.2.1</version></dependency><!--因为quartz 需要有Spring context 所有引入mail包--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.zaxxer</groupId><artifactId>HikariCP</artifactId><version>3.2.0</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId></dependency>

QuartzConfig

package com.abel.quartz.config;import java.beans.PropertyVetoException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;import com.zaxxer.hikari.HikariDataSource;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.Trigger;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;/*** Created by yangyibo on 2019/1/16.*/
@Configuration
public class QuartzConfig {/*** 1.通过name+group获取唯一的jobKey;2.通过groupname来获取其下的所有jobkey*/final static String GROUP_NAME = "QuartzJobGroups";@Value("${quartz.scheduler.instanceName}")private String quartzInstanceName;@Value("${spring.datasource.driverClassName}")private String myDSDriver;@Value("${spring.datasource.url}")private String myDSUrl;@Value("${spring.datasource.username}")private String myDSUser;@Value("${spring.datasource.password}")private String myDSPassword;@Value("${org.quartz.dataSource.myDS.maxConnections}")private int myDSMaxConnections;/*** 设置属性** @return* @throws IOException*/private Properties quartzProperties() throws IOException {Properties prop = new Properties();// 调度标识名 集群中每一个实例都必须使用相同的名称prop.put("quartz.scheduler.instanceName", quartzInstanceName);// ID设置为自动获取 每一个必须不同prop.put("org.quartz.scheduler.instanceId", "AUTO");// 禁用quartz软件更新prop.put("org.quartz.scheduler.skipUpdateCheck", "true");prop.put("org.quartz.scheduler.jmx.export", "true");// 数据库代理类,一般org.quartz.impl.jdbcjobstore.StdJDBCDelegate可以满足大部分数据库prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate");// 数据保存方式为数据库持久化prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");// 数据库别名 随便取prop.put("org.quartz.jobStore.dataSource", "quartzDataSource");//prop.put("org.quartz.jobStore.dataSource", "myDS");// 表的前缀,默认QRTZ_prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");// 是否加入集群prop.put("org.quartz.jobStore.isClustered", "true");// 调度实例失效的检查时间间隔prop.put("org.quartz.jobStore.clusterCheckinInterval", "20000");prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");// 信息保存时间 ms 默认值60秒prop.put("org.quartz.jobStore.misfireThreshold", "120000");prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE");// 程池的实现类(一般使用SimpleThreadPool即可满足几乎所有用户的需求)prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");// 定线程数,至少为1(无默认值)(一般设置为1-100之间的整数合适)prop.put("org.quartz.threadPool.threadCount", "10");// 设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1,默认为5)prop.put("org.quartz.threadPool.threadPriority", "5");prop.put("org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread", "true");prop.put("org.quartz.plugin.triggHistory.class", "org.quartz.plugins.history.LoggingJobHistoryPlugin");prop.put("org.quartz.plugin.shutdownhook.class", "org.quartz.plugins.management.ShutdownHookPlugin");prop.put("org.quartz.plugin.shutdownhook.cleanShutdown", "true");//#自定义连接池//org.quartz.dataSource.myDS.connectionProvider.class=com.poly.pay.schedule.DruidConnectionProviderreturn prop;}/*** 数据源** @return* @throws PropertyVetoException*/@Beanpublic HikariDataSource createDataSource() throws PropertyVetoException {HikariDataSource dataSource = new HikariDataSource();dataSource.setJdbcUrl(myDSUrl);dataSource.setDriverClassName(myDSDriver);dataSource.setUsername(myDSUser);dataSource.setPassword(myDSPassword);dataSource.setMaximumPoolSize(myDSMaxConnections);return dataSource;}/*** 创建触发器工厂** @param jobDetail* @param cronExpression* @return*/private static CronTriggerFactoryBean cronTriggerFactoryBean(JobDetail jobDetail, String cronExpression) {CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean();factoryBean.setJobDetail(jobDetail);factoryBean.setCronExpression(cronExpression);return factoryBean;}/****************************************************以下配置需要注意******************************************************//*** 调度工厂* 此处配置需要调度的触发器 例如 executeJobTrigger** @param executeJobTrigger* @return* @throws IOException* @throws PropertyVetoException*/@Beanpublic SchedulerFactoryBean schedulerFactoryBean(@Qualifier("executeJobTrigger") Trigger executeJobTrigger) throws IOException, PropertyVetoException {SchedulerFactoryBean factory = new SchedulerFactoryBean();// this allows to update triggers in DB when updating settings in config file://用于quartz集群,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了factory.setOverwriteExistingJobs(true);//用于quartz集群,加载quartz数据源//factory.setDataSource(dataSource);//QuartzScheduler 延时启动,应用启动完10秒后 QuartzScheduler 再启动//factory.setStartupDelay(10);//用于quartz集群,加载quartz数据源配置factory.setAutoStartup(true);factory.setQuartzProperties(quartzProperties());factory.setApplicationContextSchedulerContextKey("applicationContext");factory.setDataSource(createDataSource());//注册触发器Trigger[] triggers = {executeJobTrigger};factory.setTriggers(triggers);return factory;}/*** 加载触发器** 新建触发器进行job 的调度  例如 executeJobDetail* @param jobDetail* @return*/@Bean(name = "executeJobTrigger")public CronTriggerFactoryBean executeJobTrigger(@Qualifier("executeJobDetail") JobDetail jobDetail) {//每天凌晨3点执行return cronTriggerFactoryBean(jobDetail, "0 1 0 * * ? ");}/*** 加载job** 新建job 类用来代理*** @return*/@Beanpublic JobDetailFactoryBean executeJobDetail() {return createJobDetail(InvokingJobDetailFactory.class, GROUP_NAME, "executeJob");}/*** 执行规则job工厂** 配置job 类中需要定时执行的 方法  execute* @param jobClass* @param groupName* @param targetObject* @return*/private static JobDetailFactoryBean createJobDetail(Class<? extends Job> jobClass,String groupName,String targetObject) {JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();factoryBean.setJobClass(jobClass);factoryBean.setDurability(true);factoryBean.setRequestsRecovery(true);factoryBean.setGroup(groupName);Map<String, String> map = new HashMap<>();map.put("targetMethod", "execute");map.put("targetObject", targetObject);factoryBean.setJobDataAsMap(map);return factoryBean;}}

InvokingJobDetailFactory


package com.abel.quartz.config;import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.lang.reflect.Method;/*** Created by yangyibo on 2019/2/1.*/
public class InvokingJobDetailFactory extends QuartzJobBean {/*** 计划任务所在类*/private String targetObject;/*** 具体需要执行的计划任务*/private String targetMethod;private ApplicationContext ctx;@Overrideprotected void executeInternal(JobExecutionContext context) throws JobExecutionException {try {Object obj = ctx.getBean(targetObject);Method m = null;try {m = obj.getClass().getMethod(targetMethod);//调用被代理对象的方法m.invoke(obj);} catch (SecurityException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();}} catch (Exception e) {throw new JobExecutionException(e);}}public void setApplicationContext(ApplicationContext applicationContext) {this.ctx = applicationContext;}public void setTargetObject(String targetObject) {this.targetObject = targetObject;}public void setTargetMethod(String targetMethod) {this.targetMethod = targetMethod;}
}

ExecuteJob

package com.abel.quartz.job;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;/*** Created by yangyibo on 2019/2/1.*/
@Service
public class ExecuteJob {private static final Logger logger = LoggerFactory.getLogger(ExecuteJob.class);/*** 方法名在quartz定义*/public void execute() {System.out.println("定时任务执行了。。。。。");}
}

application.properties

## tomcat配置
server.port=8090
#server.tomcat.maxHttpHeaderSize=8192
server.tomcat.uri-encoding=UTF-8
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
spring.messages.encoding=UTF-8
# tomcat最大线程数,默认为200
server.tomcat.max-threads=800
# session最大超时时间(分钟),默认为30
server.session-timeout=60## spring 配置
spring.application.name=springboot-Quartz
application.main=com.abel.quartz.Application## 主数据源,默认的
spring.datasource.url=jdbc:mysql://localhost:3306/quart?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driverClassName=com.mysql.jdbc.Driver## 连接池配置
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
#最小空闲连接
spring.datasource.hikari.minimum-idle=10
#连接池中允许的最大连接数。缺省值:10;推荐的公式:((core_count * 2) + effective_spindle_count)
spring.datasource.hikari.maximum-pool-size=30
#spring.datasource.hikari.auto-commit=true
#一个连接idle状态的最大时长(毫秒),超时则被释放(retired),缺省:10分钟。minimumIdle<maximumPoolSize时生效
spring.datasource.hikari.idle-timeout=120000
#自定义连接池名
#spring.datasource.hikari.pool-name=DatebookHikariCP
#一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired),缺省:30分钟,建议设置比数据库超时时长少30秒,参考MySQL wait_timeout参数(show variables like '%timeout%';)
spring.datasource.hikari.max-lifetime=1800000
#等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒
spring.datasource.hikari.connection-timeout=30000
#指定验证连接有效性的超时时间,默认是5秒
spring.datasource.hikari.validation-timeout=3000
spring.datasource.hikari.connection-test-query=SELECT 1# 调度标识名 集群中每一个实例都必须使用相同的名称
quartz.scheduler.instanceName=QuartScheduler
# 允许最大连接
org.quartz.dataSource.myDS.maxConnections=10

源代码地址:https://github.com/527515025/springBoot/tree/master/springboot-Quartz
参考资料:https://blog.csdn.net/lkl_csdn/article/details/73613033

springBoot-Quartz 定时任务相关推荐

  1. SpringBoot Quartz 定时任务详解

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/80657415 本文出自[赵彦军的博客] Quartz 简介 在 JavaEE系统中 ...

  2. springboot+Quartz整合!!!简单实用

    一.什么是Quartz 在Quartz官网上是这么写的 Quartz官网 1.Quartz 是一个完全由 Java 编写的开源作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制 ...

  3. 第四十章:基于SpringBoot Quartz完成定时任务分布式多节点负载持久化

    在上一章[第三十九章:基于SpringBoot & Quartz完成定时任务分布式单节点持久化]中我们已经完成了任务的持久化,当我们创建一个任务时任务会被quartz定时任务框架自动持久化到数 ...

  4. Springboot 使用quartz 定时任务 增删改查

    前段时间公司项目用到了 定时任务 所以写了一篇定时任务的文章 ,浏览量还不错 , Springboot 整合定时任务 ) 所以就准备写第二篇, 如果你是一名Java工程师,你也可以会看到如下的页面 , ...

  5. Springboot集成quartz定时任务可视化配置​​​​​​​

    转自我的个人博客:Springboot集成quartz定时任务可视化配置 使用quartz定时任务已经有一段时间了,今天记录一下Springboot 2.x集成Quartz. 1.引入quartz j ...

  6. springboot+quartz构建定时任务

    springboot+quartz构建定时任务 开发环境 Quartz的3个基本要素 如何使用 引入相关依赖 resource目录下创建quartz.properties quartz需要用到的表 实 ...

  7. SpringBoot+Quartz动态管理定时任务

    前置理论: 1.小顶堆(适合任务少的,因为向下调整耗费性能) 堆:是一完全二叉树(除了最后一层节点其他层都达到最大节点数,且最后一层都靠左排列):堆中某个节点的值总不大于或不小于其父节点. 定时任务是 ...

  8. springboot、quartz定时任务未触发

    spring boot.quartz定时任务不触发 定时每隔5分钟触发一次 但是定时任务没有触发,不知道为什么? 若您知道原因,请留言谢谢 解决办法 针对多模块,若要一个web模块启动定时器模块,那么 ...

  9. Springboot集成Quartz定时任务yml文件配置方式

    构建maven项目,引入maven依赖包 其中quartz.quartz-jobs.spring-boot-starter-quartz.spring-context-support  四个依赖包为q ...

  10. 解决springboot + quartz的分布式问题以及dolphinscheduler

    springboot + quartz 将quartz存储默认在内存中, 多节点部署时存在分布式问题. 改成基于数据库的quartz分布式集群解决方案, 参考官方文档, 需要为quartz单独配置da ...

最新文章

  1. 批量导出表数据到CSV文件
  2. python getcwd 与dirname_python慎用os.getcwd() ,除非你知道【文件路径与当前工作路径的区别】...
  3. python读txt文件 数组-python将txt等文件中的数据读为numpy数组的方法
  4. R,让你的数据分析更简便!
  5. scala 学习笔记--集合
  6. 校园网络项目PT模拟
  7. nacos替代config-server和Euraka
  8. 面试留“家庭作业”的公司,都TM是耍流氓!
  9. 区块链隐私保护(一): 交易层的隐私保护机制
  10. 计算机设备管理器更新驱动器,怎么利用设备管理器更新显卡驱动 - 驱动管家
  11. VS Code 中解决 C++ 代码编写时的爆红
  12. python绘画海贼王_Python爬虫实战之(三)| 一个海贼迷的呐喊
  13. 游戏首选高性能台式机显示器,240hz的刷新率够吗?
  14. CSDN不友好的收藏夹
  15. SecureCRT Backspace/delete 键失效的解决方法
  16. 【MD】markdown符号表
  17. 邻接矩阵/图/DFS/BFS
  18. Ubuntu启动错误——Kernel panic - not syncing VFS unable to mount root fs on unknown-block 0 0
  19. zbb20170218_hibernate
  20. 【Java】函数式编程学习笔记——Stream流

热门文章

  1. python pip install pil_python安装PIL库
  2. python相减函数subs,SUBS(subs是什么函数)
  3. 开启服务器防火墙 局域网内连接sqlserver数据库问题
  4. 网站搭建:从零搭建个人网站教程(10)
  5. 河海大学2021年硕士研究生招考公告
  6. linux 网络速度非常慢,解决Ubuntu 10.04上网速度慢的问题
  7. linux下操作3G模块
  8. 网站关键词密度定义,关键词密度对网站优化有什么关系!
  9. 看你知道多少种水凝胶的改性及其分类
  10. python bmp转jpg