前言

好几天没写了,工作有点忙,最近工作刚好做一个定时任务统计的,所以就将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 优雅的创建定时任务的更多相关文章

  1. SpringBoot使用@Scheduled创建定时任务

    定时任务一般会存在中大型企业级项目中,为了减少服务器.数据库的压力往往会采用时间段性的去完成某些业务逻辑.比较常见的就是金融服务系统推送回调,一般支付系统订单在没有收到成功的回调返回内容时会持续性的回 ...

  2. MAC本如何优雅的创建定时任务

    在MACOS上设置定时任务大体有两种方案.一种是使用crontab,一种是使用Schedule,今天结合我的使用简单介绍一下. 先说一下背景,为什么MAC可以用crontab.如果使用过Linux的同 ...

  3. Springboot定时任务原理及如何动态创建定时任务

    一.前言 上周工作遇到了一个需求,同步多个省份销号数据,解绑微信粉丝.分省定时将销号数据放到SFTP服务器上,我需要开发定时任务去解析文件.因为是多省份,服务器.文件名规则.数据规则都不一定,所以要做 ...

  4. SpringBoot中使用@Scheduled创建定时任务

    SpringBoot中使用@Scheduled创建定时任务 定时任务一般会在很多项目中都会用到,我们往往会间隔性的的去完成某些特定任务来减少服务器和数据库的压力.比较常见的就是金融服务系统推送回调,一 ...

  5. SpringBoot(十四)_springboot使用内置定时任务Scheduled的使用(一)

    为什么使用定时? 日常工作中,经常会用到定时任务,比如各种统计,并不要求实时性.此时可以通过提前设置定时任务先把数据跑出来,后续处理起来更方便. 本篇文章主要介绍 springboot内置定时任务. ...

  6. SpringBoot创建定时任务

    之前总结过spring+quartz实现定时任务的整合http://www.cnblogs.com/gdpuzxs/p/6663725.html,而springboot创建定时任务则是相当简单. (1 ...

  7. SpringBoot基于数据库的定时任务实现

    在我们平时开发的项目中,定时任务基本属于必不可少的功能,那大家都是怎么做的呢?但我知道的大多都是静态定时任务实现. 基于注解来创建定时任务非常简单,只需几行代码便可完成.实现如下: @Configur ...

  8. JAVAEE——BOS物流项目13:Quartz概述、创建定时任务、使用JavaMail发送邮件、HighCharts概述、实现区域分区分布图

    1 学习计划 1.Quartz概述 n Quartz介绍和下载 n 入门案例 n Quartz执行流程 n cron表达式 2.在BOS项目中使用Quartz创建定时任务 3.在BOS项目中使用Jav ...

  9. windows创建定时任务执行python脚本

    一.创建定时任务 \ [程序或脚本]文本框中填的是Python编译器的名称,一般就是python.exe, [起始于]文本框中填的是Python编译器的目录,上图中假设你的Python编译器的完整路径 ...

随机推荐

  1. VMware Workstation 15 Pro 永久激活密钥

    VMware Workstation 15 Pro 永久激活密钥   一. 激活密钥 YG5H2-ANZ0H-M8ERY-TXZZZ-YKRV8 UG5J2-0ME12-M89WY-NPWXX-WQH ...

  2. 【数据结构】9.java源码关于HashTable

    1.hashtable的内部结构 基础存储数据的hash桶由Entry结构的数组存放而entry数据结构,有hash,key和value,还有一个指向下一个节点的引用next对象 这里就和hashma ...

  3. layui下拉框不显示的问题

    1.先检查有没有引入layui.js 2.然后看有没有被<form class="layui-form"></form>包住, 3.查看是否有以下代码 &l ...

  4. python 35 多线程

    目录 多线程 1. 线程 2. 线程vs进程 3. 开启线程的两种方法. 4. 线程的特性 5. 线程的相关方法 6. join 阻塞 7. 守护线程 daemon 8. 互斥锁 多线程 1. 线程 ...

  5. HDU 5135

    题意略. 思路: 本题开始我先写了一发dfs暴力,然而递归程度太深,导致爆栈.仔细回想一下dfs的过程,发现最不好处理的就是每收集到3个木棍,才能构成一个三角形. 并且,还有一个隐患就是不能完全枚举出 ...

  6. Java集合框架之ArrayList浅析

    Java集合框架之ArrayList浅析 一.ArrayList综述: 位于java.util包下的ArrayList是java集合框架的重要成员,它就是传说中的动态数组,用MSDN中的说法,就是Ar ...

  7. Windows下Python 3.6 + VS2017 + Anaconda 解决Unable to find vcvarsall.bat问题

    Python 3.6 + VS2017 + Anaconda 解决Unable to find vcvarsall.bat问题 已经安装了VS2017,需要将项目中的C代码翻译为Python代码,在编 ...

  8. cogs1709. [SPOJ 705] 不同的子串(后缀数组

    http://cogs.pro:8080/cogs/problem/problem.php?pid=vyziQkWaP 题意:给定一个字符串,计算其不同的子串个数. 思路:ans=总共子串个数-相同的 ...

  9. UVA10330拆点最大流

    #include <iostream> #include <cstdio> #include <cstring> #include <queue> #i ...

  10. hihocoder #1609 : 数组分拆II(思维)

    题目链接:http://hihocoder.com/problemset/problem/1609 题解:就先拿一个数组最多分成两部分来说吧 8 1 2 3 4 5 1 2 3 显然 输出时2 3 可 ...