看一篇搞懂quartz框架、spring boot整合quartz实现定时任务动态配置,附代码(保姆级教程二)

目的:一篇文章搞懂 Quartz 定时任务框架,从原理 到 Spring Boot 整合 到 CRUD 实际操作

说明: 这篇文章是从 Spring Boot 整合的角度来分析 Quartz 框架,介绍如何整合以及项目中怎么使用。

如果需要从原理角度一步一步分析的文章,请点击这个文章:quartz 原理组件介绍

一、Quartz 的作业存储类型

Quartz 的定时任务作业的存储类型有 2 种:内存(默认)、JDBC

1、内存:默认情况下 Quartz 会将任务调度存储在内存中,这种方式性能是最好的,因为内存的速度是最快的。不好的地方就是数据缺乏持久性,程序崩溃或者重新发布的时候,所有运行信息都会丢失。

2、JDBC:存数据库后,可以做单点也可以做集群,当任务多了之后,可以统一进行管理,随时停止、暂停、修改任务。 关闭或者重启服务器,运行的信息都不会丢失。缺点就是运行速度快慢取决于连接数据库的快慢

二、Spring Boot 整合 Quartz(基于内存)

2.1 基本配置

1、引入依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
  • 当我们引入spring-boot-starter-quartz的依赖后,spring boot 在启动的时候会自动加载配置类:org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,会初始化好调度器(源码:SchedulerFactoryBean实现InitializingBean,重写afterPropertiesSet() 里面就有了)

  • 而且 Scheduler,Spring 默认是启动的,不需要手动启动。

    @Autowired
    private Scheduler scheduler;
    

2、创建一个任务类继承 Job 类,重写 excute 方法,excute 里面的参数(JobExecutionContext context)表示:定时任务执行的环境(上下文)

@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Component
public class MyJob implements Job {
   
   

    // 编写任务内容
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
   
   
        // 获取JobDetail
        JobDetail jobDetail = context.getJobDetail();
        
        // 可以输出任务的一些详情信息
        System.out.println("任务名称:" + jobDetail.getKey().getName());
        System.out.println("任务分组名称" + jobDetail.getKey().getGroup());
        System.out.println("任务类名字:" + jobDetail.getJobClass().getName());
        System.out.println("本次任务执行时间:" + context.getFireTime());
        System.out.println("下次任务执行时间:" + context.getNextFireTime());

        // 还可以通过JobDataMa()存储数据
        JobDataMap jobDataMap = jobDetail.getJobDataMap();
        int count = jobDataMap.getInt("count");
        // 或者:Integer count1 = (Integer) jobDataMap.get("count");
        System.out.println("第" + count + "次执行");
        // 更新共享数据
        jobDataMap.put("count", ++count);
    }
}
2.1.1 启动定时任务 方式一

3、创建 JobDetail、创建 Trigger:

  • 创建一个配置类(比如:QuartzConfig),然后在配置类中写生成 JobDetail 对象的方法
  • 在配置类中写生成 Trigger 对象的方法
@Configuration
public class QuartzConfig {
   
   
    @Bean
    public JobDetail getJobDetail() {
   
   
        return JobBuilder
                // 任务绑定
                .newJob(MyJob.class)
                .storeDurably()
                // 定义唯一标识,区分其他任务
                .withIdentity("name任务名", "group任务组")
                .usingJobData("count", 1)
                .build();
    }

    @Bean
    public Trigger getTrigger() {
   
   
        // cron表达式
        String cron = "*/3 * * * * ?";
        return TriggerBuilder
                .newTrigger()
                // 唯一表示
                .withIdentity("trigger1", "group")
                // 绑定JobDetail
                .forJob(this.getJobDetail())
                .withSchedule(CronScheduleBuilder.cronSchedule(cron))
                .build();
    }
}

运行: 直接启动启动类,即可看到结果:

分析: 这里跟之前不一样,之前使用scheduler.scheduleJob(jobDetail, trigger); 来调度,这里直接将 JobDetail 放到 Trigger 中

注意: JobDetail 中一定要设置为可持久化.storeDurably(),否则运行报错

2.1.2 启动定时任务 方式二

3、不写配置类:初始化创建 JobDetail 和 Trigger,然后使用 Scheduler 来调用。

@Configuration
public class QuartzConfig2 {
   
   

    @Autowired
    private Scheduler scheduler;

    @PostConstruct
    public void init() throws SchedulerException {
   
   
        String cron = "*/3 * * * * ?";
        
        JobDetail jobDetail = JobBuilder
                .newJob(MyJob.class)
                .withIdentity("name任务名", "group任务组")
                .usingJobData("count", 1)
                .build();

        Trigger trigger = TriggerBuilder
                .newTrigger()
                // 唯一表示
                .withIdentity("trigger1", "group")
                .withSchedule(CronScheduleBuilder.cronSchedule(cron))
                .build();
        
        scheduler.scheduleJob(jobDetail, trigger);
    }
}

引入: 上面的整合运行后,不管是哪种启动定时任务方式,只要重启启动类,都会重新运行定时任务,不会j接着运行上次的。----> 下面这种基于 JDBC 的就可以做到这一点。

二、Spring Boot整合Quartz(基于JDBC)

上面提到基于存数据库后,可以进行统一的管理:随时停止、暂停、修改任务。其实这就是动态调度。

2.1 动态调度

1、动态定时任务:即定时任务的动态调度,可以根据需求自由进行任务的生成、暂停、恢复、删除和更新的操作。Quartz 本身没有提供动态调度功能,需要自己根据相关 API 开发(下面会提到)

2、使用场景:

  • 订单成功后自动发送短信通知

  • 每日推送功能引发用户不满,不再定时推送

  • 每次下班前30分钟发送工作报表,遇节假日暂停发送

3、Scheduler 调度器常用 API

API 描述
scheduler.scheduleJob(jobDetail, trigger) 生成一个新的定时任务
scheduler.pauseJob(jobKey) 暂停一个定时任务,参数 jobKey 代表该任务的唯一标识
scheduler.resumeJob(jobKey) 恢复一个定时任务,参数 jobKey 代表该任务的唯一标识
scheduler.deleteJob(jobKey) 删除一个定时任务,参数 jobKey 代表该任务的唯一标识
scheduler.rescheduleJob(triggerKey, trigger) 修改一个定时任务
scheduler.triggerJob(jobKey) 执行一次定时任务

2.2 关于JobKey类

JobKey 类,用于唯一标识一个调度任务(Job)。在 Quartz 中,任务是通过 JobKey 来识别和管理的。具体来说:JobKey 是 Quartz 中用于标识和引用任务的核心对象。

JobKey 的核心作用就是标识任务并提供对任务的访问方式。它就像任务的身份证,确保你能准确地访问、操作任务,避免任务名称重复或冲突。

1、 JobKey 的定义

JopKey 类主要由两个属性组成:

  • 任务名称:标识任务的名称,通常是唯一的字符串。
  • 任务组名:任务所属的组名,类似于任务的类别,任务组可以包含多个任务,任务组名也应该是唯一的

2、 JobKey 的构造

两种方式:

  • 通过名称和组名构造:

    JobKey jobKey = new JobKey("jobName","jobGroup");
    
  • 通过唯一标识符构造: 如果想避免重复的名称/组组合,可以使用 JobKey 的静态方法:

    JobKey jobKey = JobKey.jobKey("jobName", "jobGroup");
    

3、 JobKey 在调度器中的应用

  • 获取任务的触发器(Trigger):

    // 可以通过 Jobkey 获取与任务关联的所有触发器
    Set<Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
    
  • 获取任务的详细信息(JobDetail):

    JobDetail jobDetail = scheduler.getJobDetail(jobKey);
    
  • 获取任务的状态(TriggerState):

    TriggerState triggerState = scheduler.getTriggerState(triggerKey);
    

4、 JobKey 与 TriggerKey 的关系

  • JobKey 标识一个任务(Job),而 TriggerKey 标识与该任务关联的触发器(Trigger)
  • 一个 Job 可以有多个 Trigger,但是每个 Trigger 只能关联一个 Job

5、 JobKey 和 任务分组

通过 JobKey 中的 jobGroup 属性,可以将任务按组划分,使得任务管理更加有组织。任务组的好处包括:

  • 分组管理:可以按任务组来管理任务,查询某个组内的所有任务。
  • 按组删除任务:可以按组来批量删除任务。
  • 任务分隔:将不同类别的任务分隔开来,便于管理。

2.3 设置yml配置文件

1、引入依赖,并配置 yml 文件

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
spring:
  datasource:
    # 数据库配置
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/gxxxbixxxxaxx?useUnicode=true&characterEncoding=UTF-8
    username: xxx
    password: xxx

  # quartz配置
  quartz:
    # quartz任务存储类型:jdbc或memory
    job-store-type: jdbc
    # 是否等待任务执行完毕后,容器才会关闭
    wait-for-jobs-to-complete-on-shutdown: false
    # 配置的job是否覆盖已经存在的job信息
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小学鸡!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值