前言: 阅读完本文:🐱👓 知晓 SpringBoot 用注解如何实现定时任务明白 springBoot 如何实现一个动态定时任务 (与数据库相关联实现)理解 SpringBoot 实现设置时间执行定时任务
阅读完本文:🐱👓
SpringBoot
用注解如何实现定时任务springBoot
如何实现一个动态定时任务 (与数据库相关联实现)SpringBoot
实现设置时间执行定时任务 (使用 ThreadPoolTaskScheduler
实现)用注解实现是真的简单,只要会 cron 表达式就行。🧙♂️
第一步: 主启动类上加上 @EnableScheduling
注解
@EnableScheduling@SpringBootApplicationpublic class SpringBootScheduled { public static void main(String[] args) { SpringApplication.run(SpringBootScheduled.class); }}复制代码
第二步:写一个类,注入到Spring,关键就是 @Scheduled
注解。 () 里就是 cron 表达式,用来说明这个方法的执行周期的。 🛌
@Componentpublic class SchedulingTaskBasic { @Scheduled(cron = "*/5 * * * * ?") private void printNowDate() { long nowDateTime = System.currentTimeMillis(); System.out.println("固定定时任务执行:--->"+nowDateTime+",此任务为每五秒执行一次"); }}复制代码
执行效果:
源码在文末。🏍
其实也非常的简单。
第一步:建个数据库表。
CREATE TABLE `tb_cron` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '动态定时任务时间表', `cron_expression` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '定时任务表达式', `cron_describe` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述', PRIMARY KEY (`id`) USING BTREE) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;INSERT INTO `tb_cron` VALUES (1, '0 0/1 * * * ?', '每分钟执行一次');复制代码
第二步:导入数据库相关依赖,做到能从数据库查询数据。大家都会。🤸♂️
第三步: 编码
实体类:
@Data@TableName("tb_cron")public class Cron { private Long id; private String cronExpression; private String cronDescribe;}复制代码
mapper层:
@Repositorypublic interface CronMapper extends BaseMapper { @Select("select cron_expression from tb_cron where id=1") String getCron1();}复制代码
第四步:写一个类 实现 SchedulinGConfigurer
🍻
实现 void configureTasks(ScheduledTaskReGIStrar taskRegistrar);
方法,此方法的作用就是根据给定的 ScheduledTaskRegistrar 注册 TaskScheduler 和特定的Task实例
@Componentpublic class CompleteScheduleConfig implements SchedulingConfigurer { @Autowired @SuppressWarnings("all") CronMapper cronMapper; @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.addTriggerTask( //1.添加任务内容(Runnable) () -> System.out.println("执行动态定时任务1: " + LocalDateTime.now().toLocalTime()+",此任务执行周期由数据库中的cron表达式决定"), //2.设置执行周期(Trigger) triggerContext -> { //2.1 从数据库获取执行周期 String cron = cronMapper.getCron1(); //2.2 合法性校验. if (cron!=null) { // Omitted Code .. } //2.3 返回执行周期(Date) return new CronTrigger(cron).nextExecutionTime(triggerContext); } ); }}复制代码
注意:当你修改了任务执行周期后,生效时间为执行完最近一次任务后。这一点是需要注意的,用生活中的例子理解就是我们取消电话卡的套餐也要下个月生效,含义是一样的。
源码同样在文末。
通常业务场景是我前言中说的那样,是一次性的定时任务。如:我设置了我写的这篇文章的发布时间为今天下午的两点,执行完就删除没有了。一次性的。
实现主要依靠于 TaskScheduler
的ScheduledFuture> schedule(Runnable task, Trigger trigger);
方法来实现。其本质和动态定时任务的实现是一样的。
代码中都含有注解,不多做阐述。
import cn.hutool.core.convert.ConverterRegistry;import com.crush.scheduled.entity.Task;import lombok.extern.slf4j.Slf4j;import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;import org.springframework.stereotype.Component;import java.time.LocalDateTime;import java.util.*;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.CopyOnWriteArrayList;import java.util.concurrent.ScheduledFuture;@Component@Slf4jpublic class DynamicTaskService { public Map> taskMap = new ConcurrentHashMap<>(); public List taskList = new CopyOnWriteArrayList(); private final ThreadPoolTaskScheduler syncScheduler; public DynamicTaskService(ThreadPoolTaskScheduler syncScheduler) { this.syncScheduler = syncScheduler; } public List getTaskList() { return taskList; } public boolean add(Task task) { // 此处的逻辑是 ,如果当前已经有这个名字的任务存在,先删除之前的,再添加现在的。(即重复就覆盖) if (null != taskMap.get(task.getName())) { stop(task.getName()); } // hutool 工具包下的一个转换类型工具类 好用的很 ConverterRegistry converterRegistry = ConverterRegistry.getInstance(); Date startTime = converterRegistry.convert(Date.class, task.getStart()); // schedule :调度给定的Runnable ,在指定的执行时间调用它。 //一旦调度程序关闭或返回的ScheduledFuture被取消,执行将结束。 //参数: //任务 – 触发器触发时执行的 Runnable //startTime – 任务所需的执行时间(如果这是过去,则任务将立即执行,即尽快执行) ScheduledFuture> schedule = syncScheduler.schedule(getRunnable(task), startTime); taskMap.put(task.getName(), schedule); taskList.add(task.getName()); return true; } public Runnable getRunnable(Task task) { return () -> { log.info("---动态定时任务运行---"); try { System.out.println("此时时间==>" + LocalDateTime.now()); System.out.println("task中设定的时间==>" + task); Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } log.info("---end--------"); }; } public boolean stop(String name) { if (null == taskMap.get(name)) { return false; } ScheduledFuture> scheduledFuture = taskMap.get(name); scheduledFuture.cancel(true); taskMap.remove(name); taskList.remove(name); return true; }}复制代码
@Configurationpublic class ThreadPoolTaskExecutorConfig { @Bean public ThreadPoolTaskScheduler syncScheduler() { ThreadPoolTaskScheduler syncScheduler = new ThreadPoolTaskScheduler(); syncScheduler.setPoolSize(5); // 这里给线程设置名字,主要是为了在项目能够更快速的定位错误。 syncScheduler.setThreadGroupName("syncTg"); syncScheduler.setThreadNamePrefix("syncThread-"); syncScheduler.initialize(); return syncScheduler; }}复制代码
这里需要注意一个点,我给项目中的 LocalDateTime
做了类型转换。这里没贴出来(主要是复制以前的代码遗留下来的,源码中都有)
大家简单使用,可以直接用注解 标注在 LocalDateTime
属性上即可。
package com.crush.scheduled.controller;import com.crush.scheduled.entity.Task;import com.crush.scheduled.service.DynamicTaskService;import org.springframework.WEB.bind.annotation.*;import java.util.List;@RestController@RequestMapping("/dynamicTask")public class DynamicTaskController { private final DynamicTaskService dynamicTask; public DynamicTaskController(DynamicTaskService dynamicTask) { this.dynamicTask = dynamicTask; } @GetMapping public List getStartingDynamicTask(){ return dynamicTask.getTaskList(); } @PostMapping("/dynamic") public String startDynamicTask(@RequestBody Task task){ // 将这个添加到动态定时任务中去 dynamicTask.add(task); return "动态任务:"+task.getName()+" 已开启"; } @DeleteMapping("/{name}") public String stopDynamicTask(@PathVariable("name") String name){ // 将这个添加到动态定时任务中去 if(!dynamicTask.stop(name)){ return "停止失败,任务已在进行中."; } return "任务已停止"; }}复制代码
简单封装的一个实体类:
@Data@Accessors(chain = true) // 方便链式编写 习惯所然 public class Task { private String name; private LocalDateTime start;}复制代码
💫💨
开启一个动态任务:
查看开启还未执行的动态任务:
执行结果:
和我们代码中是一模一样的。
停止任务:
再去查看就是已经停止的拉
来源地址:https://blog.csdn.net/2301_76607156/article/details/129796248
--结束END--
本文标题: SpringBoot实现固定、动态定时任务 | 三种实现方式
本文链接: https://www.lsjlt.com/news/422336.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-04-03
2024-04-03
2024-04-01
2024-01-21
2024-01-21
2024-01-21
2024-01-21
2023-12-23
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0