Quartz 学习笔记(一)任务调度框架 | 核心组件 Job、Trigger 和 Scheduler | 入门案例 | 监听器


参考资料: 视频资料

一、Quartz


Quartz 官网:scheduler.org
Quartz 是 OpenSymphon 开源组织发布的开源项目,可以和J2EE 和 J2SE 应用程序相结合,也可以单独使用。

Quartz 是开源且具有丰富特性的“任务调度库”,能够集成任何的Java应用,小到独立的应用,大到电子商业系统。Quartz既能创建简单,也能创建复杂的任务调度,以执行上十、上百,甚至上万的任务。任务 job 被定义为标准的Java组件,能够执行任何想要实现的功能。
Quartz 调度框架包含许多企业级的任务如 JTA 事务、 集群的支持。

简而言之,Quartz 就是基于Java实现的任务调度框架,用于执行自定义的任务。

二、Quartz 运行环境


  • Quartz 可以运行嵌入在另一个独立式应用程序
  • Quartz 可以在应用程序服务器(或Servlet容器)内被实例化,并且参与事务
  • Quartz 可以作为一个独立的程序运行(其自己的Java虚拟机内),可以通过RMI使用
  • Quartz 可以被实例化,作为独立的项目集群(负载均衡和故障转移功能),用于作业的执行

三、Quartz 核心组件


  • 任务 Job
    • Job 就是想要实现的任务类,每一个 Job 必须实现 org.quartz.job接口, 且只需要实现接口定义的 execute()方法
  • 触发器 Trigger
    • Trigger 为你执行任务的触发器,,比如每天定时3点发送一份统计邮件, Trigger将会设置3点进行执行该任务。
    • Trigger主要包含两种 SimpleTrigger 和 CronTrigger 两种
  • 调度器 Scheduler
    • Scheduler 为任务的调度器,它会将任务 Job 以及触发器 Trigger 整合起来,负责基于 Trigger 设定的时间来执行Job

四、Quartz 设计模式


  • Builder 模式
    官方案例中使用 newJob(字节码).withXXX.build()的方式创建工作
    在这里插入图片描述

  • Factory 模式
    官方案例中通过 StdSchedulerFactory类获取 调度器对象
    在这里插入图片描述

  • 组件模式
    Job、Trigger触发器 和 Scheduler调度器三个组件
    在这里插入图片描述

  • 链式编程
    Quartz的类其中部分方法返回的结果就是当前对象实例,所以可以支持链式编程
    在这里插入图片描述

五、Quartz 的体系结构


在这里插入图片描述

六、Quartz 的几个常用 API


以下是 Quartz 编程 API 的几个重要接口,也是 Quartz 的重要组件:

  • Scheduler 是用于与调度程序交互的主程序接口

Scheduler 调度程序,任务执行计划表,只有安排进执行计划的任务 job (通过 scheduler.schedulerJob方法安排进执行计划),当它预先定义的执行时间到了的时候(任务触发 Trigger),该任务才会执行。

  • Job 我们预先定义的希望在未来时间能被调度程序执行的时候,可以自定义。

  • JobDetail ,使用 jobDetail来定义定时任务的实例通过 ,JobBuilder类创建

  • JobDataMap,可以包含不限量(序列化的)数据对象,在 job 实例执行的时候,可以使用其中的数据; JobDataMap 是 Java Map接口的一个实现,额外增加了一些便于存取基本类型数据的方法。

  • Trigger 触发器,Trigger对象是用来执行Job的。当调度一个 Job 时,我们实例一个触发器会调整它的属性来满足 job 执行的条件。表明任务在什么时候会执行,定义了一个已被安排的任务将会在什么时候执行的条件,比如每2秒执行一次

  • JobBuilder 用于声明一个任务实例,也可以定义关于该任务的详情,比如任务名、组名等,这个声明的实例将会作为一个实际执行的任务。

  • TriggerBuilder 触发器创建器,用于创建触发器 trigger 实例

  • JobListener、TriggerListener、SchedulerLisener 监听器,用于对组件的监听。

七、Quartz 入门案例


项目结构:
在这里插入图片描述

引入Maven依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>groupId</groupId>
    <artifactId>quartzDemo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.2</version>
        </dependency>

        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
            <version>2.3.2</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>
    </dependencies>
</project>

自定义Job

package cn.uni.job;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.util.Date;

/**
 * 自定义 Quartz 框架里的任务
 */
public class MyJob implements Job {
   

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
   
        // 获取当前时间
        String t = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
        // 工作内容
        System.out.printf("[%s] 工作中...\n", t);
    }
}

定义 Scheduler、Trigger与测试

package cn.uni.main;

import cn.uni.job.MyJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class HelloSchedulerDemo {
   
    public static void main(String[] args) {
   
        try {
   
            // 1. 调度器 ( Scheduler ) 从工厂中获取调度的实例 (默认: 实例化 new StdSchedulerFactory())
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            // 2. 任务实例 ( JobDetail )
            JobDetail jobDetail = JobBuilder.newJob(MyJob.class) // 加载任务类, 与自定义的Job类进行绑定
                    // 参数1: 任务的名称 (唯一实例), 参数2:任务组名称
                    .withIdentity("job1", "jobGroup1")
                    .build();
            // 3. 触发器 (Trigger)
            SimpleTrigger trigger = TriggerBuilder.newTrigger()
                    // 参数1: 触发器的名称(唯一实例),参数2:触发器组的名称
                    .withIdentity("trigger1", "triggerGroup1")
                    // 设置每过 3 秒执行一次
                    .withSchedule(SimpleScheduleBuilder
                            .simpleSchedule()
                            .withIntervalInSeconds(3)
                            .repeatForever())
                    // 设置立马启动
                    .startNow()
                    .build();
            // 让调度器关联任务和触发器, 保证按照触发器定义的条件执行任务
            scheduler.scheduleJob(jobDetail, trigger);
            // 启动调度器
            scheduler.start();
            // 停止调度器
            // scheduler.shutdown();

        } catch (SchedulerException e) {
   
            throw new RuntimeException(e);
        }
    }
}

运行结果(每隔三秒执行一次自定义的Job):

[2022-07-08 11:23:09] 工作中...
[2022-07-08 11:23:12] 工作中...
[2022-07-08 11:23:15] 工作中...

八、Quartz组件详情


8.1 Job

Job:工作任务调度的接口,任务类需要实现该接口。该接口中定义 execute()方法,类似JDK提供的 TimeTask 类的run方法,在里面编写任务执行的业务逻辑

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

比如在入门案例七的基础上修改Job类如下:

package cn.uni.job;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.util.Date;

/**
 * 自定义 Quartz 框架里的任务
 */
public class MyJob implements Job {
   

    public MyJob(){
   
        System.out.println("hello, job!");
    }
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
   
        // 获取当前时间
        String t = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
        // 工作内容
        System.out.printf("[%s] 工作中...\n", t);
    }
}

运行结果:

hello, job!
[2022-07-08 12:34:38] 工作中...
hello, job!
[2022-07-08 12:34:41] 工作中...

从这里可以看出,Job类每次执行前都被重新定义过。

8.2 JobDetail

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

JobDetail jobDetail = JobBuilder.newJob(MyJob.class) // 加载任务类, 与自定义的Job类进行绑定
    // 参数1: 任务的名称 (唯一实例), 参数2:任务组名称
    .withIdentity("job1", "jobGroup1")
    .build();
System.out.println(
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值