springBoot  創(chuàng)建定時(shí)任務(wù)過(guò)程詳解

前言

創(chuàng)新互聯(lián)長(zhǎng)期為上1000+客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為雞西企業(yè)提供專業(yè)的做網(wǎng)站、成都做網(wǎng)站,雞西網(wǎng)站改版等技術(shù)服務(wù)。擁有十余年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。

好幾天沒(méi)寫(xiě)了,工作有點(diǎn)忙,最近工作剛好做一個(gè)定時(shí)任務(wù)統(tǒng)計(jì)的,所以就將springboot 如何創(chuàng)建定時(shí)任務(wù)整理了一下。
總的來(lái)說(shuō),springboot創(chuàng)建定時(shí)任務(wù)是非常簡(jiǎn)單的,不用像spring 或者springmvc 需要在xml 文件中配置,在項(xiàng)目啟動(dòng)的時(shí)候加載。spring boot 使用注解的方式就可以完全支持定時(shí)任務(wù)。

不過(guò)基礎(chǔ)注解的話,可能有的需求定時(shí)任務(wù)的時(shí)間會(huì)經(jīng)常變動(dòng),注解就不好修改,每次都得重新編譯,所以想將定時(shí)時(shí)間存在數(shù)據(jù)庫(kù),然后項(xiàng)目讀取數(shù)據(jù)庫(kù)執(zhí)行定時(shí)任務(wù),所以就有了基于接口的定時(shí)任務(wù)。下面就分基于注解和基于接口詳細(xì)講解。

基于注解

pom.xml 文件不用修改,我們?cè)镜捻?xiàng)目就支持,其實(shí)定時(shí)器是springboot框架自帶的,不用引入什么依賴。我們直接創(chuàng)建一個(gè)autotask 包,創(chuàng)建一個(gè)AutoTask類。

@EnableScheduling
@Component
@Slf4j
public class AutoTask {
 @Scheduled(cron="*/6 * * * * ?")
 private void process(){
  log.info("autoTask ");
 }
}

這樣一個(gè)定時(shí)器就創(chuàng)建啦,在項(xiàng)目啟動(dòng)后,會(huì)每隔6s 打印“autoTask”的日志。是不是很簡(jiǎn)單。主要用到的兩個(gè)注解就是@EnableScheduling 和 @Scheduled。

注解@EnableScheduling 就是開(kāi)啟定時(shí)任務(wù)的。哪個(gè)類的中的方法想要定期執(zhí)行,就在這個(gè)類上加入這個(gè)注解。當(dāng)然這個(gè)這個(gè)注解也可以加在啟動(dòng)類上。加在啟動(dòng)類上表示項(xiàng)目中所有的類都可以創(chuàng)建定時(shí)任務(wù)。

springBoot  創(chuàng)建定時(shí)任務(wù)過(guò)程詳解

@Scheduled 注解就是我們常見(jiàn)的定時(shí)器啦,后面的cron 就是定時(shí)任務(wù)表達(dá)式。在方法上注解,表示這個(gè)方法定期執(zhí)行。

springBoot  創(chuàng)建定時(shí)任務(wù)過(guò)程詳解

不過(guò)@Scheduled 可以進(jìn)行兩種配置,我們熟悉的cron ,還有一種是fixedRate。比如fixedRate=6000 表示方法每6秒鐘執(zhí)行一次。

我們來(lái)啟動(dòng)項(xiàng)目看一下,可以看到兩個(gè)方法都在定期執(zhí)行。

springBoot  創(chuàng)建定時(shí)任務(wù)過(guò)程詳解

基于接口

上面可以看到springboot 基于注解是非常方便的。但是對(duì)于頻繁變動(dòng)或者一個(gè)項(xiàng)目中有很多的定時(shí)器那就不方便管理了。所以統(tǒng)一將定時(shí)器信息存放在數(shù)據(jù)庫(kù)中。

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','定時(shí)器任務(wù)一','0/6 * * * * ?');

springBoot  創(chuàng)建定時(shí)任務(wù)過(guò)程詳解

在dao 層mapper1包下創(chuàng)建一個(gè)CronMapper接口,很簡(jiǎn)單的就獲取cron

public interface CronMapper {

 @Select("select cron from scheduled where cron_id = #{id}")
 public String getCron(int id);
}

springBoot  創(chuàng)建定時(shí)任務(wù)過(guò)程詳解

這里我們就不寫(xiě)service 層了。直接在autotask 包下創(chuàng)建一個(gè)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 ");
 }
}

可以看到也很簡(jiǎn)單,就是實(shí)現(xiàn)SchedulingConfigurer 這個(gè)吧接口,addTriggerTask()是添加一個(gè)定時(shí)器。
process()方法是我們需要定時(shí)執(zhí)行的方法體。

CronTrigger(cron).nextExecutionTime(triggerContext) 就是從數(shù)據(jù)庫(kù)讀取的cron 創(chuàng)建定時(shí)器。

這個(gè)類我沒(méi)有加上@EnableScheduling 注解,因?yàn)槲以趩?dòng)類上加上了,如果你們啟動(dòng)類上沒(méi)有加,這里記得加上。

測(cè)試一下;下圖可以看到三個(gè)定時(shí)任務(wù)都執(zhí)行了,fromDB 是從數(shù)據(jù)庫(kù)讀取的。

springBoot  創(chuàng)建定時(shí)任務(wù)過(guò)程詳解

cron

cron 用法網(wǎng)上有很多,也沒(méi)有什么講的這里就附帶記錄下

結(jié)構(gòu)

cron表達(dá)式是一個(gè)字符串,分為6或7個(gè)域,每?jī)蓚€(gè)域之間用空格分隔,

其語(yǔ)法格式為:"秒域 分域 時(shí)域 日域 月域 周域 年域"

取值范圍

域名可取值可取符號(hào)(僅列部分常用)
秒域0~59的整數(shù)* - , /
分域0~59的整數(shù)* - , /
時(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點(diǎn)執(zhí)行一次    0 0 1 * * ?
每天23點(diǎn)55分執(zhí)行一次     0 55 23 * * ?
每月最后一天23點(diǎn)執(zhí)行一次    0 0 23 L * ?
每周六8點(diǎn)執(zhí)行一次    0 0 8 ? * L
每月最后一個(gè)周五,每隔2小時(shí)執(zhí)行一次     0 0 */2 ? * 6L
每月的第三個(gè)星期五上午10:15執(zhí)行一次    0 15 10 ? * 5#3
在每天下午2點(diǎn)到下午2:05期間的每1分鐘執(zhí)行    0 0-5 14 * * ?
表示周一到周五每天上午10:15執(zhí)行     0 15 10 ? * 2-6
每個(gè)月的最后一個(gè)星期五上午10:15執(zhí)行    0 15 10 ? * 6L
每天上午10點(diǎn),下午2點(diǎn),4點(diǎn)執(zhí)行一次    0 0 10,14,16 * * ?
朝九晚五工作時(shí)間內(nèi)每半小時(shí)執(zhí)行一次    0 0/30 9-17 * * ?
每個(gè)星期三中午12點(diǎn)執(zhí)行一次     0 0 12 ? * 4
每年三月的星期三的下午2:10和2:44各執(zhí)行一次    0 10,44 14 ? 3 4 
每月的第三個(gè)星期五上午10:15執(zhí)行一次    0 15 10 ? * 6#3
每月一日凌晨2點(diǎn)30執(zhí)行一次    0 30 2 1 * ?
每分鐘的第10秒與第20秒都會(huì)執(zhí)行    10,20 * * * * ?
每月的第2個(gè)星期的周5,凌晨執(zhí)行    0 0 0 ? * 6#2

番外

本來(lái)這個(gè)知識(shí)點(diǎn)不應(yīng)該放在這里講的,但是不多,順帶寫(xiě)了,剛好也能做定時(shí)器。我們項(xiàng)目中往往有一些需求需要在項(xiàng)目啟動(dòng)的時(shí)候就執(zhí)行,那這個(gè)我們?cè)趺磳?shí)現(xiàn)了。其實(shí)spring boot 使用起來(lái)也非常簡(jiǎn)單,只用實(shí)現(xiàn) ApplicationRunner 就好了。

我們?cè)赼utotask 包下創(chuàng)建一個(gè)AutoTaskFromSpringRunner類

@Slf4j
@Component
public class AutoTaskFromSpringRunner implements ApplicationRunner {

 @Override
 public void run(ApplicationArguments args) throws Exception {
  process();
 }

 private void process(){
  log.info(" run ApplicationArguments");
 }
}

啟動(dòng)項(xiàng)目看一下,可以發(fā)現(xiàn)這個(gè)會(huì)在項(xiàng)目啟動(dòng)后執(zhí)行,但是只會(huì)執(zhí)行一次。

springBoot  創(chuàng)建定時(shí)任務(wù)過(guò)程詳解

那這個(gè)怎么用來(lái)做定時(shí)器呢?當(dāng)然是結(jié)合線程來(lái)做啦,但是這個(gè)方法其實(shí)不建議,b畢竟線程很容易出問(wèn)題,但是提供一種思路:

@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("線程定時(shí)器");
 }
}

啟動(dòng)項(xiàng)目看下,發(fā)現(xiàn)也是可以起到定時(shí)器的作用的。

springBoot  創(chuàng)建定時(shí)任務(wù)過(guò)程詳解

好了,就說(shuō)這么多啦,今天項(xiàng)目的代碼也同步到github 上啦。

github地址:https://github.com/QuellanAn/zlflovemm

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。

當(dāng)前標(biāo)題:springBoot  創(chuàng)建定時(shí)任務(wù)過(guò)程詳解
URL網(wǎng)址:http://muchs.cn/article42/gpjdec.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、動(dòng)態(tài)網(wǎng)站、App開(kāi)發(fā)、網(wǎng)站改版

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁(yè)設(shè)計(jì)