SpringBoot下定時任務的實現方法
參考江南一點雨大佬的文章:
https://www.cnblogs.com/lenve/p/10728897.html
cron工具網站:
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()); } }
- 首先使用 @Scheduled 註解開啟一個定時任務。
- fixedRate 表示任務執行之間的時間間隔,具體是指兩次任務的開始時間間隔,即第二次任務開始時,第一次任務可能還沒結束。
- fixedDelay 表示任務執行之間的時間間隔,具體是指本次任務結束到下次任務開始之間的時間間隔。
- initialDelay 表示首次任務啟動的延遲時間。
- 所有時間的單位都是毫秒。
二、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())); } }
關於這種定義方式說兩點:
- 首先將這個 Job 註冊到 Spring 容器中。
- 這種定義方式有一個缺陷,就是無法傳參。
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專案即可:
關於這個配置說如下幾點:
- JobDetail 的配置有兩種方式:MethodInvokingJobDetailFactoryBean 和 JobDetailFactoryBean 。
- 使用 MethodInvokingJobDetailFactoryBean 可以配置目標 Bean 的名字和目標方法的名字,這種方式不支援傳參。
- 使用 JobDetailFactoryBean 可以配置 JobDetail ,任務類繼承自 QuartzJobBean ,這種方式支援傳參,將引數封裝在 JobDataMap 中進行傳遞。
- Trigger 是指觸發器,Quartz 中定義了多個觸發器,這裡向大家展示其中兩種的用法,SimpleTrigger 和 CronTrigger 。
- SimpleTrigger 有點類似於前面說的 @Scheduled 的基本用法。
- CronTrigger 則有點類似於 @Scheduled 中 cron 表示式的用法。