当前位置: 首页 > article >正文

Spring Boot 动态定时任务管理系统(轻量级实现)

Spring Boot项目中,实现动态增删和启停定时任务的功能对于许多应用场景来说至关重要。虽然Quartz框架是一个广泛使用的解决方案,但其复杂性和重量级特性可能使得项目变得臃肿和难以维护。为了解决这个问题,本项目旨在实现一个轻量级的定时任务管理系统,不依赖外部框架,仅利用Spring Boot和Java标准库的功能,特别适用于单体项目。

数据库

DROP TABLE IF EXISTS `scheduled_jobs`;
CREATE TABLE `scheduled_jobs`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '任务ID,唯一标识每个定时任务',
  `method_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '方法名称,执行定时任务时调用的方法名',
  `cron_expression` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'cron表达式,定义定时任务的执行时间规则',
  `status` int(11) NOT NULL DEFAULT 1 COMMENT '任务状态,1为正常运行,0为暂停',
  `content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '1' COMMENT '任务正文,具体需要执行的内筒',
  `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '任务的备注信息,描述任务的其他细节',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '任务创建时间,自动设置为当前时间',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '任务最后更新时间,每次更新时自动更新时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1391804419 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

POM依赖

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


        <!-- mybatis-plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.9</version>
        </dependency>

        <!--lombok依赖-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--MySQL数据库的依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>

        <!--hutool工具依赖-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.26</version>
        </dependency>

项目启动类

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.sws.dynamicscheduler.mapper")
public class DynamicSchedulerApplication {

    public static void main(String[] args) {
        SpringApplication.run(DynamicSchedulerApplication.class, args);
    }

}

任务管理器类

import com.sws.dynamicscheduler.mapper.ScheduledJobMapper;
import com.sws.dynamicscheduler.model.ScheduledJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ScheduledFuture;

@Service
@Slf4j
public class DynamicTaskManager {

    private final ThreadPoolTaskScheduler taskScheduler;
    private final ScheduledJobMapper scheduledJobMapper;
    private final Map<String, ScheduledFuture<?>> scheduledTasks;

    @Autowired
    public DynamicTaskManager(ScheduledJobMapper scheduledJobMapper, ThreadPoolTaskScheduler taskScheduler) {
        this.scheduledJobMapper = scheduledJobMapper;
        this.taskScheduler = taskScheduler;
        this.scheduledTasks = new HashMap<>();
    }


    @PostConstruct
    public void init() {
        // 初始化时加载数据库中的所有定时任务并调度
        List<ScheduledJob> jobs = scheduledJobMapper.selectList(null);
        for (ScheduledJob job : jobs) {
            if (job.getStatus() == 1) {
                addTask(job.getCronExpression(), job.getMethodName(),job.getContent(), job.getId().toString());
            }
        }
    }

    // 动态新增任务
    public String addTask(String cronExpression, String methodName, String content,String taskId) {
        Runnable task = () -> {
            // 执行定时任务的逻辑
           log.info("执行了定时任务:{},执行内容是:{}",methodName,content);
        };

        ScheduledFuture<?> scheduledFuture = taskScheduler.schedule(task, new CronTrigger(cronExpression));
        scheduledTasks.put(taskId, scheduledFuture);
        return taskId;
    }

    // 动态删除任务
    public void removeTask(String taskId) {
        ScheduledFuture<?> scheduledFuture = scheduledTasks.get(taskId);
        if (scheduledFuture != null) {
            scheduledFuture.cancel(false); // 取消任务
            scheduledTasks.remove(taskId); // 从集合中删除
        }
    }

    // 停止任务
    public void stopTask(Integer jobId) {
        Optional<ScheduledJob> jobOptional = Optional.ofNullable(scheduledJobMapper.selectById(jobId));
        jobOptional.ifPresent(job -> {
            job.setStatus(0); // 设置为暂停状态
            scheduledJobMapper.insert(job);
            removeTask(jobId.toString()); // 停止定时任务
        });
    }

    // 恢复任务
    public void resumeTask(Integer jobId) {
        Optional<ScheduledJob> jobOptional = Optional.ofNullable(scheduledJobMapper.selectById(jobId));
        jobOptional.ifPresent(job -> {
            job.setStatus(1); // 设置为正常状态
            scheduledJobMapper.insert(job);
            addTask(job.getCronExpression(), job.getMethodName(), job.getContent(),jobId.toString()); // 恢复定时任务
        });
    }
}

实体类

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;


import java.util.Date;

@Data
@TableName("`scheduled_jobs`")
public class ScheduledJob {

    private Integer id;                // 任务ID,唯一标识每个定时任务
    private String methodName;         // 方法名称,执行定时任务时调用的方法名
    private String cronExpression;    // cron表达式,定义定时任务的执行时间规则
    private Integer status;            // 任务状态,1为正常运行,0为暂停
    private String content;           // 任务正文,具体需要执行的内容
    private String remark;             // 任务的备注信息,描述任务的其他细节
    private Date createTime;           // 任务创建时间,自动设置为当前时间
    private Date updateTime;           // 任务最后更新时间,每次更新时自动更新时间


}

配置类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

@Configuration
public class SchedulerConfig {

    @Bean
    public ThreadPoolTaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(10); // 设置线程池的大小
        scheduler.setThreadNamePrefix("scheduled-task-"); // 设置线程名称前缀
        return scheduler;
    }
}

Mapper类

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.sws.dynamicscheduler.model.ScheduledJob;

public interface ScheduledJobMapper extends BaseMapper<ScheduledJob> {

}

控制类

import com.sws.dynamicscheduler.model.ScheduledJob;
import com.sws.dynamicscheduler.mapper.ScheduledJobMapper;
import com.sws.dynamicscheduler.scheduler.DynamicTaskManager;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;

@RestController
@RequestMapping("/tasks")
public class TaskController {

    @Resource
    DynamicTaskManager taskManager;

    @Resource
    ScheduledJobMapper scheduledJobMapper;


    // 动态添加任务
    @PostMapping("/add")
    public String addTask(@RequestParam String cronExpression, @RequestParam String methodName,@RequestParam String content) {
        ScheduledJob job = new ScheduledJob();
        job.setMethodName(methodName);
        job.setContent(content);
        job.setCronExpression(cronExpression);
        job.setStatus(1);
        scheduledJobMapper.insert(job); // 保存到数据库

        // 添加定时任务
        return taskManager.addTask(cronExpression, methodName,content,job.getId().toString());
    }

    // 动态删除任务
    @DeleteMapping("/remove")
    public void removeTask(@RequestParam Integer jobId) {
        taskManager.removeTask(jobId.toString());
        scheduledJobMapper.deleteById(jobId);
    }

    // 暂停任务
    @PostMapping("/pause")
    public void pauseTask(@RequestParam Integer jobId) {
        taskManager.stopTask(jobId);
    }

    // 恢复任务
    @PostMapping("/resume")
    public void resumeTask(@RequestParam Integer jobId) {
        taskManager.resumeTask(jobId);
    }

    // 获取所有任务
    @GetMapping("/all")
    public List<ScheduledJob> getAllTasks() {
        return scheduledJobMapper.selectList(null);
    }
}

项目地址:神蛐/DynamicScheduler


http://www.kler.cn/a/449878.html

相关文章:

  • Xcode 16 编译弹窗问题、编译通过无法,编译通过打包等问题汇总
  • 用C#(.NET8)开发一个NTP(SNTP)服务
  • Vue.js 响应接口
  • 应用端sql慢查询监控分析
  • 怎么实现柔性动态自适应IVR功能
  • 安装fast_bev环境
  • IDEA自己常用的几个快捷方式(自己的习惯)
  • Nginx三种安装方式
  • 【Threejs】从零开始(十一)--3D交互事件
  • Ubuntu20.04 修改root密码
  • 小程序将对象通过url传递到下个页面
  • LeetCode每日三题(一)哈希
  • R语言基础| 功效分析
  • Effective C++ 条款 02:尽量以 const,enum,inline 替换 #define
  • 递归查询全量分页数据问题
  • C++---------随机库,standfor库
  • 16×16LED点阵字符滚动显示-基于译码器与移位寄存器(设计报告+仿真+单片机源程序)
  • IMX6ULL开发板如何关掉自带的QT的GUI界面和poky的界面的方法
  • [spring]处理器
  • SpringCloudGateway+Nacos注册与转发Netty+WebSocket
  • 02-8.python入门基础一函数的高级使用
  • 一次性部署:使用Docker部署PHP应用
  • 源码分析之Openlayers中ZoomSlider滑块缩放控件
  • 【C语言】深入探讨 C 语言 `int` 类型大小及其跨平台影响
  • 【机器人】ATM 用于策略学习的任意点轨迹建模 RSS 2024 | 论文精读
  • 音视频入门基础:MPEG2-TS专题(20)——ES流简介