四、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编译器的完整路径 ...
随机推荐
- springboot的log4j配置与logback配置
log4j配置的依赖 <!-- 删除pom.xml文件中所有对日志jar包的引用--> <dependency> <groupId>org.springframew ...
- 史上最全面的SignalR系列教程-6、SignalR 实现聊天室
1.概述 通过前面几篇文章对SignalR的详细介绍.我们知道Asp.net SignalR是微软为实现实时通信的一个类库.一般情况下,SignalR会使用JavaScript的长轮询(long po ...
- day0203
day02 1.for i in range() --->用于设置for循环的迭代设置. ranage 也是一个前闭后开的. 2.random.randrange() --->随机产生给予 ...
- JS如何重写一个函数
分享一些自己在开发上遇到的问题,比如我们页面上用了大量的打印语句,但是在某些时候,我们不想要了. 解决方案1 : 我们删除这里的代码,如果太多了,那工作量太大好累,想想都不想干 解决方案2 :我们将c ...
- cf 1102 B
题意:求字符串中任意相邻两位是否可以可以由前一个加上任意个x或y屏蔽十位与后一位相等,如果可以需要添加的最少数字是多少,x值为0-9,y值也为0-9,求出任意x,y对应情形下字符串需要添加的最少数字, ...
- js 截屏保存图片
html2canvas.js 这个js有个强大的功能,就是能将html 对应的dom生成canvas. 这样,我们就可以通过生成的canvas转化成 base64 图片,从而实现截屏功能: 核心代码如 ...
- 用jquery uploadify上传插件上传文件
public void ProcessRequest(HttpContext context) { string esOIDs = System.Web.HttpContext.Current.Req ...
- SpringMVC 三种异常处理方式
SpringMVC 三种异常处理方式 在 SpringMVC, SpringBoot 处理 web 请求时, 若遇到错误或者异常,返回给用户一个良好的错误信息比 Whitelabel Error Pa ...
- electron-vue-webpack引入bootstrap多实例问题Multiple instances of Vue detected!
在node modules里面找到electron-webpack目录, 修改out->main.js白名单内容,增加 whiteListedModules.add("bootstra ...
- SCRUM的五个价值观
转自:http://www.scrumcn.com/agile/scrum-knowledge-library/scrum.html#tab-id-8 承诺 – 愿意对目标做出承诺 专注– 把你的心思 ...