您好,登錄后才能下訂單哦!
springBoot中怎么創(chuàng)建定時任務(wù),很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。
基于注解
pom.xml 文件不用修改,我們原本的項目就支持,其實定時器是springboot框架自帶的,不用引入什么依賴。我們直接創(chuàng)建一個autotask 包,創(chuàng)建一個AutoTask類。
@EnableScheduling@Component@Slf4jpublic class AutoTask { @Scheduled(cron="*/6 * * * * ?") private void process(){ log.info("autoTask "); }}
這樣一個定時器就創(chuàng)建啦,在項目啟動后,會每隔6s 打印“autoTask”的日志。是不是很簡單。主要用到的兩個注解就是@EnableScheduling 和 @Scheduled。
注解@EnableScheduling 就是開啟定時任務(wù)的。哪個類的中的方法想要定期執(zhí)行,就在這個類上加入這個注解。當然這個這個注解也可以加在啟動類上。加在啟動類上表示項目中所有的類都可以創(chuàng)建定時任務(wù)。
@Scheduled 注解就是我們常見的定時器啦,后面的cron 就是定時任務(wù)表達式。在方法上注解,表示這個方法定期執(zhí)行。
不過@Scheduled 可以進行兩種配置,我們熟悉的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@Componentpublic 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表達式是一個字符串,分為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ù) * - , /
常例
每隔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@Componentpublic class AutoTaskFromSpringRunner implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { process(); } private void process(){ log.info(" run ApplicationArguments"); }}
那這個怎么用來做定時器呢?當然是結(jié)合線程來做啦,但是這個方法其實不建議,b畢竟線程很容易出問題,但是提供一種思路:啟動項目看一下,可以發(fā)現(xiàn)這個會在項目啟動后執(zhí)行,但是只會執(zhí)行一次。
@Slf4j@Componentpublic 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("線程定時器"); }}
看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進一步的了解或閱讀更多相關(guān)文章,請關(guān)注億速云行業(yè)資訊頻道,感謝您對億速云的支持。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。