本文記錄在SpringBoot中使用定時任務。
在我們的項目中,經常需要用到定時任務去幫我們做一些事情,比如服務狀態監控,業務數據狀態的更改等,SpringBoot中實現定時任務有2中方案,一種是自帶的,我們只需要加上注解即可;另一種是集成Quartz來實現定時任務。
一 SpringBoot 提供的定時任務
在SpringBoot的starter包中已經提供了對定時任務的支持,我們很容易實現定時任務。修改pom.xml文件,加入如下內容,引入依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
在啟動類上加注@EnableScheduling 注解,開啟定時任務
@SpringBootApplication
@EnableScheduling
public class TimingTaskApplication {
public static void main(String[] args) {
SpringApplication.run(TimingTaskApplication.class, args);
}
}
創建定時任務類及要定時執行的方法
@Component
public class ScheduleTaskDemo {
private int num1 = 0;
private DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Scheduled(cron = "*/5 * * * * ?")
public void test1(){
System.out.println("這是test1方法第"+ (++num1) + "次執行,執行時間:"+df.format(new Date()));
}
}
@Component 注解 將當前類交給Spring容器管理
@Scheduled 注解標明方法是一個定時執行的方法
啟動項目后可以看到控制台打印出的信息

@Scheduled 注解有幾個參數可以使用,每個參數的意義不一樣,參數及執行規則說明如下:
fixedRate @Scheduled(fixedRate = 5000) 上一次開始執行時間點之后每5秒執行一次;
fixedDelay @Scheduled(fixedDelay = 5) 上一次執行完畢時間點之后每5秒執行一次;
initialDelay @Scheduled(initialDelay = 1, fixedDelay = 6) 第一次延遲1秒后執行,之后按照fixedRate的規則執行;
cron @Scheduled(cron = "*/5 * * * * ?") 一個表達式,一共有7位,一般只需要設置6為就可以了
第一位:秒,取值范圍是0-59;
第二位:分,取值范圍是0-59;
第三位:時,取值范圍0-23;
第四位:日,取值范圍1-31;
第五位:月,取值范圍1-12;
第六位:星期,取值范圍1-7,1代表星期日,2代表星期一,7代表星期六;
第七位:年,取值范圍1970-099,可以不設置。
cron表達式也可以在http://cron.qqe2.com進行在線生成。
二 SpringBoot集成Quartz
Quartz是用Java編寫的一個開源的任務調度框架。提供了豐富的Api供調用,支持集群環境和持久化,支持多種配置,與SpringBoot可以無縫集成。
Quartz幾個關鍵元素:
Job 代表要執行的任務,是個接口,提供了一個方法 execute(JobExecutionContext context);
JobDetail 代表具體的要執行的任務;
Trigger 代表調度任務的觸發器,配置調度任務的執行規則;
Scheduler 代表調度容器,一個調度容器中可以注冊多個JobDetail和Trigger。
元素關系如下圖:

SpringBoot對Quartz已經提供了支持,我們可以很容易的使用,在pom.xml文件中引入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
在啟動類上加注解 @EnableScheduling ,開啟定時執行。
創建一個要執行的任務繼承QuartzJobBean,輸出任務執行時間
public class MyTask1 extends QuartzJobBean {
private DateFormat df = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("MyTask1 執行時間:" + df.format(new Date()));
}
}
創建一個配置類,初始化MyTask1任務所需要的JobDetail和Trigger
@SpringBootConfiguration
public class QuartzConfig {
@Bean
public JobDetail myTask1JobDetail(){
return JobBuilder.newJob(MyTask1.class).withIdentity("myTask1").storeDurably().build();
}
@Bean
public Trigger myTask1Trigger(){
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
//5秒執行一次
.withIntervalInSeconds(5)
.repeatForever();
SimpleTrigger trigger = TriggerBuilder.newTrigger()
//指定觸發器對應的JobDetail
.forJob(myTask1JobDetail())
.withIdentity("myTask1")
.withSchedule(scheduleBuilder).build();
return trigger;
}
}
啟動項目,可以看到控制台輸出的內容

在上邊的方法,我們使用的定時執行方法是在代碼中寫的固定值,這種局限性比較大,難以滿足一些復雜的定制任務執行時間。我們使用Cron表達式來完成定時任務執行時間配置。
創建任務類,繼承QuartzJobBean
public class MyTask2 extends QuartzJobBean {
private DateFormat df = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("MyTask2 執行時間:" + df.format(new Date()));
}
}
在配置類QuartzConfig中創建任務所需的JobDetail和Trigger
@Bean
public JobDetail myTask2JobDetail(){
return JobBuilder.newJob(MyTask2.class).withIdentity("myTask2").storeDurably().build();
}
@Bean
public Trigger myTask2Trigger(){
//cron 表達式
String cronStr = "*/10 * * * * ?";
//根據表達式設置ScheduleBuilder
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronStr);
CronTrigger trigger = TriggerBuilder.newTrigger()
//指定JobDetail
.forJob(myTask2JobDetail())
.withIdentity("myTask2")
//指定ScheduleBuilder
.withSchedule(cronScheduleBuilder)
.build();
return trigger;
}
重啟項目,看到控制台輸出內容,任務1每5秒執行一次,任務2每10秒執行一次

