• Spring Boot 框架学习笔记(七)整合Quartz调度框架


    简介

    QuartzOpenSymphony开源组织在Job scheduling领域又一个开源项目,完全由Java开发,可以用来执行定时任务。
    Quartz可以与J2EE和J2SE应用程序相结合也可以单独使用。

    运行环境

    • 嵌入独立的应用程序
    • 在应用程序服务器(或servlet容器)内被实例化,参与事务
    • 作为一个独立程序运行,可以通过RMI使用
    • 可以作为独立的项目集群被实例化(负载平衡和故障转移功能),用于作业执行

    核心概念

    1. 任务Job

    需要实现的任务类,每个job都必须实现org.quartz.job接口,实现 execute() 方法,执行后完成任务。

    //通过JobBulider构建一个任务实例
    JobDetail jobDetail = JobBuilder.newJob(xxxJob.class);
    
    • 1
    • 2
    1. 触发器 Trigger

    执行任务的触发器(定时),主要包含SimpleTriggerCronTrigger以及自定义Trigger

    //通过TriggerBuilder构建触发器实例
     SimpleTrigger trigger = TriggerBuilder.newTrigger();
    
    • 1
    • 2
    1. 调度器 Scheduler

    任务调度器,负责基于 Trigger触发器设定的时间来执行Job任务。

    //从调度工厂获取
    Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
    
    • 1
    • 2

    任务存储方式

    Quartz提供了两种存储任务的方式:

    • Memory:内存方式,将任务存储到内存中,当项目重启时就会丢失,不建议生产环境使用。
    • Jdbc:数据库方式,将任务存储到Quartz提供的固定结构的表内,项目重启任务不会丢失。

    常用API

    • Scheduler:用于定时调度程序交互的主程序接口。

    Scheduler调度程序:任务执行计划表,通过scheduler.scheduleJob方法安排进执行任务,当到了预先定义的执行时间的时候触发trigger,执行任务

    • Job:可自定义的在未来某个时间能被调度程序执行的任务类
    • JobDetail:使用JobDetail来定义定时任务的实例,JobDetail实例是通过JobBuilder类创建的
    • JobDataMap:可以包含不限量(序列化的)的数据对象,在Job实例执行的时候,可以使用其中的数据;

    JobDataMapJava Map接口的一个实现,额外增加了一些便于存取基本类型数据的方法

    • Trigger:触发器,触发执行Job任务。定义一个已被安排的任务将在什么时候执行的时间条件
    • JobBuilder:用于声明一个任务实例,也可以定义关于该任务的详情比如任务名,组名等。通过JobBuilder声明的实例将会作为一个实际执行的任务。
    • TriggerBuilder:触发器创建器,用于创建触发器trigger实例
    • JobListener、TriggerListener、SchedulerListener:监听器,用于对组件的监听

    使用案例

    1. 添加依赖

    springboot版本2.0之后

       <!--quartz依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-quartz</artifactId>
            </dependency>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    springboot版本较低

     <!--核心包-->
    <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>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2. 创建任务类实现Job接口,或者继承QuartzJobBean抽象类

    实现Job接口

    /**
     * 任务类
     * */
    public class HelloJob implements Job {
        static int i = 1;
        @Override
        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            System.out.println("第"+i+++"次"+"Hello,Quartz!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    继承QuartzJobBean抽象类

    /**
     * 任务类
     * */
    public class HelloJob extends QuartzJobBean {
        static int i = 1;
    
        @Override
        protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
            System.out.println("第"+i+++"次"+"Hello,Quartz!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    QuartzJobBean是由Spring提供,实现org.quartz.Job接口,是对Quartz内置任务接口的实现封装,源码如下:

    public abstract class QuartzJobBean implements Job {
        public QuartzJobBean() {
        }
    
        public final void execute(JobExecutionContext context) throws JobExecutionException {
            try {
                BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
                MutablePropertyValues pvs = new MutablePropertyValues();
                pvs.addPropertyValues(context.getScheduler().getContext());
                pvs.addPropertyValues(context.getMergedJobDataMap());
                bw.setPropertyValues(pvs, true);
            } catch (SchedulerException var4) {
                throw new JobExecutionException(var4);
            }
    
            this.executeInternal(context);
        }
    
        protected abstract void executeInternal(JobExecutionContext var1) throws JobExecutionException;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    较于Job接口的优点
    • 自动将实现类实例加入IOC

    使用QuartzJobBean来创建自定义任务时,Spring会自动扫描项目内的实现类,将每一个实现类通过反射机制创建出实例并将实例写入到IOC容器内。

    • 可在实现类内注入实例

    直接使用Quartz时,如果自定义任务类实例不加入IOC容器,我们无法在自定义任务类注入Service

    3. 创建调度类调度执行

    实现Job

    /**
     * 调度器
     * */
    public class HelloSchedulerDemo {
        public static void main(String[] args) throws SchedulerException {
            //1.从调度工厂获取调度器实例
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            //2. 通过JobBulider构建一个任务实例
            JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
                    //设置任务的唯一实例名和任务组的组名
                    .withIdentity("helloJob","helloGroup")
                    //构建实例
                    .build();
            //3. 通过TriggerBuilder构建触发器实例
            SimpleTrigger trigger = TriggerBuilder.newTrigger()
                    //设置触发器唯一实例名和触发器组名
                    .withIdentity("helloTrigger","helloGroup")
                    //执行计划,每3秒执行一次
                    .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(3))
                    //立即执行
                    .startNow()
                    //构建实例
                    .build();
            //4. 调度器绑定任务实例和触发器
            scheduler.scheduleJob(jobDetail,trigger);
            //5.开始定时任务
            scheduler.start();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    在这里插入图片描述

    继承QuartzJobBean

    • 创建配置类
    
    
    • 1

    详细说明

    Job和JobDetail

    • JOB

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

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

    • JobDetail

    JobDetail:作用是绑定 Job,每次Scheduler调度执行一个Job的时候,首先会拿到对应的Job,然后创建该Job实例,再去执行Job中的execute()的内容,任务执行结束后,关联的Job对象实例会被释放,且会被JVM GC清除。除此之外,JobDetail为Job实例提供了许多设置属性

    • 为什么要使用Job+JobDetail模式,而不是直接使用Job

    JobDetail定义任务属性,Job定义任务逻辑
    任务有可能并发执行,当直接使用Job的时候,Job实例可能出现并发访问的情况。
    使用Job+JobDetail模式,每次调度执行都会生成一个Job实例,这样就不用担心并发访问的问题

    JobExecutionContext

    Scheduler调用一个Job,就会将JobExecutionContext传递给Jobexecute()方法
    Job能通过JobExecuteContext对象访问到Quartz运行时的环境以及Job本身的明细数据

  • 相关阅读:
    猿创征文|一篇打通架构设计,Java设计模式10,建造者模式
    Bandizip批量解压遇到的问题
    Django基础入门操作 (Django-01)
    分享从零开始学习网络设备配置--任务4.2 使用IPv6静态及默认路由实现网络连通
    【SpringBoot】打包成Docker镜像后日志输出中文乱码
    Nacos的使用和踩过的一些坑
    客快物流大数据项目(八十七):ClickHouse的使用案例
    (附源码)spring boot校园万能跑系统 毕业设计 160934
    python 集合
    resultMap 和 resultType的用法和区别详解
  • 原文地址:https://blog.csdn.net/qq_47267252/article/details/125522259