首页 > 其他分享 >Spring Boot:打造动态定时任务,开启灵活调度之旅

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

时间:2024-10-28 16:19:42浏览次数:7  
标签:之旅 Spring Boot springframework cron import org 定时 public

一、描述

在 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);
    }
}

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

标签:之旅,Spring,Boot,springframework,cron,import,org,定时,public
From: https://blog.csdn.net/Yaml4/article/details/143304263

相关文章

  • Springboot世界美食风情展示系统211wo(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表用户,美食类别,世界美食,美食攻略,美食订单开题报告内容一、项目背景与意义随着经济的快速发展和网络技术的进步,互联网已经深刻改变了人们的生活方式。电子商务......
  • Springboot食物营养数据分析系统fe78b(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表用户,食材分类,热卖食材,美食类型,美食食谱,营养数据,美食资讯开题报告内容一、选题背景与意义随着现代生活节奏的加快,人们对食品营养的需求与关注日益增强。然......
  • Springboot实验室设备维修维护管理系统81882(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表用户,公告信息,设备分类,设备信息,设备报修,设备维修,预警信息,培训信息开题报告内容一、研究背景与意义随着科学技术的飞速发展,实验室作为科研与教学的重要基......
  • Springboot实验室教学管理平台59z69(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表学生,老师,教室表,节次,学生课程表,老师课程表,调课申请单,教室,学生教室申请表,老师教室申请表开题报告内容一、研究背景与意义随着高等教育信息化的日益加速,......
  • 【JAVA毕业设计】基于Vue和SpringBoot的校园美食分享平台
    本文项目编号T033,文末自助获取源码\color{red}{T033,文末自助获取源码}......
  • 【JAVA毕业设计】基于Vue和SpringBoot的购物商城网站
    本文项目编号T032,文末自助获取源码\color{red}{T032,文末自助获取源码}......
  • java毕业设计基于springboot的商城系统
    文章目录项目介绍技术介绍功能介绍核心代码数据库参考系统效果图项目介绍  在当今信息爆炸的大时代,由于信息管理系统能够更有效便捷的完成信息的管理,越来越多的人及机构都已经引入和发展以信息管理系统为基础的信息化管理模式,随之信息管理技术也在不断的发展和成......
  • Springboot整合Swagger3
    1、pom.xml依赖<!--Swagger3依赖--><dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId><version>${swagger.version}</version>......
  • SpringBoot整合Mybatis
    1、项目结构 2、pom.xml依赖<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation=&q......
  • 【Java源码】基于SpringBoot的校园二手交易市场
    1项目介绍本课程演示的是一套基于SpringBoot的校园二手交易市场,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。包含:项目源码、项目文档、数据库脚本、软件工具等所有资料带你从零开始部署运行本套系统该项目附带的源码资料可作为毕设使用系......