利用Spring Boot轻松实现动态定时器开发!
前言
传统定时器是硬编码。但是有的时候业务上需要不断地调整
问题描述
我们开发了一个定闹钟的功能。这个功能肯定是定时器开发。但是这就存在一个问题这个定时是动态的。那么我们如何实现呢?Spring Boot核心学习笔记共享。
简介
定时器在开发中真的算是一种福利了。通过定时器我们省去了很多人力。我们通过定时器将一些繁琐定期的事情通过代码去完成。在Java开发中我们通过Timer类可以简单实现定时器功能。既然是springboot课程今天我们就来看看srpingboot整合定时器的事情
传统定时器
这里使用的是之前课程一的配置。springboot打算是系列讲解。所以配置都是承前启后的。建议大家按顺序观看。
@Component
public class SimpleSchedule {
@Autowired
TestMapper testMapper;
@Scheduled(cron = "*/6 * * * * ?")
private void process() {
List<test> tests = testMapper.getTests();
System.out.println(tests);
}
}
定时器的编写也很简单,只需要在类或者方法上加上@Scheduled注解。然后配置cron表达式就可以了。这里得注意一下需要在spirngboot启动类上加上开发定时器的注解。
@SpringBootApplication
public class CrontabApplication {
public static void main(String[] args) {
SpringApplication.run(CrontabApplication.class, args);
}
}
代码中我们使用的是最简单的一种方式。
cron表达式:指定任务在特定时间执行
fixedDelay:表示上一次任务执行完成后多久再执行,参数类型long,单位:ms
fixedDelayString:与fixedDelay一样,只是参数类型是String
fixedRate:表示按一定的频率执行任务,参数类型long,单位:ms 如: fixedRate(5000),表示这个定时器任务每5秒执行一次
fixedRateString:与fixedRate一样,只是参数类型变为String
initialDelay:表示延迟多久再第一次执行任务,参数类型为long ,单位:ms
initialDelayString:与initialDelay一样,只是参数类型String
动态定时器
上面的定时器已经成功的配置了。但是现在有一个需求客户想通过页面定制配置定时器执行的频率。上面代码我们是写死6S执行一次。如果客户想通过可视化配置。配置完成之后我总不能再手动改写代码吧。那么动态定时器就产生了。
V1.0
既然动态我们就得将客户配置的数据进行本地化。当然是存储在数据库中。
对应的我们新建Mapper查询定时任务信息。因为这里只配置了表达式。没有配置表达式对应的定时器。也是为了测试。这里默认表达式就是一个。
@Configuration
public class ScheduleConfigV1 implements SchedulingConfigurer {
@Autowired
CronMapper cronMapper;
@Autowired
TestMapper testMapper;
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.addTriggerTask(()-> {
System.out.println("执行定时器任务:" + LocalDateTime.now().toLocalTime());
List<test> tests = testMapper.getTests();
System.out.println(tests);
},
triggerContext -> {
List<cron> crons = cronMapper.getCron();
Cron cron = crons.get(0);
return new CronTrigger(cron.getCron()).nextExecutionTime(triggerContext);
});
}
}
执行这个代码我们最好先关掉前面那个静态的定时器。这样看的效果明显点。首先数据库配置的是6秒执行一次。然后把数据改成2秒执行一次。看看效果。
我们发现只要数据库信息修改了。定时任务会自动修改频率的。最重要的是不需要重启我们的代码。
上面虽然是动态配置了。但是有一个缺点。就是修改之后生效是在下一次触发定时器执行后有效。说白了就是一开始一小时执行一次,在这期间修改了不能立马生效必须得到下一次一小时才会去刷新配置。这里的动态可以理解成懒动态。
V2.0
上面的功能虽然是动态的。但是对于量产的话肯定是不科学的。首先数据库不可能只存一条数据的。
如果存多条数据那么多条定时规则与具体的定时器怎么进行匹配呢?
既然是动态的那么如何通过数据库控制定时器的开关呢?
定时任务的通过代码启动实际是scheduler.schedule(task, new CronTrigger("/2 * * * * ?"));实现的。这个方法返回的对象是ScheduledFuture。通过canel方法取消定时任务。基于这两个方法我们来改进下我们之前的定时任务。
Registar
首先我们提供一个注册器,注册器的功能就是管理定时任务。提供增加删除功能。在增加定时器的节点上我们调用scheduler.schedule(task, new CronTrigger("/2 * * * * ?"));来启动定时任务。在删除节点上调用之前获取的ScheduledFuture来canel这个定时任务。这样做的好处我们可以随时控制定时任务的开关
public void addCronTask(Runnable task, String cron) {
addCronTask(new CronTask(task,cron));
}
上面添加需要有一个runnable和cron表达式。用一个ConcurrentHashMap来管理添加进来的runnable。runnable为key,ScheduledTask为值。
public ScheduledTask scheduleCronTask(CronTask cronTask) {
ScheduledTask scheduledTask;
scheduledTask = new ScheduledTask();
scheduledTask.future = this.taskScheduler.schedule(cronTask.getRunnable(), cronTask.getTrigger());
return scheduledTask;
}
这样构建一个ScheduledTask对象。
public final class ScheduledTask {
public volatile ScheduledFuture future;
/**
- 取消定时任务
*/
public void cancel() {
ScheduledFuture future = this.future;
if (future != null) {
future.cancel(true);
}
}
}
这样我们就可以通过构建一个runnable线程,结合表达式通过注册器注册就可以开启这个线程已固定频率执行。通过remove关闭线程。
SchedulingRunnable task = new SchedulingRunnable(TestMapper.class, "getTests", null);
cronTaskRegistrar.addCronTask(task, "0/10 * * * * ?");
这样做的好处是我们可以在表数据修改的情况下立马更新定时任务规则。
总结
下面Java类是我们这次使用用到的类。
SchedulingConfigurer
DisposableBean
ConcurrentHashMap
java新手自学群 626070845
java/springboot/hadoop/JVM 群 4915800
Hadoop/mongodb(搭建/开发/运维)Q群481975850
GOLang Q1群:6848027
GOLang Q2群:450509103
GOLang Q3群:436173132
GOLang Q4群:141984758
GOLang Q5群:215535604
C/C++/QT群 1414577
单片机嵌入式/电子电路入门群群 306312845
MUD/LIB/交流群 391486684
Electron/koa/Nodejs/express 214737701
大前端群vue/js/ts 165150391
操作系统研发群:15375777
汇编/辅助/破解新手群:755783453
大数据 elasticsearch 群 481975850
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
2018-08-24 esxi 配置 交换主机 虚拟机交换机 linux centos 配置双网卡