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

ops/2024/12/25 0:53:53/

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>

项目启动类

java">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);}}

任务管理器类

java">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;@Autowiredpublic DynamicTaskManager(ScheduledJobMapper scheduledJobMapper, ThreadPoolTaskScheduler taskScheduler) {this.scheduledJobMapper = scheduledJobMapper;this.taskScheduler = taskScheduler;this.scheduledTasks = new HashMap<>();}@PostConstructpublic 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()); // 恢复定时任务});}
}

实体类

java">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;           // 任务最后更新时间,每次更新时自动更新时间}

配置类

java">import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;@Configuration
public class SchedulerConfig {@Beanpublic ThreadPoolTaskScheduler taskScheduler() {ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();scheduler.setPoolSize(10); // 设置线程池的大小scheduler.setThreadNamePrefix("scheduled-task-"); // 设置线程名称前缀return scheduler;}
}

Mapper类

java">import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.sws.dynamicscheduler.model.ScheduledJob;public interface ScheduledJobMapper extends BaseMapper<ScheduledJob> {}

控制类

java">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 {@ResourceDynamicTaskManager taskManager;@ResourceScheduledJobMapper 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.ppmy.cn/ops/144709.html

相关文章

【人工智能】探索当下热门视频生成模型

引言 在当今数字化浪潮下&#xff0c;视频生成模型宛如一颗璀璨的新星&#xff0c;正以惊人的速度改变着内容创作的格局。从影视制作到广告营销&#xff0c;从个人创意表达至教育培训领域&#xff0c;这些智能工具为我们开启了一扇通往无限可能的新大门。接下来&#xff0c;就让…

基于物联网的园区停车管理系统的设计与实现

1 论文参考 2 系统总体方案设计 2.1 可行性分析 基于物联网的园区停车管理系统的设计与实现是可行的。首先&#xff0c;随着物联网技术的不断发展&#xff0c;园区停车管理系统可以实现智能化管理&#xff0c;提高停车效率&#xff0c;减少人力成本。其次&#xff0c;园区停车…

Android-线性布局LinearLayout

线性布局LinearLayout-横着或者竖着按顺序排列的布局 新建工程,在layout下新建一个layout文件,如图操作 LinearLayout的基础属性如下表格,先简单了解一下,接下来逐一讲解 属性 值 说明 orientation 1.vertical:垂直排列 2.horizontal:水平排列 也就是这个线性布局到底是水…

linux firewalld 命令详解

简介 firewalld 是一个在 Linux 中的防火墙管理工具&#xff0c;提供动态接口管理网络流量&#xff0c;它使用区域来定义网络连接的信任级别&#xff0c;并支持 IPv4 和 IPv6。 常用示例 启动防火墙 sudo systemctl start firewalld 停止防火墙 sudo systemctl stop fire…

《C++ 赋能强化学习:Q - learning 算法的实现之路》

在当今科技飞速发展的时代&#xff0c;人工智能无疑是最热门的领域之一&#xff0c;而强化学习作为其中的重要分支&#xff0c;正逐渐改变着我们解决复杂问题的方式。Q - learning 算法作为强化学习中的经典算法&#xff0c;在众多领域如游戏、机器人控制、资源管理等有着广泛的…

Liunx下MySQL:表的约束

目录 什么是约束 空属性null/not null 默认值 列描述 zerofill 主键 自增长 什么是约束 约束就是约束ovO。 约束是为了保证数据的合法性&#xff0c;业务逻辑的正确性逼这程序员做约束之内的事情。 假如约束就是10之内的数字&#xff0c;那么程序员想要插入11&#xf…

深度学习之目标检测篇——残差网络与FPN结合

特征金字塔多尺度融合特征金字塔的网络原理 这里是基于resnet网络与Fpn做的结合&#xff0c;主要把resnet中的特征层利用FPN的思想一起结合&#xff0c;实现resnet_fpn。增强目标检测backone的有效性。代码实现如下&#xff1a; import torch from torch import Tensor from c…

2.4 网络概念(分层、TCP)

网络层与传输层概述 网络层&#xff1a; 抽象概念&#xff1a;网络层是基于 IP 的抽象概念&#xff0c;与数据链路层用 MAC 地址标记设备不同。MAC 地址是一种具体化的概念&#xff0c;绑定于所在的物理网络&#xff0c;而 IP 地址可以是固定的&#xff0c;也可以通过路由动态…