最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot運(yùn)行時(shí)修改定時(shí)任務(wù)Cron表達(dá)式的實(shí)現(xiàn)方案

 更新時(shí)間:2025年06月30日 08:43:10   作者:風(fēng)象南  
在項(xiàng)目開發(fā)中,定時(shí)任務(wù)是一個(gè)常見的需求,SpringBoot通過(guò)@Scheduled注解提供了簡(jiǎn)便的定時(shí)任務(wù)實(shí)現(xiàn)方式,但默認(rèn)情況下,一旦應(yīng)用啟動(dòng),定時(shí)任務(wù)的Cron表達(dá)式就無(wú)法動(dòng)態(tài)調(diào)整,本文將介紹如何在SpringBoot應(yīng)用運(yùn)行期間動(dòng)態(tài)修改定時(shí)任務(wù)的Cron表達(dá)式,需要的朋友可以參考下

一、引言

在項(xiàng)目開發(fā)中,定時(shí)任務(wù)是一個(gè)常見的需求。Spring Boot 通過(guò) @Scheduled 注解提供了簡(jiǎn)便的定時(shí)任務(wù)實(shí)現(xiàn)方式,但默認(rèn)情況下,一旦應(yīng)用啟動(dòng),定時(shí)任務(wù)的 Cron 表達(dá)式就無(wú)法動(dòng)態(tài)調(diào)整。

然而,在實(shí)際業(yè)務(wù)場(chǎng)景中,我們常常需要根據(jù)運(yùn)行狀態(tài)或用戶配置動(dòng)態(tài)調(diào)整定時(shí)任務(wù)的執(zhí)行頻率。

本文將介紹如何在 Spring Boot 應(yīng)用運(yùn)行期間動(dòng)態(tài)修改定時(shí)任務(wù)的 Cron 表達(dá)式,實(shí)現(xiàn)定時(shí)任務(wù)的靈活調(diào)度。

二、Spring 定時(shí)任務(wù)機(jī)制概述

2.1 Spring 定時(shí)任務(wù)的實(shí)現(xiàn)方式

Spring Boot 支持三種定時(shí)任務(wù)的實(shí)現(xiàn)方式:

@Scheduled 注解:最簡(jiǎn)單的方式,直接在方法上添加注解 SchedulingConfigurer 接口:通過(guò)實(shí)現(xiàn)該接口,可以進(jìn)行更靈活的配置 TaskScheduler 接口:最底層的 API,提供最大的靈活性

傳統(tǒng)的 @Scheduled 注解使用示例:

@Component
public class ScheduledTasks {
    
    @Scheduled(cron = "0 0/5 * * * ?")  // 每5分鐘執(zhí)行一次
    public void executeTask() {
        System.out.println("定時(shí)任務(wù)執(zhí)行,時(shí)間:" + new Date());
    }
}

2.2 @Scheduled 注解的局限性

雖然 @Scheduled 注解使用簡(jiǎn)便,但它存在明顯的局限性:

  1. Cron 表達(dá)式在編譯時(shí)就確定,運(yùn)行時(shí)無(wú)法修改
  2. 無(wú)法根據(jù)條件動(dòng)態(tài)啟用或禁用定時(shí)任務(wù)
  3. 無(wú)法在運(yùn)行時(shí)動(dòng)態(tài)添加新的定時(shí)任務(wù)
  4. 無(wú)法獲取定時(shí)任務(wù)的執(zhí)行狀態(tài)

這些局限使得 @Scheduled 注解不適合需要?jiǎng)討B(tài)調(diào)整的場(chǎng)景。

三、動(dòng)態(tài)定時(shí)任務(wù)的實(shí)現(xiàn)方案

要實(shí)現(xiàn)定時(shí)任務(wù)的動(dòng)態(tài)調(diào)整,我們有幾種可行的方案:

3.1 基于 SchedulingConfigurer 接口的實(shí)現(xiàn)

這是最常用的方式,通過(guò)實(shí)現(xiàn) SchedulingConfigurer 接口,我們可以獲取 TaskSchedulerScheduledTaskRegistrar,從而實(shí)現(xiàn)定時(shí)任務(wù)的動(dòng)態(tài)管理。

以下是基本實(shí)現(xiàn)步驟:

步驟 1:創(chuàng)建任務(wù)配置類

package com.example.scheduler;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;

import java.util.Date;

@Configuration
@EnableScheduling
public class DynamicScheduleConfig implements SchedulingConfigurer {
    
    @Autowired
    private CronRepository cronRepository;  // 用于存儲(chǔ)和獲取Cron表達(dá)式
    
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskScheduler());
        
        // 從數(shù)據(jù)庫(kù)或配置中心獲取初始Cron表達(dá)式
        String initialCron = cronRepository.getCronByTaskName("sampleTask");
        
        // 添加可動(dòng)態(tài)修改的定時(shí)任務(wù)
        taskRegistrar.addTriggerTask(
            // 定時(shí)任務(wù)的執(zhí)行邏輯
            () -> {
                System.out.println("動(dòng)態(tài)定時(shí)任務(wù)執(zhí)行,時(shí)間:" + new Date());
            },
            // 定時(shí)任務(wù)觸發(fā)器,可根據(jù)需要返回下次執(zhí)行時(shí)間
            triggerContext -> {
                // 每次任務(wù)觸發(fā)時(shí),重新獲取Cron表達(dá)式
                String cron = cronRepository.getCronByTaskName("sampleTask");
                CronTrigger trigger = new CronTrigger(cron);
                return trigger.nextExecution(triggerContext);
            }
        );
    }
    
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(10);  // 設(shè)置線程池大小
        scheduler.setThreadNamePrefix("task-");
        scheduler.initialize();
        return scheduler;
    }
}

步驟 2:創(chuàng)建存儲(chǔ)和管理 Cron 表達(dá)式的組件

@Repository
public class CronRepository {
    
    // 這里可以連接數(shù)據(jù)庫(kù)或配置中心,本例使用內(nèi)存存儲(chǔ)簡(jiǎn)化演示
    private final Map<String, String> cronMap = new ConcurrentHashMap<>();
    
    public CronRepository() {
        // 設(shè)置初始值
        cronMap.put("sampleTask", "0 0/1 * * * ?");  // 默認(rèn)每分鐘執(zhí)行一次
    }
    
    public String getCronByTaskName(String taskName) {
        return cronMap.getOrDefault(taskName, "0 0/1 * * * ?");
    }
    
    public void updateCron(String taskName, String cron) {
        // 驗(yàn)證cron表達(dá)式的有效性
        try {
            new CronTrigger(cron);
            cronMap.put(taskName, cron);
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException("Invalid cron expression: " + cron, e);
        }
    }
}

步驟 3:創(chuàng)建 REST API 用于修改 Cron 表達(dá)式

@RestController
@RequestMapping("/scheduler")
public class SchedulerController {
    
    @Autowired
    private CronRepository cronRepository;
    
    @GetMapping("/cron/{taskName}")
    public Map<String, String> getCron(@PathVariable String taskName) {
        Map<String, String> result = new HashMap<>();
        result.put("taskName", taskName);
        result.put("cron", cronRepository.getCronByTaskName(taskName));
        return result;
    }
    
    @PutMapping("/cron/{taskName}")
    public Map<String, String> updateCron(
            @PathVariable String taskName, 
            @RequestParam String cron) {
        cronRepository.updateCron(taskName, cron);
        
        Map<String, String> result = new HashMap<>();
        result.put("taskName", taskName);
        result.put("cron", cron);
        result.put("message", "Cron expression updated successfully");
        return result;
    }
}

3.2 使用 Spring 的 TaskScheduler 直接管理定時(shí)任務(wù)

我們可以直接使用 TaskScheduler 接口進(jìn)行定時(shí)任務(wù)的細(xì)粒度控制:

package com.example.scheduler;

import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.stream.Collectors;

@Service
public class AdvancedTaskScheduler {
    
    @Autowired
    private TaskScheduler taskScheduler;
    
    @Autowired
    private CronRepository cronRepository;
    
    // 維護(hù)所有調(diào)度任務(wù)
    private final Map<String, ScheduledTask> scheduledTasks = new ConcurrentHashMap<>();
    
    @Data
    @AllArgsConstructor
    private static class ScheduledTask {
        private String taskName;
        private String cron;
        private Runnable runnable;
        private ScheduledFuture<?> future;
        private boolean running;
    }
    
    /**
     * 注冊(cè)一個(gè)新的定時(shí)任務(wù)
     */
    public void registerTask(String taskName, Runnable runnable) {
        // 判斷任務(wù)是否已存在
        if (scheduledTasks.containsKey(taskName)) {
            throw new IllegalArgumentException("Task with name " + taskName + " already exists");
        }
        String cron = cronRepository.getCronByTaskName(taskName);
        ScheduledFuture<?> future = taskScheduler.schedule(
            runnable,
            triggerContext -> {
                // 動(dòng)態(tài)獲取最新的cron表達(dá)式
                String currentCron = cronRepository.getCronByTaskName(taskName);
                return new CronTrigger(currentCron).nextExecution(triggerContext);
            }
        );
        
        scheduledTasks.put(taskName, new ScheduledTask(taskName, cron, runnable, future, true));
    }
    
    /**
     * 更新任務(wù)的Cron表達(dá)式
     */
    public void updateTaskCron(String taskName, String cron) {
        // 更新數(shù)據(jù)庫(kù)/配置中心中的cron表達(dá)式
        cronRepository.updateCron(taskName, cron);
        
        // 重新調(diào)度任務(wù)
        ScheduledTask task = scheduledTasks.get(taskName);
        if (task != null) {
            // 取消現(xiàn)有任務(wù)
            task.getFuture().cancel(false);
            
            // 創(chuàng)建新任務(wù)
            ScheduledFuture<?> future = taskScheduler.schedule(
                task.getRunnable(),
                triggerContext -> {
                    return new CronTrigger(cron).nextExecution(triggerContext);
                }
            );
            
            // 更新任務(wù)信息
            task.setCron(cron);
            task.setFuture(future);
        }
    }
    
    /**
     * 暫停任務(wù)
     */
    public void pauseTask(String taskName) {
        ScheduledTask task = scheduledTasks.get(taskName);
        if (task != null && task.isRunning()) {
            task.getFuture().cancel(false);
            task.setRunning(false);
        }
    }
    
    /**
     * 恢復(fù)任務(wù)
     */
    public void resumeTask(String taskName) {
        ScheduledTask task = scheduledTasks.get(taskName);
        if (task != null && !task.isRunning()) {
            ScheduledFuture<?> future = taskScheduler.schedule(
                task.getRunnable(),
                triggerContext -> {
                    String currentCron = cronRepository.getCronByTaskName(taskName);
                    return new CronTrigger(currentCron).nextExecution(triggerContext);
                }
            );
            
            task.setFuture(future);
            task.setRunning(true);
        }
    }
    
    /**
     * 刪除任務(wù)
     */
    public void removeTask(String taskName) {
        ScheduledTask task = scheduledTasks.get(taskName);
        if (task != null) {
            task.getFuture().cancel(false);
            scheduledTasks.remove(taskName);
        }
    }
    
    /**
     * 獲取所有任務(wù)信息
     */
    public List<Map<String, Object>> getAllTasks() {
        return scheduledTasks.values().stream()
            .map(task -> {
                Map<String, Object> map = new HashMap<>();
                map.put("taskName", task.getTaskName());
                map.put("cron", task.getCron());
                map.put("running", task.isRunning());
                return map;
            })
            .collect(Collectors.toList());
    }
}

四、使用數(shù)據(jù)庫(kù)存儲(chǔ) Cron 表達(dá)式

對(duì)于生產(chǎn)環(huán)境,我們需要確保定時(shí)任務(wù)的配置能夠持久化,將 CronRepository 修改為使用數(shù)據(jù)庫(kù)存儲(chǔ)

@Repository
public class DatabaseCronRepository implements CronRepository {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Override
    public String getCronByTaskName(String taskName) {
        try {
            return jdbcTemplate.queryForObject(
                "SELECT cron FROM scheduled_tasks WHERE task_name = ?",
                String.class,
                taskName
            );
        } catch (EmptyResultDataAccessException e) {
            return "0 0/1 * * * ?";  // 默認(rèn)值
        }
    }
    
    @Override
    public void updateCron(String taskName, String cron) {
        // 驗(yàn)證cron表達(dá)式
        try {
            new CronTrigger(cron);
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException("Invalid cron expression: " + cron, e);
        }
        
        // 更新數(shù)據(jù)庫(kù)
        int updated = jdbcTemplate.update(
            "UPDATE scheduled_tasks SET cron = ? WHERE task_name = ?",
            cron, taskName
        );
        
        if (updated == 0) {
            // 如果記錄不存在,則插入
            jdbcTemplate.update(
                "INSERT INTO scheduled_tasks (task_name, cron) VALUES (?, ?)",
                taskName, cron
            );
        }
    }
}

數(shù)據(jù)庫(kù)表結(jié)構(gòu):

CREATE TABLE scheduled_tasks (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    task_name VARCHAR(100) NOT NULL UNIQUE,
    cron VARCHAR(100) NOT NULL,
    description VARCHAR(255),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

五、總結(jié)

在一些相對(duì)簡(jiǎn)單的業(yè)務(wù)或項(xiàng)目或服務(wù)器資源有限的情況下,可以基于本文思路進(jìn)行簡(jiǎn)單擴(kuò)展,即可實(shí)現(xiàn)定時(shí)任務(wù)管理,無(wú)需額外引入其他定時(shí)任務(wù)組件。

如果是一些相對(duì)復(fù)雜的項(xiàng)目對(duì)定時(shí)任務(wù)有更多需求和可靠性保證的要求,可以引入如xxl-job、ElasticJob等任務(wù)調(diào)度組件。

以上就是SpringBoot運(yùn)行時(shí)修改定時(shí)任務(wù)Cron表達(dá)式的實(shí)現(xiàn)方案的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot修改Cron表達(dá)式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java中Unsafe的使用講解

    java中Unsafe的使用講解

    這篇文章主要介紹了java中Unsafe的使用講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • SSM框架流程及原理分析

    SSM框架流程及原理分析

    本文給大家分享小編一些心得體會(huì),主要是學(xué)習(xí)SSM框架之后的收獲吧,重點(diǎn)給大家介紹SSM框架流程以及原理分析,通過(guò)圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2021-06-06
  • Java實(shí)現(xiàn)四則混合運(yùn)算代碼示例

    Java實(shí)現(xiàn)四則混合運(yùn)算代碼示例

    這篇文章主要介紹了Java實(shí)現(xiàn)四則混合運(yùn)算代碼示例,文中展示了詳細(xì)代碼,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-10-10
  • SpringBoot整合Shiro的環(huán)境搭建教程

    SpringBoot整合Shiro的環(huán)境搭建教程

    這篇文章主要為大家詳細(xì)介紹了SpringBoot整合Shiro的環(huán)境搭建教程,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以了解一下
    2022-12-12
  • Spring實(shí)現(xiàn)泛型注入的示例詳解

    Spring實(shí)現(xiàn)泛型注入的示例詳解

    Spring?4.0版本中更新了很多新功能,其中比較重要的一個(gè)就是對(duì)帶泛型的Bean進(jìn)行依賴注入的支持。本文將通過(guò)實(shí)例詳細(xì)講講Spring如何實(shí)現(xiàn)泛型注入,需要的可以參考一下
    2022-07-07
  • SpringBoot配置Spring?Security的實(shí)現(xiàn)示例

    SpringBoot配置Spring?Security的實(shí)現(xiàn)示例

    本文主要介紹了SpringBoot配置Spring?Security的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-10-10
  • SpringBoot統(tǒng)一異常處理的實(shí)用方案

    SpringBoot統(tǒng)一異常處理的實(shí)用方案

    在日常開發(fā)中,你一定見過(guò)這樣的代碼:代碼冗余、維護(hù)困難、前端對(duì)接痛苦、日志混亂,線上出問(wèn)題還難定位,統(tǒng)一異常處理,就是用來(lái)解決這些問(wèn)題的,今天這篇文章,帶你從零到一實(shí)現(xiàn)SpringBoot全局統(tǒng)一異常處理,需要的朋友可以參考下
    2026-03-03
  • Java JDK 1.8 lambda的用法詳解

    Java JDK 1.8 lambda的用法詳解

    這篇文章主要介紹了Java JDK 1.8 lambda的用法詳解,文中給大家提到了jdk 1.8 Lambda 表達(dá)式 遍歷數(shù)組的方法,需要的朋友可以參考下
    2019-09-09
  • MyBatis ORM映射方式示例詳解

    MyBatis ORM映射方式示例詳解

    MyBatis作為一種靈活且強(qiáng)大的ORM框架,提供了多種映射方式,包括基于XML的映射、基于注解的映射以及混合映射,這篇文章主要介紹了MyBatis ORM映射方式詳解,需要的朋友可以參考下
    2024-12-12
  • Mybatis使用命令生成逆向工程的方法

    Mybatis使用命令生成逆向工程的方法

    這篇文章主要介紹了Mybatis使用命令生成逆向工程的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01

最新評(píng)論

施秉县| 咸阳市| 镇宁| 互助| 乐安县| 隆德县| 图片| 灵川县| 江安县| 新源县| 定兴县| 盐源县| 刚察县| 花莲市| 隆子县| 龙川县| 德安县| 乳源| 三穗县| 茂名市| 衡南县| 佳木斯市| 巴南区| 瑞昌市| 泰州市| 寻甸| 甘南县| 渭源县| 华安县| 西和县| 乌苏市| 栾城县| 黄冈市| 资中县| 龙井市| 镶黄旗| 巴林右旗| 彭泽县| 讷河市| 临安市| 双鸭山市|