• 《SpringBoot篇》19.SpringBoot整合Quart


    陈老老老板
    说明:工作了,学习一些新的技术栈和工作中遇到的问题,边学习边总结,各位一起加油。需要注意的地方都标红了,还有资源的分享. 一起加油。
    本文是介绍Quartz与SpringBoot整合

    一、Quartz简介

    1.简介

    可以先看一下Quartz官网:Quartz官网
    说明:在整合之前先学习一下什么是QUartz:Quartz是一个功能丰富的开源作业调度库,可以集成到几乎任何Java应用程序中,Quartz 是 OpenSymphony 开源组织在 Job Scheduling 领域又一个开源项目,是完全由 Java 开发的一个开源任务日程管理系统,“任务进度管理器”就是一个在预先确定(被纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统。 Quartz 是一个开源的作业调度框架,它完全由 Java 写成,并设计用于 J2SE 和 J2EE 应用中,它提供了巨大的灵活性而不牺牲简单性。(也就是定时任务,确定好时间,就按指定时间执行)

    2.​核心概念:

    • 工作(Job):用于定义具体执行的工作,是一个接口,只定义一个方法execute() 方法,在实现接口的 execute() 方法中编写所需要定时执行的 Job。
    • 工作明细(JobDetail):用于描述定时工作相关的信息,包括了任务的唯一标识和具体要执行的任务,可以通过 JobDataMap 往任务中传递数据
    • 触发器(Trigger):描述了工作明细与调度器的对应关系,是一个,描述触发 Job (工作)执行的时间触发规则
      说明:主要有 SimpleTrigger 和 CronTrigger 这两个子类。
      SimpleTrigger 当且仅当需调度一次或者以固定时间间隔周期执行调度,是最适合的选择;
      CronTrigger 则可以通过 Cron 表达式定义出各种复杂时间规则的调度方案:(如工作日周一到周五的 15:00 ~ 16:00 执行调度等)
    • 调度器(Scheduler):用于描述触发工作的执行规则,通常使用cron表达式定义规则。通过 Trigger 和 JobDetail 可以用来调度、暂停和删除任务。调度器就相当于一个容器,装载着任务和触发器,该类是一个接口,代表一个 Quartz 的独立运行容器,Trigger 和 JobDetail 可以注册到 Scheduler 中,两者在 Scheduler 中拥有各自的组及名称,组及名称是 Scheduler 查找定位容器中某一对象的依据,Trigger 的组及名称必须唯一,JobDetail 的组和名称也必须唯一(但可以和 Trigger 的组和名称相同,因为它们是不同类型的)

    ​注:简单说就是你定时干什么事情,这就是工作,工作不可能就是一个简单的方法,还要设置一些明细信息。

    3.作业存储类型

    • RAMJobStore:RAM 也就是内存,默认情况下 Quartz 会将任务调度存储在内存中,这种方式性能是最好的,因为内存的速度是最快的。不好的地方就是数据缺乏持久性,但程序崩溃或者重新发布的时候,所有运行信息都会丢失
    • JDBC 作业存储:存到数据库之后,可以做单点也可以做集群,当任务多了之后,可以统一进行管理,随时停止、暂停、修改任务。关闭或者重启服务器,运行的信息都不会丢失。缺点就是运行速度快慢取决于连接数据库的快慢

    二、SpringBoot整合Quartz

    这里演示使用的是第一种内存存储作业信息,较为简单,只需在properties中设置即可。

    1、创建项目

    在这里插入图片描述

    2.添加依赖

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-quartzartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    整体依赖

     <dependencies>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starterartifactId>
            dependency>
    
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-testartifactId>
                <scope>testscope>
            dependency>
    
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-quartzartifactId>
            dependency>
        dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2.配置文件

    (1)创建quartz.properties

    ​注:默认情况下,Quartz 会加载 classpath 下的 quartz.properties 作为配置文件。如果找不到,则会使用 quartz 框架自己 jar 包下 org/quartz 底下的 quartz.properties 文件

    #主要分为scheduler、threadPool、jobStore、dataSource等部分
    
    
    org.quartz.scheduler.instanceId=AUTO
    org.quartz.scheduler.instanceName=DefaultQuartzScheduler
    #如果您希望Quartz Scheduler通过RMI作为服务器导出本身,则将“rmi.export”标志设置为true
    #在同一个配置文件中为'org.quartz.scheduler.rmi.export'和'org.quartz.scheduler.rmi.proxy'指定一个'true'值是没有意义的,如果你这样做'export'选项将被忽略
    org.quartz.scheduler.rmi.export=false
    #如果要连接(使用)远程服务的调度程序,则将“org.quartz.scheduler.rmi.proxy”标志设置为true。您还必须指定RMI注册表进程的主机和端口 - 通常是“localhost”端口1099
    org.quartz.scheduler.rmi.proxy=false
    org.quartz.scheduler.wrapJobExecutionInUserTransaction=false
    
    
    #实例化ThreadPool时,使用的线程类为SimpleThreadPool
    org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
    #threadCount和threadPriority将以setter的形式注入ThreadPool实例
    #并发个数  如果你只有几个工作每天触发几次 那么1个线程就可以,如果你有成千上万的工作,每分钟都有很多工作 那么久需要50-100之间.
    #只有1到100之间的数字是非常实用的
    org.quartz.threadPool.threadCount=5
    #优先级 默认值为5
    org.quartz.threadPool.threadPriority=5
    #可以是“true”或“false”,默认为false
    org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true
    
    
    #在被认为“misfired”(失火)之前,调度程序将“tolerate(容忍)”一个Triggers(触发器)将其下一个启动时间通过的毫秒数。默认值(如果您在配置中未输入此属性)为60000(60秒)
    org.quartz.jobStore.misfireThreshold=5000
    # 默认存储在内存中,RAMJobStore快速轻便,但是当进程终止时,所有调度信息都会丢失
    #org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore
    
    #持久化方式,默认存储在内存中,此处使用数据库方式
    org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
    #您需要为JobStore选择一个DriverDelegate才能使用。DriverDelegate负责执行特定数据库可能需要的任何JDBC工作
    # StdJDBCDelegate是一个使用“vanilla”JDBC代码(和SQL语句)来执行其工作的委托,用于完全符合JDBC的驱动程序
    org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
    #可以将“org.quartz.jobStore.useProperties”配置参数设置为“true”(默认为false),以指示JDBCJobStore将JobDataMaps中的所有值都作为字符串,
    #因此可以作为名称 - 值对存储而不是在BLOB列中以其序列化形式存储更多复杂的对象。从长远来看,这是更安全的,因为您避免了将非String类序列化为BLOB的类版本问题
    org.quartz.jobStore.useProperties=true
    #表前缀
    org.quartz.jobStore.tablePrefix=QRTZ_
    #数据源别名,自定义
    org.quartz.jobStore.dataSource=qzDS
    
    
    • 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
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    关于quartz全部配置详情可以点击查看
    ​注:其实不需要这么多想简单入门可以按如下的配置
    quartz.properties

    org.quartz.scheduler.instanceName = MyScheduler
    org.quartz.threadPool.threadCount = 3
    org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
    
    • 1
    • 2
    • 3
    • org.quartz.scheduler.instanceName - 设置调度程序scheduler的名称为MyScheduler
    • org.quartz.threadPool.threadCount - 线程里设置了3个线程,意味着最多同时运行3个job
    • org.quartz.jobStore.class - 指定为RAMJobStore,表示所有Quartz的数据,包括jobDetail、trigger等均运行在内存中(而不是数据库中)。 如果你想Quartz使用你的数据库,还是建议你在使用数据库配置之前使用RAMJobStore进行工作。通过使用一个数据库,你可以打开一个全新的维度,但在这之前,建议你使用RAMJobStore。

    3、定义任务Bean,按照Quartz的开发规范制作,继承QuartzJobBean

    public class MyQuartz extends QuartzJobBean {
        @Override
        protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        //这里是你想执行的任务信息
        //可以使用context参数获取其他信息,联系上下文
            System.out.println("quartz task run...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4、创建Quartz配置类,定义工作明细(JobDetail)与触发器的(Trigger)bean

    @Configuration
    public class QuartzConfig {
        @Bean
        public JobDetail printJobDetail(){
            //绑定具体的工作(newJob中的参数,就是要执行的Job类)
            //storeDurably()用来做持久化
            return JobBuilder.newJob(MyQuartz.class).storeDurably().build();
        }
        @Bean
        public Trigger printJobTrigger(){
        //	创建cron表达式表示什么时间执行,一般日期和星期不一起出现                   每两秒执行一次
            ScheduleBuilder schedBuilder = CronScheduleBuilder.cronSchedule("0/2 * * * * ?");
            //绑定对应的工作明细   forJob中写上面JobDetail(任务明细)的方法名
            return  TriggerBuilder.newTrigger().forJob(printJobDetail()).withSchedule(schedBuilder).build();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    CronScheduleBuilder.cronSchedule(“0/5 * * * * ?”);这里使用的是cron表达式,下一篇博客会有详解。

    ​工作明细中要设置对应的具体工作,使用newJob()操作传入对应的工作任务类型即可。

    5.测试

    点击启动类,启动项目,就会发现每两秒执行一次。
    在这里插入图片描述
    在这里插入图片描述

    ​注:​触发器需要绑定任务,使用forJob()操作传入绑定的工作明细对象。此处可以为工作明细设置名称然后使用名称绑定,也可以直接调用对应方法绑定。触发器中最核心的规则是执行时间,此处使用调度器定义执行时间,执行时间描述方式使用的是cron表达式。有关cron表达式的规则,各位小伙伴可以去参看相关课程学习,略微复杂,而且格式不能乱设置,不是写个格式就能用的,写不好就会出现冲突问题。

    三、简单定时任务使用Task

    ​说明:​spring根据定时任务的特征,将定时任务的开发简化到了极致。要做定时任务总要告诉容器,然后定时执行什么任务直接告诉对应的bean什么时间执行就行了。

    1、开启定时任务功能,在引导类上开启定时任务功能的开关,使用注解@EnableScheduling

    @SpringBootApplication
    //开启定时任务功能
    @EnableScheduling
    public class Springboot22TaskApplication {
        public static void main(String[] args) {
            SpringApplication.run(Springboot22TaskApplication.class, args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2、定义Bean,在对应要定时执行的操作上方,使用注解@Scheduled定义执行的时间,执行时间的描述方式还是cron表达式

    @Component
    public class MyBean {
        @Scheduled(cron = "0/1 * * * * ?")
        public void print(){
            System.out.println(Thread.currentThread().getName()+" :spring task run...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    ​ 如何想对定时任务进行相关配置,可以通过配置文件进行

    spring:
      task:
       	scheduling:
          pool:
           	size: 1							# 任务调度线程池大小 默认 1
          thread-name-prefix: ssm_      	# 调度线程名称前缀 默认 scheduling-      
            shutdown:
              await-termination: false		# 线程池关闭时等待所有任务完成
              await-termination-period: 10s	# 调度线程关闭前最大等待时间,确保最后一定关闭
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    总结:定时任务是工作中必须掌握的内容。希望对您有帮助,感谢阅读

    结束语:裸体一旦成为艺术,便是最圣洁的。道德一旦沦为虚伪,便是最下流的。
    勇敢去做你认为正确的事,不要被世俗的流言蜚语所困扰。

  • 相关阅读:
    生态环境综合管理信息化平台推动生态环境部门数字化转型
    【luogu P3403】跳楼机(图论)
    数字化仪的超声波应用
    Redis基本命令和常用数据类型
    《数字图像处理-OpenCV/Python》连载(22)绘制直线与线段
    vue3双向绑定原理(对比vue2)
    基于局部结构特征的图像匹配
    Dubbo项目搭建(简单部署)
    WPS如何转PDF格式?WPS转PDF怎么转?
    创建一个基本的win32窗口
  • 原文地址:https://blog.csdn.net/weixin_47343544/article/details/127329274