四、springBoot 优雅的创建定时任务
前言
好几天没写了,工作有点忙,最近工作刚好做一个定时任务统计的,所以就将springboot 如何创建定时任务整理了一下。
总的来说,springboot创建定时任务是非常简单的,不用像spring 或者springmvc 需要在xml 文件中配置,在项目启动的时候加载。spring boot 使用注解的方式就可以完全支持定时任务。
不过基础注解的话,可能有的需求定时任务的时间会经常变动,注解就不好修改,每次都得重新编译,所以想将定时时间存在数据库,然后项目读取数据库执行定时任务,所以就有了基于接口的定时任务。下面就分基于注解和基于接口详细讲解。
基于注解
pom.xml 文件不用修改,我们原本的项目就支持,其实定时器是springboot框架自带的,不用引入什么依赖。我们直接创建一个autotask 包,创建一个AutoTask类。
@EnableScheduling
@Component
@Slf4j
public class AutoTask {
@Scheduled(cron="*/6 * * * * ?")
private void process(){
log.info("autoTask ");
}
}
这样一个定时器就创建啦,在项目启动后,会每隔6s 打印“autoTask”的日志。是不是很简单。主要用到的两个注解就是@EnableScheduling 和 @Scheduled。
注解@EnableScheduling 就是开启定时任务的。哪个类的中的方法想要定期执行,就在这个类上加入这个注解。当然这个这个注解也可以加在启动类上。加在启动类上表示项目中所有的类都可以创建定时任务。

@Scheduled 注解就是我们常见的定时器啦,后面的cron 就是定时任务表达式。在方法上注解,表示这个方法定期执行。

不过@Scheduled 可以进行两种配置,我们熟悉的cron ,还有一种是fixedRate。比如fixedRate=6000 表示方法每6秒钟执行一次。
我们来启动项目看一下,可以看到两个方法都在定期执行。

基于接口
上面可以看到springboot 基于注解是非常方便的。但是对于频繁变动或者一个项目中有很多的定时器那就不方便管理了。所以统一将定时器信息存放在数据库中。
DROP TABLE IF EXISTS `scheduled`;
CREATE TABLE `scheduled` (
`cron_id` varchar(30) NOT NULL PRIMARY KEY,
`cron_name` varchar(30) NULL,
`cron` varchar(30) NOT NULL
);
INSERT INTO `scheduled` VALUES ('1','定时器任务一','0/6 * * * * ?');

在dao 层mapper1包下创建一个CronMapper接口,很简单的就获取cron
public interface CronMapper {
@Select("select cron from scheduled where cron_id = #{id}")
public String getCron(int id);
}

这里我们就不写service 层了。直接在autotask 包下创建一个AutoTaskFromDB类
@Slf4j
@Component
public class AutoTaskFromDB implements SchedulingConfigurer {
@Autowired
protected CronMapper cronMapper;
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.addTriggerTask(() -> process(),
triggerContext -> {
String cron = cronMapper.getCron(1);
if (cron.isEmpty()) {
log.info("cron 为空");
}
return new CronTrigger(cron).nextExecutionTime(triggerContext);
}
);
}
private void process(){
log.info("formDB ");
}
}
可以看到也很简单,就是实现SchedulingConfigurer 这个吧接口,addTriggerTask()是添加一个定时器。
process()方法是我们需要定时执行的方法体。
CronTrigger(cron).nextExecutionTime(triggerContext) 就是从数据库读取的cron 创建定时器。
这个类我没有加上@EnableScheduling 注解,因为我在启动类上加上了,如果你们启动类上没有加,这里记得加上。
测试一下;下图可以看到三个定时任务都执行了,fromDB 是从数据库读取的。

cron
cron 用法网上有很多,也没有什么讲的这里就附带记录下
结构
cron表达式是一个字符串,分为6或7个域,每两个域之间用空格分隔,
其语法格式为:"秒域 分域 时域 日域 月域 周域 年域"
取值范围
| 域名 | 可取值 | 可取符号(仅列部分常用) |
|---|---|---|
| 秒域 | 0~59的整数 | * - , / |
| 分域 | 0~59的整数 | * - , / |
| 时域 | 0~23的整数 | * - , / |
| 日域 | 1~31的整数 | * - , / ? L |
| 月域 | 112的整数或JANDEC | * - , / |
| 周域 | 17的整数或SUNSAT | * - , / ? L # |
| 年域 | 1970~2099的整数 | * - , / |
常例
| 表达式 | 意义 |
|---|---|
| 每隔5秒钟执行一次 | */5 * * * * ? |
| 每隔1分钟执行一次 | 0 * /1 * * * ? |
| 每天1点执行一次 | 0 0 1 * * ? |
| 每天23点55分执行一次 | 0 55 23 * * ? |
| 每月最后一天23点执行一次 | 0 0 23 L * ? |
| 每周六8点执行一次 | 0 0 8 ? * L |
| 每月最后一个周五,每隔2小时执行一次 | 0 0 */2 ? * 6L |
| 每月的第三个星期五上午10:15执行一次 | 0 15 10 ? * 5#3 |
| 在每天下午2点到下午2:05期间的每1分钟执行 | 0 0-5 14 * * ? |
| 表示周一到周五每天上午10:15执行 | 0 15 10 ? * 2-6 |
| 每个月的最后一个星期五上午10:15执行 | 0 15 10 ? * 6L |
| 每天上午10点,下午2点,4点执行一次 | 0 0 10,14,16 * * ? |
| 朝九晚五工作时间内每半小时执行一次 | 0 0/30 9-17 * * ? |
| 每个星期三中午12点执行一次 | 0 0 12 ? * 4 |
| 每年三月的星期三的下午2:10和2:44各执行一次 | 0 10,44 14 ? 3 4 |
| 每月的第三个星期五上午10:15执行一次 | 0 15 10 ? * 6#3 |
| 每月一日凌晨2点30执行一次 | 0 30 2 1 * ? |
| 每分钟的第10秒与第20秒都会执行 | 10,20 * * * * ? |
| 每月的第2个星期的周5,凌晨执行 | 0 0 0 ? * 6#2 |
番外
本来这个知识点不应该放在这里讲的,但是不多,顺带写了,刚好也能做定时器。我们项目中往往有一些需求需要在项目启动的时候就执行,那这个我们怎么实现了。其实spring boot 使用起来也非常简单,只用实现 ApplicationRunner 就好了。
我们在autotask 包下创建一个AutoTaskFromSpringRunner类
@Slf4j
@Component
public class AutoTaskFromSpringRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
process();
}
private void process(){
log.info(" run ApplicationArguments");
}
}
启动项目看一下,可以发现这个会在项目启动后执行,但是只会执行一次。

那这个怎么用来做定时器呢?当然是结合线程来做啦,但是这个方法其实不建议,b毕竟线程很容易出问题,但是提供一种思路:
@Slf4j
@Component
public class AutoTaskFromSpringRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
process();
new Thread(() -> {
while (true) {
process2();
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
log.error("{}",e);
}
}
}).start();
}
private void process(){
log.info(" run ApplicationArguments");
}
private void process2(){
log.info("线程定时器");
}
}
启动项目看下,发现也是可以起到定时器的作用的。

好了,就说这么多啦,今天项目的代码也同步到github 上啦。
github地址:https://github.com/QuellanAn/zlflovemm
后续加油♡
欢迎大家关注个人公众号 "程序员爱酸奶"
分享各种学习资料,包含java,linux,大数据等。资料包含视频文档以及源码,同时分享本人及投递的优质技术博文。
如果大家喜欢记得关注和分享哟❤

四、springBoot 优雅的创建定时任务的更多相关文章
- SpringBoot使用@Scheduled创建定时任务
定时任务一般会存在中大型企业级项目中,为了减少服务器.数据库的压力往往会采用时间段性的去完成某些业务逻辑.比较常见的就是金融服务系统推送回调,一般支付系统订单在没有收到成功的回调返回内容时会持续性的回 ...
- MAC本如何优雅的创建定时任务
在MACOS上设置定时任务大体有两种方案.一种是使用crontab,一种是使用Schedule,今天结合我的使用简单介绍一下. 先说一下背景,为什么MAC可以用crontab.如果使用过Linux的同 ...
- Springboot定时任务原理及如何动态创建定时任务
一.前言 上周工作遇到了一个需求,同步多个省份销号数据,解绑微信粉丝.分省定时将销号数据放到SFTP服务器上,我需要开发定时任务去解析文件.因为是多省份,服务器.文件名规则.数据规则都不一定,所以要做 ...
- SpringBoot中使用@Scheduled创建定时任务
SpringBoot中使用@Scheduled创建定时任务 定时任务一般会在很多项目中都会用到,我们往往会间隔性的的去完成某些特定任务来减少服务器和数据库的压力.比较常见的就是金融服务系统推送回调,一 ...
- SpringBoot(十四)_springboot使用内置定时任务Scheduled的使用(一)
为什么使用定时? 日常工作中,经常会用到定时任务,比如各种统计,并不要求实时性.此时可以通过提前设置定时任务先把数据跑出来,后续处理起来更方便. 本篇文章主要介绍 springboot内置定时任务. ...
- SpringBoot创建定时任务
之前总结过spring+quartz实现定时任务的整合http://www.cnblogs.com/gdpuzxs/p/6663725.html,而springboot创建定时任务则是相当简单. (1 ...
- SpringBoot基于数据库的定时任务实现
在我们平时开发的项目中,定时任务基本属于必不可少的功能,那大家都是怎么做的呢?但我知道的大多都是静态定时任务实现. 基于注解来创建定时任务非常简单,只需几行代码便可完成.实现如下: @Configur ...
- JAVAEE——BOS物流项目13:Quartz概述、创建定时任务、使用JavaMail发送邮件、HighCharts概述、实现区域分区分布图
1 学习计划 1.Quartz概述 n Quartz介绍和下载 n 入门案例 n Quartz执行流程 n cron表达式 2.在BOS项目中使用Quartz创建定时任务 3.在BOS项目中使用Jav ...
- windows创建定时任务执行python脚本
一.创建定时任务 \ [程序或脚本]文本框中填的是Python编译器的名称,一般就是python.exe, [起始于]文本框中填的是Python编译器的目录,上图中假设你的Python编译器的完整路径 ...
随机推荐
- ASP.NET Core on K8S深入学习(7)Dashboard知多少
本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 在第二篇<部署过程解析与Dashboard>中介绍了如何部署Das ...
- 基于.net EF6 MVC5+WEB Api 的Web系统框架总结(2)-业务项目搭建
本节将介绍如何进行业务项目搭建. 本业务项目示例是简单的企业信息管理功能,业务项目采用Code First方式,搭建包括: 创建实体项目 创建实体数据表映射 创建业务处理项目 创建业务Web项目 搭建 ...
- 设计模式(C#)——02工厂模式
推荐阅读: 我的CSDN 我的博客园 QQ群:704621321 在简单工厂模式中讲到简单工厂模式的缺点:难以扩展,一旦添加新运算就必须修改简单工厂方法. 工厂方法模式: ...
- win命令获取外网ip
win命令: chcp 65001 curl https://ip.cn bat: @echo offchcp 65001 && curl https://ip.cnpause 链接: ...
- Delphi - Windows系统下,Delphi调用API函数和7z.dll动态库,自动把文件压缩成.tar.gz格式的文件
项目背景 应欧美客户需求,需要将文件压缩成.tar.gz格式的文件,并上传给客户端SFTP服务器. 你懂的,7-Zip软件的显著特点是文件越大压缩比越高,在Linux系统上相当于我们Windows系统 ...
- Java Builder 模式,你搞明白了么?
Builder 模式定义 Builder 模式中文叫作建造者模式,又叫生成器模式,它属于对象创建型模式,是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示.建造者模式是一步一步 ...
- Redis高可用架构
前言 Redis是一个高性能的key-value数据库,现时越来越多企业与应用使用Redis作为缓存服务器.楼主是一枚JAVA后端程序员,也算是半个运维工程师了.在Linux服务器上搭建Redis,怎 ...
- Mybatis案例升级版——小案例大道理
纯Mybatis案例升级版——小案例大道理 前言: 这几天看了一本书<原则>,在上面看到了一句话叫“每个人都把自己眼界的局限当成世界的局限”,大学生是
- light 1205 - Palindromic Numbers(数位dp)
题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1205 题解:这题作为一个数位dp,是需要咚咚脑子想想的.这个数位dp方程可能不 ...
- codeforces 842 D. Vitya and Strange Lesson(01字典树+思维+贪心)
题目链接:http://codeforces.com/contest/842/problem/D 题解:像这种求一段异或什么的都可以考虑用字典树而且mex显然可以利用贪心+01字典树,和线段树差不多就 ...