Spring Boot整合Quartz

一、简介

类名描述
Scheduler与调度器交互的主要API(实际上这个就是调度器)
Joborg.quartz.Job希望由调度器执行的组件,是一个接口,也就是我们使用的时候被调度的任务需要实现此接口
JobDetailorg.quartz.JobDetail用来定义job的实例
Triggerorg.quartz.Trigger触发器,定义JobDetail的执行计划的组件
JobBuilderorg.quartz.JobBuilder用于定义或者构建JobDetail执行计划实例
TriggerBuilderorg.quartz.TriggerBuilder用于定义或者构建Trigger触发器实例

二、SpringBoot整合Quartz

1.引入依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
2.application.yml配置
spring:    
   quartz:
        # 持久化-数据库方式存储
        job-store-type: jdbc
        # 相关属性配置
        properties:
            org:
                quartz:
                    scheduler:
                        instanceName: amazonInterfaceScheduler
                        instanceId: AUTO
                    jobStore:
                        class: org.quartz.impl.jdbcjobstore.JobStoreTX
                        driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
                        tablePrefix: QRTZ_
                        isClustered: true
                        clusterCheckinInterval: 10000
                        useProperties: false
                        # sqlserver 启用
                        selectWithLockSQL: SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?
                    # 线程池的参数配置
                    threadPool:
                        class: org.quartz.simpl.SimpleThreadPool
                        threadCount: 10
                        threadPriority: 5
                        threadsInheritContextClassLoaderOfInitializingThread: false
3.选择数据库初始化sql

官方sql地址:https://github.com/quartz-scheduler/quartz/tree/master/quartz-core/src/main/resources/org/quartz/impl/jdbcjobstore

三、Quartz使用

1.JobTrigger

一个job(自定义实现org.quartz.Job接口的类)可以有多个JobDetail实例。一个Job可以有多个Trigger,但一个Trigger不能对应多个Job

1.1、job

Job 指的是你想要执行的任务类,每一个 Job 必须实现 org.quartz.job 接口,且只需要实现接口定义的 execute() 方法。在 execute 方法内编写任务的业务逻辑。

1.2、Trigger

Trigger用来触发Job的执行。Trigger也有一个关联的JobDataMap,可用于将参数传递给由特定Trigger触发的Job实例。Quartz提供了很多不同的Trigger类型,但最常用的是SimpleTriggerCronTrigger

Trigger 主要包含两种:

  • SimpleTrigger
  • CronTrigger
1.3、Cron表达式

Cron表达式是由7个子表达式组成的字符串,关于 Cron 的各个域的定义如下表格所示:

是否必填值以及范围通配符
0-59, - * /
0-59, - * /
0-23, - * /
1-31, - * ? / L W
1-12JAN-DEC, - * /
1-7SUN-SAT, - * ? / L #
1970-2099, - * /
运算符含义
*表示匹配该域的任意值,假如在Minutes域使用*, 即表示每分钟都会触发事件。
/表示值的增量,从一个值开始,每间隔多少时间后再次执行,可以出现在所有的字段。如在分钟字段上, 0/15表示从0分开始, 间隔15分钟执行一次, 相当于0,15,30,45
,表示多个值, 可以出现在所有的字段。 如果我们在 “分” 这个域中定义为 8,12,35 ,则表示分别在第8分,第12分 第35分执行该定时任务。
-表示一个区间。如果我们在 “时” 这个域中定义 1-6,则表示在1到6点之间每小时都触发一次。
?表示不指定值。使用的场景为不需要关心当前设置这个字段的值。例如:要在每月的8号触发一个操作,但不关心是周几,我们可以这么设置 0 0 0 8 * ?
LL是 Last 的缩写, 可以出现在月中的天和周中的天这两个字段, 当时含义不一样。 在月中的天这个字段中, L表示这个月的最后一天。 而在周中的天中, 如果L单独出现, 那么就表示7或者SAT即星期六, 如果出现在一个数字的后面, 那么就表示这个月的周几, 如“6L”, 表示这个月的最后一个周五
W表示离指定日期的最近那个工作日(周一至周五)触发,只能在 “日” 中使用且只能用在具体的数字之后。若在“日”上置”15W”,表示离每月15号最近的那个工作日触发。假如15号正好是周六,则找最近的周五(14号)触发, 如果15号是周未,则找最近的下周一(16号)触发.如果15号正好在工作日(周一至周五),则就在该天触发。如果是 “1W” 就只能往本月的下一个最近的工作日推不能跨月往上一个月推。
#表示每月的第几个周几,只能作用于 “周” 上。例如 2#3表示在每月的第三个周二。

示例:

  1. 0 0/5 * * * ?:每5分钟执行一次
  2. 10 0/5 * * * ?:每5分钟的第10秒的时候执行一次,如:10:00:10, 10:05:10 …
  3. 0 30 10-13 ? * WED,FRI:每周三和周五的10:30/11:30/12:30/13:30执行
  4. 0 0/30 8-9 5,20 * ?:每月5号和20号的8:00/8:30/9:00/9:30执行
1.4、使用CronTrigger触发器创建Trigger实例
CronTrigger trigger = TriggerBuilder
    .newTrigger()
    .withIdentity(TriggerKey.triggerKey("triggerName", "triggerGroup"))
    .withSchedule(CronScheduleBuilder
                  .cronSchedule(StrUtil.trimToEmpty("0 0/5 * * * ?"))
                  .withMisfireHandlingInstructionIgnoreMisfires())
    .build();

2.JobJobDetail

  • JobJobDetail 的区分,Job是指我们具体的「任务类」。JobDetail指通过 JobBuilder 类创建出的一个实例,它和Job 类进行了绑定。

  • Job 实例在 Quartz 中的生命周期:每次调度器执行 Job 时,它在调用 execute 方法前会创建一个新的Job 实例(JobDetail),当调用完成之后,关联的 Job 对象实例会被释放,释放的实例会被垃圾回收机制回收。

  • JobDetail: JobDetail 为 Job 实例提供许多设置属性,以及jobDataMap 成员变量属性,它用来存储特定 Job 实例的状态信息,调度器需要借助 JobDetail 对象来添加 Job 实例。

2.1、job
public class DumbJob implements Job {
    public void execute(JobExecutionContext context) throws JobExecutionException {
        // 通过JobExecutionContext对象访问到Quartz运行时候的环境以及Job本身的明细数据
        JobKey key = context.getJobDetail().getKey();
        JobDataMap dataMap = context.getMergedJobDataMap();  
        // TODO:处理逻辑
    }  
}
2.2、根据job类创建JobDetail实例
JobDetail jobDetail = JobBuilder
    .newJob(DumbJob.class)
    .withIdentity(JobKey.jobKey("jobName", "jobGroup"))
    .build();
// 根据jobDetail和trigger注册任务
scheduler.scheduleJob(jobDetail, trigger);

3.Identities

Identities其实就是调度任务和触发器的身份标识。当JobTrigger注册到Quartz的调度器中的时候需要定义相应的识别标记(其实就是JobKeyTriggerKey)。调度任务和触发器(JobKeyTriggerKey)的识别标记中允许使用“分组(group)”,这对于组织你的工作和触发诸如“报告工作”和“维护工作”等类别是有用的。作业或触发器的键的名称部分必须在组内是惟一的—换句话说,作业或触发器的完整键(或标识符)是名称(name)和组别(group)的复合。这里可以先这样理解,JobKey(namegroup)是JobDetail的联合主键,TriggerKey(namegroup)是Trigger的联合主键。

JobTrigger 注册到 Scheduler 时,可以为它们设置 key,配置其身份属性。同一个分组下的JobTrigger 的名称必须唯一,即一个 JobTriggerkey 由名称(name)和分组(group)组成。

4.JobDataMap

4.1、概述

(1).在进行任务调度时JobDataMap存储在JobExecutionContext中,非常方便获取。

(2).JobDataMap可以用来装载任何可以序列化的数据对象,当job实例对象被执行时这些参数对象会传递给它。

(3).JobDataMap实现了JDKMap接口,并且添加了一些非常方便的方法用来存取数据基本数据类型。

4.2、JobDataMap放置数据对象
// trigger实例放置
trigger.getJobDataMap().put("triggerData", "triggerDataValue");
// jobDetail实例放置
jobDetail.getJobDataMap().put("jobDetailData", "jobDetailDataValue");

4.3、JobDataMap获取数据对象

JobExecutionContext 将会合并JobDetailTriggerJobDataMap,如果其中属性名相同,后者将覆盖前者。可以使用JobExecutionContext.getMergedJobDataMap()方法来获取合并后的JobDataMap

public class DumbJob implements Job {
    public void execute(JobExecutionContext context) throws JobExecutionException {
        // JobDataMap获取数据对象
        String triggerDataValue = (String)context.getMergedJobDataMap().get("triggerData");  
        // TODO:处理逻辑
    }  
}

5.Job的状态与并发

有几个注解,可以添加到Job实现类上,以影响Quartz的行为。

  1. @DisallowConcurrentExecution注解可以添加到Job实现类上,告诉Quartz不要同时执行给定Job定义的多个实例(指向该Job实现类的)。参考上文中提到的例子,假设DumbJob类添加了这个注解,那么同一时刻只能有一个DumbJob类的实例在运行。

    因此,这里所说的不同实例是以JobDetail为基础的而不是Job实现类。之所以要把这个注解添加到Job实现类上,只是因为Job实现类的代码修改更方便。

  2. @PersistJobDataAfterExecution注解可以添加到Job实现类上,告诉Quartzexecute()方法成功执行(没有抛异常)后,更新存储的JobDataMap数据。这样,同一个JobDetail下次执行时就能获取到更新后的数据了。与@DisallowConcurrentExecution一样,这个注解也是以JobDetail为基础区分的,而不是Job实现类。

    如果要使用@PersistJobDataAfterExecution,强烈建议同时添加@DisallowConcurrentExecution注解,以避免多个实例同时更新Job数据。

6.Quartz执行流程

1、scheduler是一个计划调度器容器(总部),容器里面可以盛放众多的JobDetailtrigger,当容器启动后,里面的每个JobDetail都会根据trigger按部就班自动去执行。

2、JobDetail是一个可执行的工作,它本身可能是有状态的。

3、Trigger代表一个调度参数的配置,什么时候去调。

4、当JobDetailTriggerscheduler容器上注册后,形成了装配好的作业(JobDetailTrigger所组成的一对儿),就可以伴随容器启动而调度执行了。

创建jobDetailtrigger –> 根据JobDetail提供的Job类型创建一个Job class的实例 –>Scheduler注册 –> Scheduler执行Job时,调用其execute()方法 –> Job class的实例被丢弃,Jvm的垃圾回收器会将它们回收

项目中可以通过配置在execute()方法通过反射执行逻辑所在的方法,这样就可以通过配置数据库来实现作业任务了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值