1. 程式人生 > 其它 >SpringBoot下定時任務的實現方法

SpringBoot下定時任務的實現方法

參考江南一點雨大佬的文章:

https://www.cnblogs.com/lenve/p/10728897.html

cron工具網站:

  https://tool.lu/crontab/

  https://www.bejson.com/othertools/cron/

寫在前面:Linux下的Cron跟Spring下的Cron表示式有些許的不一樣,注意到網站上去驗證

SpringBoot中實現定時任務的兩種方式

  在 Spring + SpringMVC 環境中,一般來說,要實現定時任務,我們有兩中方案,一種是使用 Spring 自帶的定時任務處理器 @Scheduled 註解,另一種就是使用第三方框架 Quartz 。

Spring Boot 源自 Spring+SpringMVC ,因此天然具備這兩個 Spring 中的定時任務實現策略,當然也支援 Quartz,本文我們就來看下 Spring Boot 中兩種定時任務的實現方式;

一、@Scheduled

使用 @Scheduled 非常容易,直接建立一個 Spring Boot 專案,並且新增 web 依賴spring-boot-starter-web,專案建立成功後,新增@EnableScheduling註解

1、開啟定時任務:

@EnableScheduling
@SpringBootApplication
public class Springboot19ScheduledApplication {

    public static void main(String[] args) {
        SpringApplication.run(Springboot19ScheduledApplication.class, args);
    }
}

2、配置定時任務:具體的表示式請參考上面的網址自行驗證

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.Date;

/**
 * @ClassName ScheduledTaskConfig
 * @Author zhangzhixi
 * @Description 定時任務配置類
 * @Date 2022-2-27 19:20
 * @Version 1.0
 */
@Configuration
public class ScheduledTaskConfig {
    @Scheduled(fixedRate = 2000)
    public void fixedRate() {
        System.out.println("fixedRate>>>" + new Date());
    }

    @Scheduled(fixedDelay = 2000)
    public void fixedDelay() {
        System.out.println("fixedDelay>>>" + new Date());
    }

    @Scheduled(initialDelay = 2000, fixedDelay = 2000)
    public void initialDelay() {
        System.out.println("initialDelay>>>" + new Date());
    }

    /**
     * 每5秒執行一次
     */
    @Scheduled(cron = "0/5 * * * * *")
    public void cron() {
        System.out.println("cronExpression>>>" + new Date());
    }
}
  1. 首先使用 @Scheduled 註解開啟一個定時任務。
  2. fixedRate 表示任務執行之間的時間間隔,具體是指兩次任務的開始時間間隔,即第二次任務開始時,第一次任務可能還沒結束。
  3. fixedDelay 表示任務執行之間的時間間隔,具體是指本次任務結束到下次任務開始之間的時間間隔。
  4. initialDelay 表示首次任務啟動的延遲時間。
  5. 所有時間的單位都是毫秒。

二、Quatz

一般在專案中,除非定時任務涉及到的業務實在是太簡單,使用 @Scheduled 註解來解決定時任務,否則大部分情況可能都是使用 Quartz 來做定時任務。在 Spring Boot 中使用 Quartz ,只需要在建立專案時,新增 Quartz 依賴即可:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

1:開啟定時任務的註解

@EnableScheduling
@SpringBootApplication
public class Springboot18QuartzApplication {
    public static void main(String[] args) {
        SpringApplication.run(Springboot18QuartzApplication.class, args);
    }
}

Quartz 在使用過程中,有兩個關鍵概念,一個是JobDetail(要做的事情),另一個是觸發器(什麼時候做),要定義 JobDetail,需要先定義 Job,Job 的定義有兩種方式:  

2.1:Job的第一種定義方式:直接定義bean

/**
 * @ClassName MyJobOne
 * @Author zhangzhixi
 * @Description
 * @Date 2022-2-27 16:58
 * @Version 1.0
 */
@Component
public class MyJobOne {
    public void sayHello() {
        System.out.println(MyJobOne.class + "========>" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }
}

關於這種定義方式說兩點:

  1. 首先將這個 Job 註冊到 Spring 容器中。
  2. 這種定義方式有一個缺陷,就是無法傳參。

2.2:Job的第二種定義方式:繼承 QuartzJobBean 並實現預設的方法

/**
 * @ClassName MyJonTwo
 * @Author zhangzhixi
 * @Description
 * @Date 2022-2-27 17:01
 * @Version 1.0
 */
@Component
public class MyJonTwo extends QuartzJobBean {

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) {
        new HelloService().sayHello();
    }
}

HelloService:

/**
 * @ClassName HelloService
 * @Author zhangzhixi
 * @Description
 * @Date 2022-2-27 17:07
 * @Version 1.0
 */
public class HelloService {
    public void sayHello() {
        System.out.println(HelloService.class + "========>" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }
}

和第1種方式相比,這種方式支援傳參,任務啟動時,executeInternal 方法將會被執行。

Job 有了之後,接下來建立類,配置 JobDetail 和 Trigger 觸發器,如下:

3:配置觸發器

/**
 * @ClassName QuartzConfig
 * @Author zhangzhixi
 * @Description
 * @Date 2022-2-27 17:05
 * @Version 1.0
 */
@Configuration
public class QuartzConfig {
    /**
     * JobDetail的配置1:
     *      使用 MethodInvokingJobDetailFactoryBean 可以配置目標 Bean 的名字和目標方法的名字,這種方式不支援傳參。
     * @return
     */
    @Bean
    MethodInvokingJobDetailFactoryBean methodInvokingJobDetailFactoryBean() {
        MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean();
        bean.setTargetBeanName("myJobOne");
        bean.setTargetMethod("sayHello");
        return bean;
    }

    /**
     * JobDetail的配置2:
     *      使用 JobDetailFactoryBean 可以配置 JobDetail ,任務類繼承自 QuartzJobBean ,這種方式支援傳參,將引數封裝在 JobDataMap 中進行傳遞。
     * @return
     */
    @Bean
    JobDetailFactoryBean jobDetailFactoryBean() {
        JobDetailFactoryBean bean = new JobDetailFactoryBean();
        bean.setJobClass(MyJonTwo.class);

        JobDataMap map = new JobDataMap();
        map.put("helloService", helloService());

        bean.setJobDataMap(map);
        return bean;
    }


    /**
     * 觸發器:simpleTrigger
     * @return
     */
    @Bean
    SimpleTriggerFactoryBean simpleTriggerFactoryBean() {
        SimpleTriggerFactoryBean bean = new SimpleTriggerFactoryBean();
        /*1.設定觸發器開始的時間*/
        bean.setStartTime(new Date());
        /*2.設定觸發器執行的次數*/
        bean.setRepeatCount(5);
        /*3.設定執行間隔(單位:ms)*/
        bean.setRepeatInterval(3000);
        /*4.新增MethodInvokingJobDetailFactoryBean觸發器的設定*/
        bean.setJobDetail(Objects.requireNonNull(methodInvokingJobDetailFactoryBean().getObject()));
        return bean;
    }

    /**
     * 觸發器:cronTrigger
     * @return
     */
    @Bean
    CronTriggerFactoryBean cronTrigger() {
        CronTriggerFactoryBean bean = new CronTriggerFactoryBean();
        /*1、新增cron表示式*/
        bean.setCronExpression("0/10 * * * * ?");
        /*2、新增JobDetailFactoryBean的設定*/
        bean.setJobDetail(Objects.requireNonNull(jobDetailFactoryBean().getObject()));
        return bean;
    }

    /**
     * 觸發器程式排程工廠,傳入觸發器
     * @return
     */
    @Bean
    SchedulerFactoryBean schedulerFactoryBean() {
        SchedulerFactoryBean bean = new SchedulerFactoryBean();
        /*傳入觸發器:引數是可變長引數*/
        bean.setTriggers(cronTrigger().getObject(), simpleTriggerFactoryBean().getObject());
        return bean;
    }

    @Bean
    HelloService helloService() {
        return new HelloService();
    }
}

啟動SpringBoot專案即可:

關於這個配置說如下幾點:

  1. JobDetail 的配置有兩種方式:MethodInvokingJobDetailFactoryBean 和 JobDetailFactoryBean 。
  2. 使用 MethodInvokingJobDetailFactoryBean 可以配置目標 Bean 的名字和目標方法的名字,這種方式不支援傳參。
  3. 使用 JobDetailFactoryBean 可以配置 JobDetail ,任務類繼承自 QuartzJobBean ,這種方式支援傳參,將引數封裝在 JobDataMap 中進行傳遞。
  4. Trigger 是指觸發器,Quartz 中定義了多個觸發器,這裡向大家展示其中兩種的用法,SimpleTrigger 和 CronTrigger 。
  5. SimpleTrigger 有點類似於前面說的 @Scheduled 的基本用法。
  6. CronTrigger 則有點類似於 @Scheduled 中 cron 表示式的用法。