SpringBoot官方支持任务调度框架,轻量级用起来也挺不错!

Springboot 整合 Quartz(定时任务框架) Quartz是 OpenSymphony 开源组织在 Job scheduling 领域又一个开源项目,完全由 Java 开发,可以用来执行定时任务,类似于 java.util.Timer。持久性作业 - 就是保持调度定时的状态;作业管理 - 对调度作业进行有效的管理; 阅读详情

推荐阅读:

摘要

之前我们讲过一个分布式任务调度框架PowerJob,可以通过可视化的方式来进行任务调度。但是有时候我们只是需要一个轻量级的任务调度功能,而PowerJob需要搭建调度中心未免有些重,这时候SpringBoot官方支持的任务调度框架Quartz就派上用场了!本文主要介绍Quartz在SpringBoot中的使用,让你在实现任务调度上有更多的选择!

Quartz简介

Quartz是一款功能强大的开源任务调度框架,几乎可以集成到任何Java应用程序中(小到单机应用,大到分布式应用)。Quartz可用于创建简单或复杂的任务调度,用以执行数以万计的任务。任务被定义为标准化的Java组件,Java编写的任务都可以被执行。

核心概念

Quartz中有一些比较核心的概念,理解它们对使用Quartz很有帮助!

  • Scheduler(调度器):Quartz中的任务调度器,通过Trigger和JobDetail可以用来调度、暂停和删除任务。
  • Trigger(触发器):Quartz中的触发器,可以通过CRON表达式来指定任务执行的时间,时间到了会自动触发任务执行。
  • JobDetail(任务详情):Quartz中需要执行的任务详情,包括了任务的唯一标识和具体要执行的任务,可以通过JobDataMap往任务中传递数据。
  • Job(任务):Quartz中具体的任务,包含了执行任务的具体方法。

CRON表达式

Cron表达式是一个字符串,包括6~7个时间元素,在Quartz中可以用于指定任务的执行时间。

CRON的语法格式

Seconds Minutes Hours DayofMonth Month DayofWeek
复制代码

CRON格式中每个时间元素的说明

时间元素可出现的字符有效数值范围
Seconds, - * /0-59
Minutes, - * /0-59
Hours, - * /0-23
DayofMonth, - * / ? L W0-31
Month, - * /1-12
DayofWeek, - * / ? L #1-7或SUN-SAT

CRON格式中特殊字符说明

字符作用举例
,列出枚举值在Minutes域使用5,10,表示在5分和10分各触发一次
-表示触发范围在Minutes域使用5-10,表示从5分到10分钟每分钟触发一次
*匹配任意值在Minutes域使用*, 表示每分钟都会触发一次
/起始时间开始触发,每隔固定时间触发一次在Minutes域使用5/10,表示5分时触发一次,每10分钟再触发一次
?在DayofMonth和DayofWeek中,用于匹配任意值在DayofMonth域使用?,表示每天都触发一次
#在DayofMonth中,确定第几个星期几1#3表示第三个星期日
L表示最后在DayofWeek中使用5L,表示在最后一个星期四触发
W表示有效工作日(周一到周五)在DayofMonth使用5W,如果5日是星期六,则将在最近的工作日4日触发一次

在线CRON表达式生成器

其实CRON表达式无需多记,需要使用的时候直接使用在线生成器就可以了,地址:cron.qqe2.com/

整合SpringBoot使用

接下来我们讲下如何在SpringBoot中使用Quartz来实现任务调度,在电商系统中往往会有需要定时发送邮件或者站内信的需求,我们以此为场景来实现下!

  • Quartz存储任务信息有两种方式,使用内存或者使用数据库来存储,这里我们采用数据库存储的方式,首先需要新建Quartz的相关表,建表脚本在项目的resources目录下,名称为tables_mysql.sql,创建成功后数据库中多出11张表;

  • 接下来在pom.xml中添加Quartz的相关依赖即可,SpringBoot官方已经给我们提供好了相关Starter;
<!--SpringBoot集成QuartZ-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
  • 在application.yml中添加Quartz相关配置,配置说明直接看注释就好了,主要是对scheduler、jobStore和threadPool进行配置;
spring:
  quartz:
    job-store-type: jdbc # quartz任务存储类型:jdbc或memory
    wait-for-jobs-to-complete-on-shutdown: true # 关闭时等待任务完成
    overwrite-existing-jobs: true # 可以覆盖已有的任务
    properties: # quartz原生配置
      org:
        quartz:
          scheduler:
            instanceName: scheduler # 调度器实例名称
            instanceId: AUTO # 调度器实例ID自动生成
          jobStore:
            class: org.quartz.impl.jdbcjobstore.JobStoreTX # 调度信息存储处理类
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate # 使用完全兼容JDBC的驱动
            tablePrefix: QRTZ_ # quartz相关表前缀
            useProperties: false # 是否将JobDataMap中的属性转为字符串存储
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool # 指定线程池实现类,对调度器提供固定大小的线程池
            threadCount: 10 # 设置并发线程数量
            threadPriority: 5 # 指定线程优先级
  • 创建任务调度业务接口,定义好三个方法,分别为通过CRON表达式调度任务、调度指定时间的任务和取消定时任务;
/**
 * Quartz定时任务操作类
 * Created by macro on 2020/9/27.
 */
public interface ScheduleService {
    /**
     * 通过CRON表达式调度任务
     */
    String scheduleJob(Class<? extends Job> jobBeanClass, String cron, String data);

    /**
     * 调度指定时间的任务
     */
    String scheduleFixTimeJob(Class<? extends Job> jobBeanClass, Date startTime, String data);

    /**
     * 取消定时任务
     */
    Boolean cancelScheduleJob(String jobName);
}
  • 创建任务调度业务实现类,通过Scheduler、CronTrigger、JobDetail的API实现相关方法;
/**
 * Quartz定时任务操作实现类
 * Created by macro on 2020/9/27.
 */
@Slf4j
@Service
public class ScheduleServiceImpl implements ScheduleService {
    @Autowired
    private Scheduler scheduler;
    private String defaultGroup = "default_group";

    @Override
    public String scheduleJob(Class<? extends Job> jobBeanClass, String cron, String data) {
        // 创建需要执行的任务
        String jobName = UUID.fastUUID().toString();
        JobDetail jobDetail = JobBuilder.newJob(jobBeanClass)
                .withIdentity(jobName, defaultGroup)
                .usingJobData("data", data)
                .build();
        //创建触发器,指定任务执行时间
        CronTrigger cronTrigger = TriggerBuilder.newTrigger()
                .withIdentity(jobName, defaultGroup)
                .withSchedule(CronScheduleBuilder.cronSchedule(cron))
                .build();
        //使用调度器进行任务调度
        try {
            scheduler.scheduleJob(jobDetail, cronTrigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.info("创建定时任务失败!");
        }
        return jobName;
    }

    @Override
    public String scheduleFixTimeJob(Class<? extends Job> jobBeanClass, Date startTime, String data) {
        //日期转CRON表达式
        String startCron = String.format("%d %d %d %d %d ? %d",
                DateUtil.second(startTime),
                DateUtil.minute(startTime),
                DateUtil.hour(startTime, true),
                DateUtil.dayOfMonth(startTime),
                DateUtil.month(startTime) + 1,
                DateUtil.year(startTime));
        return scheduleJob(jobBeanClass, startCron, data);
    }

    @Override
    public Boolean cancelScheduleJob(String jobName) {
        boolean success = false;
        try {
            // 暂停触发器
            scheduler.pauseTrigger(new TriggerKey(jobName, defaultGroup));
            // 移除触发器中的任务
            scheduler.unscheduleJob(new TriggerKey(jobName, defaultGroup));
            // 删除任务
            scheduler.deleteJob(new JobKey(jobName, defaultGroup));
            success = true;
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return success;
    }
}
  • 定义好需要执行的任务,继承QuartzJobBean类,实现executeInternal方法即可,这里定义了三个任务,定时发送邮件、定时发送站内信和执行CRON表达式任务;
/**
 * 发送邮件定时任务执行器
 * Created by macro on 2020/9/27.
 */
@Slf4j
@Component
public class SendEmailJob extends QuartzJobBean {
    @Autowired
    private ScheduleService scheduleService;

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        Trigger trigger = jobExecutionContext.getTrigger();
        JobDetail jobDetail = jobExecutionContext.getJobDetail();
        JobDataMap jobDataMap = jobDetail.getJobDataMap();
        String data = jobDataMap.getString("data");
        log.info("定时发送邮件操作:{}",data);
        //完成后删除触发器和任务
        scheduleService.cancelScheduleJob(trigger.getKey().getName());
    }
}
/**
 * 发送站内信定时任务执行器
 * Created by macro on 2020/9/27.
 */
@Slf4j
@Component
public class SendMessageJob extends QuartzJobBean {
    @Autowired
    private ScheduleService scheduleService;

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        Trigger trigger = jobExecutionContext.getTrigger();
        JobDetail jobDetail = jobExecutionContext.getJobDetail();
        JobDataMap jobDataMap = jobDetail.getJobDataMap();
        String data = jobDataMap.getString("data");
        log.info("定时发送站内信操作:{}",data);
        //完成后删除触发器和任务
        scheduleService.cancelScheduleJob(trigger.getKey().getName());
    }
}
/**
 * 使用CRON表达式的任务执行器
 * Created by macro on 2020/9/29.
 */
@Slf4j
@Component
public class CronProcessJob extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        JobDetail jobDetail = jobExecutionContext.getJobDetail();
        JobDataMap jobDataMap = jobDetail.getJobDataMap();
        String data = jobDataMap.getString("data");
        log.info("CRON表达式任务执行:{}",data);
    }
}
  • 最后创建好任务调度相关接口,调用任务调度业务类即可。
/**
 * 定时任务调度相关接口
 * Created by macro on 2020/9/29.
 */
@Api(tags = "ScheduleController", description = "定时任务调度相关接口")
@RestController
@RequestMapping("/schedule")
public class ScheduleController {
    @Autowired
    private ScheduleService scheduleService;

    @ApiOperation("定时发送邮件")
    @PostMapping("/sendEmail")
    public CommonResult sendEmail(@RequestParam String startTime,@RequestParam String data) {
        Date date = DateUtil.parse(startTime, DatePattern.NORM_DATETIME_FORMAT);
        String jobName = scheduleService.scheduleFixTimeJob(SendEmailJob.class, date, data);
        return CommonResult.success(jobName);
    }

    @ApiOperation("定时发送站内信")
    @PostMapping("/sendMessage")
    public CommonResult sendMessage(@RequestParam String startTime,@RequestParam String data) {
        Date date = DateUtil.parse(startTime, DatePattern.NORM_DATETIME_FORMAT);
        String jobName = scheduleService.scheduleFixTimeJob(SendMessageJob.class, date, data);
        return CommonResult.success(jobName);
    }

    @ApiOperation("通过CRON表达式调度任务")
    @PostMapping("/scheduleJob")
    public CommonResult scheduleJob(@RequestParam String cron, @RequestParam String data) {
        String jobName = scheduleService.scheduleJob(CronProcessJob.class, cron, data);
        return CommonResult.success(jobName);
    }

    @ApiOperation("取消定时任务")
    @PostMapping("/cancelScheduleJob")
    public CommonResult cancelScheduleJob(@RequestParam String jobName) {
        Boolean success = scheduleService.cancelScheduleJob(jobName);
        return CommonResult.success(success);
    }
}

运行测试

  • 调用定时发送邮件接口测试;

  • 到点之后发现控制台已经打印任务执行信息;
2020-09-30 11:23:00.035  INFO 10160 --- [eduler_Worker-1] com.macro.mall.tiny.job.SendEmailJob     : 定时发送邮件操作:发送邮件内容
  • 使用CRON表达式来启动一个定时任务,从0s开始,每隔10s执行一次;

  • 控制台每隔10s打印任务执行信息;
2020-09-30 11:26:30.024  INFO 10160 --- [eduler_Worker-2] com.macro.mall.tiny.job.CronProcessJob   : CRON表达式任务执行:CRON消息内容
2020-09-30 11:26:40.025  INFO 10160 --- [eduler_Worker-3] com.macro.mall.tiny.job.CronProcessJob   : CRON表达式任务执行:CRON消息内容
2020-09-30 11:26:50.017  INFO 10160 --- [eduler_Worker-4] com.macro.mall.tiny.job.CronProcessJob   : CRON表达式任务执行:CRON消息内容
2020-09-30 11:27:00.023  INFO 10160 --- [eduler_Worker-5] com.macro.mall.tiny.job.CronProcessJob   : CRON表达式任务执行:CRON消息内容
2020-09-30 11:27:10.019  INFO 10160 --- [eduler_Worker-6] com.macro.mall.tiny.job.CronProcessJob   : CRON表达式任务执行:CRON消息内容
  • 我们可以通过启动任务返回的jobName,调用取消定时任务的接口来取消任务,调用成功后定时任务不再执行。

SpringBoot整合Quartz 目录`Quartz` 简介 Quartz 简介 Quartz 是一款功能强大的开源任务调度框架,几乎可以集成到任何 Java 应用程序中(小到单机应用,大到分布式应用)。Quartz 可用于创建简单或复杂的任务调度,用以执行数以万计的任务。任务被定义为标准化的 Java 组件,Java 编写的任务都可以被执行 Quartz 是一个任务日程管理系统,一个在预先确定(被纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统 Quartz 用一个小 Java 库发布文件(.jar文件),这个库文件包含了所 阅读详情

相关推荐

springboot整合quartz

前言 在上一篇中,我们了解了quartz的基本使用,在项目中与springboot的整合是比较常见的方式,下面让我们来看看如何在springboot中集成quartz吧 1、引入pom <!--spring boot集成quartz--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spr

congge 1816

springboot整合quartz项目使用(含完整代码)

学习quartz有两方面,首先xxl-Job,elastic-Job这些框架都是基于quartz的基础上二次开发的,学习quartz更有利于我们加强理解定时调度。第二方面就是工作需求,有一些传统互联网公司还是有很多项目是使用quartz来完成定时任务的开发的。

gorylee的博客 4万+

springboot整合elasticjob

springboot整合elasticjob

congge 2884

Springboot 整合Quartz

springboot整合quartz相关基本配置

yang_fei9264的博客 8119

告别‘小目标’丢失!手把手复现DNANet红外检测网络(PyTorch版)

本文详细介绍了如何使用PyTorch从零实现DNANet红外小目标检测网络,重点解析了DNIM模块和CSAM注意力机制的设计与实现。通过实战教程,帮助开发者解决红外小目标检测中的特征提取和训练调参难题,适用于军事侦察、安防监控等场景。

weixin_28701593的博客 253

Lenovo 拯救者15ISK硬件升级实战:从内存到固态硬盘的全面优化

本文详细介绍了为联想拯救者15ISK笔记本电脑进行硬件升级的完整实战指南。通过评估升级可行性,指导如何挑选兼容的内存条与NVMe固态硬盘,并提供详细的拆机安装步骤与系统安装避坑技巧。升级后,笔记本的开机速度、软件加载及多任务处理能力获得飞跃式提升,让老旧设备重获新生。

weixin_29310631的博客 557

spring-rs:一款 Rust 编写的轻量级应用框架

在软件开发领域,选择合适的应用框架是提升开发效率、优化应用性能的关键因素。今天,我们将为您介绍一款新兴的开源项目——spring-rs,这是一个受到 Java SpringBoot 启发的 Rust 应用框架,具有高性能、高安全性、轻量化和易于使用的特点。 ## 项目介绍 spring-rs 是一个基于 Rust 语言的应用框架,它的设计理念是“约定大于配置”,这与 Java 中的 Sprin...

gitblog_00229的博客 1156

从一根USB线缆说起:深入浅出聊聊那些影响信号完整性和EMC性能的‘小细节’(双绞、屏蔽、360度搭接全解析)

本文深入探讨了USB线缆中影响信号完整性和EMC性能的关键细节,包括双绞线绞距、屏蔽层设计和360度搭接工艺。通过实验数据和实用技巧,揭示了这些‘小细节’如何显著影响高频信号质量和电磁兼容性,为工程师提供了从选购到系统设计的全面指南。

weixin_30824479的博客 440

调度失败:执行器地址为空_面试应该知道的任务调度平台

部分面试资料链接:https://pan.baidu.com/s/1qDb2YoCopCHoQXH15jiLhA 密码:jsam想获得全部面试必看资料,关注公众号,大家可以在公众号后台回复“知乎”即可。背景日常开发中,我们难免会遇到需要处理一些定时任务,而且这些定时任务还需要灵活的调度,并且在异常的情况下需要做的重试或者报警。这些任务我们希望能灵活配置,并且能及时生效,不需要经常发版本更新代码。所...

weixin_39622760的博客 2227

让 ABAP 复杂内表优雅“喂饱”:Complex Internal Table Filling 全面实战指南

本文为ABAP开发者系统梳理了复杂内表的填充与复制方法。重点介绍了work area的两种声明方式、APPEND操作的多形态用法及其初始值语义,以及VALUE #( )构造器的逐行与整表写法。同时讲解了CORRESPONDING的同名字段映射功能,帮助开发者在"航司与航线"等复杂业务场景中实现最佳实践。文章还涵盖内存优化、可读性建议和常见误区,提供可运行样例,适用于ABAP On-Premise和SAP BTP环境。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 169

在Qt中集成VTK和PCL:实现数据可视化的完整指南

在现代软件开发中,数据可视化至关重要。将VTK(Visualization Toolkit)和PCL(Point Cloud Library)集成到Qt环境里,能为开发者提供强大的可视化解决方案。本文将深入讲解如何在Qt中读取PCL文件,展示VTK模型和PCL数据,适合想要在Qt项目中实现数据可视化的开发者。

轩宇的博客 918

python任务调度平台 界面_面试应该知道的任务调度平台

密码:jsam想获得全部面试必看资料,关注公众号,大家可以在公众号后台回复“知乎”即可。背景日常开发中,我们难免会遇到需要处理一些定时任务,而且这些定时任务还需要灵活的调度,并且在异常的情况下需要做的重试或者报警。这些任务我们希望能灵活配置,并且能及时生效,不需要经常发版本更新代码。所以我们希望能有一个这样的平台,能满足我们的这些需求。感谢开源社区,已经有了很好的解决方案,就是 XXL-JOB。 ...

weixin_39690958的博客 198

极智AI | 详解 ViT 算法实现

大家好,我是极智视界,本文详细介绍一下 ViT 算法的设计与实现,包括代码。

极智视界 5606

MediaPipe 教程:从安装到应用-全网最全

MediaPipe是Google推出的开源框架,专为构建机器学习管道设计,可以高效处理视频、音频等时间序列数据。本文教程从安装到应用逐步讲解: 安装步骤简单,只需通过pip安装mediapipe包并验证版本; 重点演示人体姿态检测功能,可识别33个身体关键点; 提供基础代码实现,包括视频捕获、关键点检测与可视化; 强调模块化开发,将功能封装成类以提高代码复用性。 教程适合初学者,通过清晰指引和实用代码示例,帮助快速实现计算机视觉应用。

FJN110的博客 1564

PCB仿真软件:Altium Designer_(18).PCB设计中的热管理

在PCB设计中,热管理是一个至关重要的环节。随着电子设备的集成度越来越高,功耗和发热量也随之增加,不合理的热设计可能导致电路板过热,从而影响电路的性能和可靠性。热管理不仅能够提高电路板的使用寿命,还能确保电路在各种环境条件下的稳定工作。本节将详细介绍如何在Altium Designer中进行有效的热管理,包括热分析、热设计和热仿真等关键步骤。

kkchenjj的博客 1988

这 6 个 SpringBoot 项目够经典!

前言不得不佩服 SpringBoot 的生态如此强大,今天给大家推荐几款优秀的后台管理系统,小伙伴们再也不用从头到尾撸一个项目了。SmartAdmin我们开源一套漂亮的代码和一套整洁的代码...

654

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

java开源项目-六个经典的 SpringBoot 练手项目

前言不得不佩服 SpringBoot 的生态如此强大,今天给大家推荐几款优秀的后台管理系统,小伙伴们再也不用从头到尾撸一个项目了。SmartAdmin我们开源一套漂亮的代码和一套整洁的代码...

独行侠梦的博客 5869

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

定时任务没触发_Springboot定时任务以及优缺点

为什么要使用定时任务: 众所周知,我们在做一个项目的过程中,除了人工触发一些任务外,有很多功能是需要它自动去运行。 比如说商品订单的自动审核,自动定时流转状态等等,这些都是需要用到定时去完成,而不是简简单单的每次都通过人工去操作。毕竟如果有些任务是大半夜的,这得多折腾人。 因此,定时任务的必要性就此体现出来了。介绍:定时任务可以自己开发,也可以使用一些轻量级分布式任务调度平台,类似于xxl-job...

weixin_35943077的博客 819

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

接私活必备开源的SpringBoot项目

点击上方蓝字关注我们# 前言不得不佩服 SpringBoot 的生态如此强大,今天给大家推荐几款优秀的后台管理系统,小伙伴们再也不用从头到尾撸一个项目了。# SmartAdmin我们开源...

Rookie 1699

01SpringBoot概述

阅读导航。

本人主攻Java,希望自己能成为出色的程序员。 363

SpringBoot项目中几种定时任务的实现方式

定时任务实现的几种方式: Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。一般用的较少。 ScheduledExecutorService:也jdk自带的一个类;是基于线程池设计的定时任务类,每个调度任务都会分配到线程池中的一个线程去执行,也就是说,...

qq_40887780的博客 678
上一篇: 这份让腾讯、阿里巴巴都羡慕不已的MySQL全面手册,受喜爱程度不输任何大厂笔记!
下一篇: Nginx如何支持HTTPS?手把手教你操作,so easy!
「已注销」
博客等级 码龄6年 36粉丝 149原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值