Spring Boot:打造动态定时任务,开启灵活调度之旅

news2024/12/23 22:56:56

一、描述

在 Spring Boot 中设置动态定时任务是一种非常实用的功能,可以根据实际需求在运行时动态地调整定时任务的执行时间、频率等参数。以下是对 Spring Boot 设置动态定时任务的简单介绍:

1、传统定时任务的局限性

在传统的 Spring Boot 定时任务中,通常是通过在方法上使用@Scheduled注解来设置固定的执行时间和频率。这种方式在任务的执行计划相对固定的情况下是有效的,但在一些需要动态调整任务执行时间的场景中就显得不够灵活。例如,在一个电商系统中,可能需要根据不同的促销活动时间动态地调整订单处理任务的执行时间;在一个监控系统中,可能需要根据实时的系统负载情况动态地调整数据采集任务的执行频率。

2、动态定时任务的实现方式

  1. 使用数据库存储任务配置信息:

    • 可以在数据库中创建一个任务配置表,存储任务的名称、执行时间、执行频率等信息。
    • 在 Spring Boot 应用启动时,读取数据库中的任务配置信息,并根据这些信息创建定时任务。
    • 当需要动态调整任务执行时间时,可以通过修改数据库中的任务配置信息,然后通知 Spring Boot 应用重新读取任务配置,从而实现动态调整定时任务的目的。
  2. 使用配置文件动态加载:

    • 在 Spring Boot 的配置文件(如 application.properties 或 application.yml)中,可以定义一些动态的配置参数,用于设置定时任务的执行时间和频率。
    • 通过使用 Spring Boot 的配置文件加载机制,可以在运行时动态地修改配置文件中的参数,然后通知 Spring Boot 应用重新加载配置文件,从而实现动态调整定时任务的目的。
  3. 使用管理界面进行动态配置:

    • 可以开发一个管理界面,让管理员可以在界面上直接设置定时任务的执行时间和频率。
    • 管理界面可以通过调用 Spring Boot 应用提供的 API 来修改任务配置信息,然后通知应用重新读取任务配置,从而实现动态调整定时任务的目的。

3、动态定时任务的优势

  1. 灵活性高:可以根据实际需求在运行时动态地调整定时任务的执行时间和频率,满足不同场景下的需求。
  2. 易于管理:通过数据库、配置文件或管理界面等方式,可以方便地管理定时任务的配置信息,提高系统的可维护性。
  3. 实时响应:可以根据实时的业务需求和系统状态动态地调整定时任务,提高系统的响应能力和效率。

二、案例

1、第一种写法

1、新建spring boot项目

添加相应的依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
        <optional>true</optional>
    </dependency>

    <!-- spring boot 2.3版本后,如果需要使用校验,需手动导入validation包-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>
2、启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
 
/**
 * @author wl
 */
@EnableScheduling
@SpringBootApplication
public class Application {
 
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
        System.out.println("(*^▽^*)启动成功!!!(〃'▽'〃)");
    }
}
3、配置文件application.yml

定义服务端口

server:
  port: 8089

定时任务执行时间配置文件:task-config.ini:

myPrintTime.cron=0/10 * * * * ?

4、定时任务执行类:
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Date;

@Data
@Slf4j
@Component
@PropertySource("classpath:/my-task-config.ini")
public class CustomScheduleTask implements SchedulingConfigurer {

    @Value("${myPrintTime.cron}")
    private String cron;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(() -> {
            log.info("Custom task executed at: {}", LocalDateTime.now());
        }, new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                // 使用CronTrigger触发器,可动态修改cron表达式来操作循环规则
                CronTrigger cronTrigger = new CronTrigger(cron);
                Date nextExecutionTime = cronTrigger.nextExecutionTime(triggerContext);
                return nextExecutionTime;
            }
        });
    }
}
5、controller

编写一个接口,构建动态定时任务管理接口

import com.wl.demo.task.ScheduleTask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;



@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {

    private final ScheduleTask scheduleTask;

    @Autowired
    public TestController(ScheduleTask scheduleTask) {
        this.scheduleTask = scheduleTask;
    }

    @GetMapping("/updateCron")
    public ResponseEntity<String> updateCron(String cron) {
        log.info("new cron :{}", cron);
        scheduleTask.setCron(cron);
        return new ResponseEntity<>("定时任务 cron 表达式更新成功", HttpStatus.OK);
    }
}

启动项目,可以看到任务每10秒执行一次

也可以通过url地址修改任务时间,localhost:8089ytest/updateCron?cron=0/15 * * * *?


6、CronTrigger触发器

除了上面的借助cron表达式的方法,还有另一种触发器,区别于CronTrigger触发器,该触发器可随意设置循环间隔时间,不像cron表达式只能定义小于等于间隔59秒,在这个新的定时任务类中,我们可以从不同的配置文件中读取 cron 表达式,并且设置了一个不同的默认循环时间。根据实际需求,可以灵活地调整 cron 表达式和循环时间间隔。

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.scheduling.support.PeriodicTrigger;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Date;

@Data
@Slf4j
@Component
@PropertySource("classpath:/my-task-config.ini")
public class NewScheduleTask implements SchedulingConfigurer {

    @Value("${myPrintTime.cron}")
    private String cron;

    private Long customTimer = 15000L;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(() -> {
            log.info("New task execution time: {}", LocalDateTime.now());
        }, new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                // 使用 CronTrigger 或根据需求切换
                CronTrigger cronTrigger = new CronTrigger(cron);
                Date nextExecutionTime = cronTrigger.nextExecutionTime(triggerContext);
                if (nextExecutionTime == null) {
                    PeriodicTrigger periodicTrigger = new PeriodicTrigger(customTimer);
                    return periodicTrigger.nextExecutionTime(triggerContext);
                }
                return nextExecutionTime;
            }
        });
    }
}

修改时间的接口

import com.wl.demo.task.ScheduleTask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;



@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {

    private final ScheduleTask scheduleTask;

    @Autowired
    public TestController(ScheduleTask scheduleTask) {
        this.scheduleTask = scheduleTask;
    }

    @GetMapping("/updateCron")
    public ResponseEntity<String> updateCron(String cron) {
        log.info("new cron :{}", cron);
        scheduleTask.setCron(cron);
        return new ResponseEntity<>("定时任务 cron 表达式更新成功", HttpStatus.OK);
    }

    @GetMapping("/updateTimer")
    public String updateTimer(Long timer) {
        log.info("new timer :{}", timer);
        scheduleTask.setTimer(timer);
        return "ok";
    }
}

运行结果

2、第二种写法

1、添加依赖

和前面一样,在 Maven 项目的pom.xml文件中添加以下依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
2、创建定时任务执行接口和实现类

首先定义一个定时任务执行的接口:

public interface ScheduledTaskExecutor {
    void execute();
}

然后创建一个实现类:

import org.springframework.stereotype.Component;

@Component
public class DynamicTaskExecutor implements ScheduledTaskExecutor {

    @Override
    public void execute() {
        System.out.println("定时任务执行:" + new java.util.Date());
    }
}
3、配置定时任务调度器

创建一个定时任务调度器类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;

import java.util.Date;

@Configuration
@EnableScheduling
public class ScheduledTaskConfig implements SchedulingConfigurer {

    @Autowired
    private DynamicTaskExecutor dynamicTaskExecutor;

    private String cronExpression = "0/5 * * * *?"; // 默认每 5 秒执行一次

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(
                () -> dynamicTaskExecutor.execute(),
                triggerContext -> {
                    CronTrigger trigger = new CronTrigger(cronExpression);
                    return trigger.nextExecutionTime(triggerContext);
                }
        );
    }

    // 提供一个方法用于动态修改定时任务的表达式
    public void setCronExpression(String expression) {
        cronExpression = expression;
    }
}
4、动态修改定时任务

可以在其他地方调用ScheduledTaskConfigsetCronExpression()方法来动态修改定时任务的执行时间表达式。

例如:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class SchedulingService {

    @Autowired
    private ScheduledTaskConfig scheduledTaskConfig;

    public void changeCronExpression(String newExpression) {
        scheduledTaskConfig.setCronExpression(newExpression);
    }
}

通过这种方式,你可以在运行时动态地调整定时任务的执行时间,提高应用的灵活性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2230291.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Chrome与夸克谁更节省系统资源

在当今数字化时代&#xff0c;浏览器已经成为我们日常生活中不可或缺的一部分。无论是工作、学习还是娱乐&#xff0c;我们都依赖于浏览器来访问互联网。然而&#xff0c;不同的浏览器在性能和资源消耗方面存在差异。本文将探讨Chrome和夸克两款浏览器在系统资源消耗方面的表现…

react的antd-mobile使用Steps显示物流

antd-mobile的图标&#xff0c;是需要安装依赖的 step如果只有一个步骤是不会展示的&#xff0c;代码里面的标题那块可以看出来 尝试了很多遍测试发现一直不显示&#xff0c;查询后发现是这个组件的本身设置的原因 那么就算你只展示一个那么也要写两个step&#xff0c;第二个…

AI-基本概念-多层感知器模型/CNN/RNN/自注意力模型

1 需求 神经网络 …… 深度学习 …… 深度学习包含哪些神经网络&#xff1a; 全连接神经网络卷积神经网络循环神经网络基于注意力机制的神经网络 2 接口 3 CNN 在这个示例中&#xff1a; 首先定义了一个简单的卷积神经网络SimpleCNN&#xff0c;它包含两个卷积层、两个池…

链表详解(一)

目录 顺序表的问题及思考链表链表的概念及结构链表的分类单链表的实现链表功能实现遍历链表void SLTprint(SLNode* phead)代码 创造新节点SLNode* CreateNode(SLNDataType x)代码 顺序表的问题及思考 中间/头部的插入删除&#xff0c;时间复杂度为O(N),效率低,但是尾部插入效率…

【MongoDB】Windows/Docker 下载安装,MongoDB Compass的基本使用、NoSQL、MongoDB的基础概念及基础用法(超详细)

文章目录 Windows下载MongoDB Compass使用NoSQL的基本概念MongoDB常用术语MongoDB与RDBMS区别MongoDB的CRUD 更多相关内容可查看 Docker安装MongoDB可查看&#xff1a;Docker-安装MongoDB Windows下载 官网下载地址&#xff1a;https://www.mongodb.com/try/download/communi…

uni-app发起请求以及请求封装,上传及下载功能(六)

文章目录 一、发起网络请求1.使用及封装2. https 请求配置自签名证书3.拦截器 二、上传下载1.上传 uni.uploadFile(OBJECT)2. 下载 uni.downloadFile(OBJECT) 一、发起网络请求 uni-app中内置的uni.request()已经很强大了&#xff0c;简单且好用。为了让其更好用&#xff0c;同…

C语言 | Leetcode C语言题解之第526题优美的排列

题目&#xff1a; 题解&#xff1a; int countArrangement(int n) {int f[1 << n];memset(f, 0, sizeof(f));f[0] 1;for (int mask 1; mask < (1 << n); mask) {int num __builtin_popcount(mask);for (int i 0; i < n; i) {if (mask & (1 <<…

《Baichuan-Omni》论文精读:第1个7B全模态模型 | 能够同时处理文本、图像、视频和音频输入

技术报告Baichuan-Omni Technical ReportGitHub仓库地址 文章目录 论文摘要1. 引言简介2. 训练2.1. 高质量的多模态数据2.2. 多模态对齐预训练2.2.1. 图像-语言分支2.2.2. 视频语音分支2.2.3. 音频语言分支2.2.4. 图像-视频-音频全方位对齐 2.3. 多模态微调监督 3. 实验3.1. 语…

Cesium着色器

GLSL&#xff08;OpenGL Shading Language&#xff09;是用于编写着色器的语言 着色器类型 顶点着色器&#xff1a;负责处理每个顶点的属性&#xff0c;如位置、颜色等。片段着色器&#xff08;或像素着色器&#xff09;&#xff1a;负责计算最终像素的颜色。 <!DOCTYPE h…

基于SSM医院门诊互联电子病历管理系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;医生管理&#xff0c;项目分类管理&#xff0c;项目信息管理&#xff0c;预约信息管理&#xff0c;检查信息管理&#xff0c;系统管理 用户账号功能包括&#xff1a;系统首页&…

论文阅读笔记-Get To The Point: Summarization with Pointer-Generator Networks

前言 最近看2021ACL的文章&#xff0c;碰到了Copying Mechanism和Coverage mechanism两种技巧&#xff0c;甚是感兴趣的翻阅了原文进行阅读&#xff0c;Copying Mechanism的模型CopyNet已经进行阅读并写了阅读笔记&#xff0c;如下&#xff1a; 论文阅读笔记&#xff1a;Copyi…

unocss 添加支持使用本地 svg 预设图标,并支持更改大小

安装 pnpm install iconify/utils 在配置文件 unocss.config.ts&#xff1a; presets > presetIcons 选项中 通过 FileSystemIconLoader 加载本地图标&#xff0c;并指定目录。 import presetWeapp from unocss-preset-weapp import { extractorAttributify, transformer…

NineData云原生智能数据管理平台新功能发布|2024年10月版

10 月发布内容 本月发布 7 项更新&#xff0c;其中重点发布 2 项、功能优化 3 项、性能优化 1 项、其他发布 1 项。 重点发布​ 数据库 Devops - 数据生成​ NineData 支持在数据库中自动生成符合特定业务场景的随机数据&#xff0c;用于模拟实际生产环境中的数据情况&…

10种数据预处理中的数据泄露模式解析:识别与避免策略

在机器学习教学实践中,我们常会遇到这样一个问题:"模型表现非常出色,准确率超过90%!但当将其提交到隐藏数据集进行测试时,效果却大打折扣。问题出在哪里?"这种情况几乎总是与数据泄露有关。 当测试数据在数据准备阶段无意中泄露(渗透)到训练数据时,就会发生数据泄露…

<十六>Ceph mon 运维

Ceph 集群有故障了&#xff0c;你执行的第一个运维命令是什么&#xff1f; 我猜测是ceph -s 。无论执行的第一个命令是什么&#xff0c;都肯定是先检查Mon。 在开始之前我们有必要介绍下Paxos协议&#xff0c;毕竟Mon就是靠它来实现数据唯一性。 一&#xff1a; Paxos 协议 1…

Spring Boot的核心优势及其应用详解

目录 前言1. Spring Boot的核心优势1.1 启动依赖的集成1.2 自动化配置 2. 内嵌服务器支持2.1 内嵌Tomcat服务器2.2 独立运行与便捷部署 3. 外部配置管理3.1 多环境支持3.2 配置优先级与外部化配置 4. Spring Boot的应用场景4.1 微服务架构4.2 云原生应用 结语 前言 在现代的Ja…

8进制在线编码工具--实现8进制编码

具体前往&#xff1a;文本转八进制在线工具-将文本字符串转换为8进制编码,支持逗号&#xff0c;空格和反斜杠分隔符

Windows 命令提示符(cmd)中输入 mysql 并收到错误消息“MySQL不是内部或外部命令,也不是可运行的程序或批处理文件?

目录 背景: 过程&#xff1a; 1.找到MySQL安装的路径 2.编辑环境变量 3.打开cmd&#xff0c;输入mysql --version测试成功 总结: 背景: 很早之前安装了Mysql数据库&#xff0c;想查询一下当前安装的MySQL客户端的版本号&#xff0c;我在命令行界面输入mysql --verion命令回…

Python学习的自我理解和想法(22)

学的是b站的课程&#xff08;千锋教育&#xff09;&#xff0c;跟老师写程序&#xff0c;不是自创的代码&#xff01; 今天是学Python的第22天&#xff0c;学的内容是正则表达式&#xff0c;明天会出一篇详细实例介绍。电脑刚修好&#xff01;开学了&#xff0c;时间不多&…

大数据-203 数据挖掘 机器学习理论 - 决策树 sklearn 剪枝参数 样本不均匀问题

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…