springBoot 創(chuàng)建定時任務(wù)過程詳解
前言
好幾天沒寫了,工作有點忙,最近工作剛好做一個定時任務(wù)統(tǒng)計的,所以就將springboot 如何創(chuàng)建定時任務(wù)整理了一下。
總的來說,springboot創(chuàng)建定時任務(wù)是非常簡單的,不用像spring 或者springmvc 需要在xml 文件中配置,在項目啟動的時候加載。spring boot 使用注解的方式就可以完全支持定時任務(wù)。
不過基礎(chǔ)注解的話,可能有的需求定時任務(wù)的時間會經(jīng)常變動,注解就不好修改,每次都得重新編譯,所以想將定時時間存在數(shù)據(jù)庫,然后項目讀取數(shù)據(jù)庫執(zhí)行定時任務(wù),所以就有了基于接口的定時任務(wù)。下面就分基于注解和基于接口詳細(xì)講解。
基于注解
pom.xml 文件不用修改,我們原本的項目就支持,其實定時器是springboot框架自帶的,不用引入什么依賴。我們直接創(chuàng)建一個autotask 包,創(chuàng)建一個AutoTask類。
@EnableScheduling @Component @Slf4j public class AutoTask { @Scheduled(cron="*/6 * * * * ?") private void process(){ log.info("autoTask "); } }
這樣一個定時器就創(chuàng)建啦,在項目啟動后,會每隔6s 打印“autoTask”的日志。是不是很簡單。主要用到的兩個注解就是@EnableScheduling 和 @Scheduled。
注解@EnableScheduling 就是開啟定時任務(wù)的。哪個類的中的方法想要定期執(zhí)行,就在這個類上加入這個注解。當(dāng)然這個這個注解也可以加在啟動類上。加在啟動類上表示項目中所有的類都可以創(chuàng)建定時任務(wù)。
@Scheduled 注解就是我們常見的定時器啦,后面的cron 就是定時任務(wù)表達(dá)式。在方法上注解,表示這個方法定期執(zhí)行。
不過@Scheduled 可以進(jìn)行兩種配置,我們熟悉的cron ,還有一種是fixedRate。比如fixedRate=6000 表示方法每6秒鐘執(zhí)行一次。
我們來啟動項目看一下,可以看到兩個方法都在定期執(zhí)行。
基于接口
上面可以看到springboot 基于注解是非常方便的。但是對于頻繁變動或者一個項目中有很多的定時器那就不方便管理了。所以統(tǒng)一將定時器信息存放在數(shù)據(jù)庫中。
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','定時器任務(wù)一','0/6 * * * * ?');
在dao 層mapper1包下創(chuàng)建一個CronMapper接口,很簡單的就獲取cron
public interface CronMapper { @Select("select cron from scheduled where cron_id = #{id}") public String getCron(int id); }
這里我們就不寫service 層了。直接在autotask 包下創(chuàng)建一個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 "); } }
可以看到也很簡單,就是實現(xiàn)SchedulingConfigurer 這個吧接口,addTriggerTask()是添加一個定時器。
process()方法是我們需要定時執(zhí)行的方法體。
CronTrigger(cron).nextExecutionTime(triggerContext) 就是從數(shù)據(jù)庫讀取的cron 創(chuàng)建定時器。
這個類我沒有加上@EnableScheduling 注解,因為我在啟動類上加上了,如果你們啟動類上沒有加,這里記得加上。
測試一下;下圖可以看到三個定時任務(wù)都執(zhí)行了,fromDB 是從數(shù)據(jù)庫讀取的。
cron
cron 用法網(wǎng)上有很多,也沒有什么講的這里就附帶記錄下
結(jié)構(gòu)
cron表達(dá)式是一個字符串,分為6或7個域,每兩個域之間用空格分隔,
其語法格式為:"秒域 分域 時域 日域 月域 周域 年域"
取值范圍
域名 | 可取值 | 可取符號(僅列部分常用) |
---|---|---|
秒域 | 0~59的整數(shù) | * - , / |
分域 | 0~59的整數(shù) | * - , / |
時域 | 0~23的整數(shù) | * - , / |
日域 | 1~31的整數(shù) | * - , / ? L |
月域 | 1~12的整數(shù)或JAN~DEC | * - , / |
周域 | 1~7的整數(shù)或SUN~SAT | * - , / ? L # |
年域 | 1970~2099的整數(shù) | * - , / |
常例
表達(dá)式 | 意義 |
---|---|
每隔5秒鐘執(zhí)行一次 | */5 * * * * ? |
每隔1分鐘執(zhí)行一次 | 0 * /1 * * * ? |
每天1點執(zhí)行一次 | 0 0 1 * * ? |
每天23點55分執(zhí)行一次 | 0 55 23 * * ? |
每月最后一天23點執(zhí)行一次 | 0 0 23 L * ? |
每周六8點執(zhí)行一次 | 0 0 8 ? * L |
每月最后一個周五,每隔2小時執(zhí)行一次 | 0 0 */2 ? * 6L |
每月的第三個星期五上午10:15執(zhí)行一次 | 0 15 10 ? * 5#3 |
在每天下午2點到下午2:05期間的每1分鐘執(zhí)行 | 0 0-5 14 * * ? |
表示周一到周五每天上午10:15執(zhí)行 | 0 15 10 ? * 2-6 |
每個月的最后一個星期五上午10:15執(zhí)行 | 0 15 10 ? * 6L |
每天上午10點,下午2點,4點執(zhí)行一次 | 0 0 10,14,16 * * ? |
朝九晚五工作時間內(nèi)每半小時執(zhí)行一次 | 0 0/30 9-17 * * ? |
每個星期三中午12點執(zhí)行一次 | 0 0 12 ? * 4 |
每年三月的星期三的下午2:10和2:44各執(zhí)行一次 | 0 10,44 14 ? 3 4 |
每月的第三個星期五上午10:15執(zhí)行一次 | 0 15 10 ? * 6#3 |
每月一日凌晨2點30執(zhí)行一次 | 0 30 2 1 * ? |
每分鐘的第10秒與第20秒都會執(zhí)行 | 10,20 * * * * ? |
每月的第2個星期的周5,凌晨執(zhí)行 | 0 0 0 ? * 6#2 |
番外
本來這個知識點不應(yīng)該放在這里講的,但是不多,順帶寫了,剛好也能做定時器。我們項目中往往有一些需求需要在項目啟動的時候就執(zhí)行,那這個我們怎么實現(xiàn)了。其實spring boot 使用起來也非常簡單,只用實現(xiàn) ApplicationRunner 就好了。
我們在autotask 包下創(chuàng)建一個AutoTaskFromSpringRunner類
@Slf4j @Component public class AutoTaskFromSpringRunner implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { process(); } private void process(){ log.info(" run ApplicationArguments"); } }
啟動項目看一下,可以發(fā)現(xiàn)這個會在項目啟動后執(zhí)行,但是只會執(zhí)行一次。
那這個怎么用來做定時器呢?當(dāng)然是結(jié)合線程來做啦,但是這個方法其實不建議,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("線程定時器"); } }
啟動項目看下,發(fā)現(xiàn)也是可以起到定時器的作用的。
好了,就說這么多啦,今天項目的代碼也同步到github 上啦。
github地址:https://github.com/QuellanAn/zlflovemm
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java實現(xiàn)畫圖 給圖片底部添加文字標(biāo)題
這篇文章主要介紹了Java實現(xiàn)畫圖 給圖片底部添加文字標(biāo)題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11Java設(shè)計模式模板方法模式(Template)用法解析
這篇文章主要介紹了Java設(shè)計模式模板方法模式(Template)用法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-11-11使用Swagger時Controller中api接口顯示不全的問題分析及解決
swagger是一個十分好用的api接口管理、測試框架,現(xiàn)在越來越多的人使用這個做接口的測試和管理,但經(jīng)常遇到Controller中的api接口顯示不全的問題,所以本文給大家詳細(xì)分析了問題以及解決方法,需要的朋友可以參考下2024-02-02解析SpringSecurity+JWT認(rèn)證流程實現(xiàn)
這篇文章主要介紹了解析SpringSecurity+JWT認(rèn)證流程實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07