🌟 前言
歡迎來到我的技術小宇宙!🌌 這里不僅是我記錄技術點滴的后花園,也是我分享學習心得和項目經驗的樂園。📚 無論你是技術小白還是資深大牛,這里總有一些內容能觸動你的好奇心。🔍
🤖 洛可可白:個人主頁
🔥 個人專欄:?前端技術 ?后端技術
🏠 個人博客:洛可可白博客
🐱 代碼獲取:bestwishes0203
📷 封面壁紙:洛可可白wallpaper

這里寫自定義目錄標題
- Spring Boot 定時任務的多種實現方式
- 1. 使用 `@Scheduled` 注解
- 示例代碼
- 優點
- 缺點
- 2. 使用 `ScheduledExecutorService`
- 示例代碼
- 優點
- 缺點
- 3. 使用 Quartz 框架
- 示例代碼
- 優點
- 缺點
- 4. 使用 `SchedulingConfigurer` 接口
- 示例代碼
- 優點
- 缺點
- 5. 使用 `TaskScheduler` 接口
- 示例代碼
- 優點
- 缺點
- 6. 使用 Redis 實現分布式定時任務
- 示例代碼
- 優點
- 缺點
- 7. 使用 XXL-JOB 或 Elastic-Job
- 示例代碼(XXL-JOB)
- 優點
- 缺點
- 總結
- 選擇合適的定時任務實現方式
- 示例項目結構
- 示例代碼完整版
- `DemoApplication.java`
- `SchedulingConfig.java`
- `ScheduledTask.java`
- `RedisConfig.java`
- `RedisDistributedTask.java`
- `application.properties`
- 結語
Spring Boot 定時任務的多種實現方式
在現代的 Spring Boot 應用程序中,定時任務是一種常見的需求。無論是定期清理日志、同步數據,還是執行定時的業務邏輯,Spring Boot 提供了多種靈活的方式來實現定時任務。本文將詳細介紹幾種常見的定時任務實現方式,并通過示例代碼幫助你快速上手。
1. 使用 @Scheduled
注解
@Scheduled
是 Spring Boot 提供的一種簡單且強大的定時任務實現方式,適用于大多數簡單的定時任務場景。
示例代碼
配置類:
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;@Configuration
@EnableScheduling
public class SchedulingConfig {// 啟用定時任務支持
}
任務類:
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;@Component
public class ScheduledTask {// 固定頻率:每5秒執行一次任務@Scheduled(fixedRate = 5000)public void executeTask() {System.out.println("【@Scheduled 任務】執行時間:" + LocalDateTime.now());}// Cron 表達式:每天中午12點執行一次任務@Scheduled(cron = "0 0 12 * * ?")public void executeCronTask() {System.out.println("【Cron 任務】執行時間:" + LocalDateTime.now());}
}
優點
- 簡單易用:只需添加注解即可實現定時任務。
- 集成度高:與 Spring 容器無縫集成,支持依賴注入。
缺點
- 單節點運行:默認情況下,
@Scheduled
任務僅在單個節點上運行,不支持分布式場景。
2. 使用 ScheduledExecutorService
ScheduledExecutorService
是 Java 提供的原生定時任務工具,適合需要更細粒度控制的任務調度場景。
示例代碼
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;public class ScheduledExecutorServiceExample {public static void main(String[] args) {ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);executor.scheduleAtFixedRate(() -> {System.out.println("任務執行:" + System.currentTimeMillis());}, 0, 5, TimeUnit.SECONDS);}
}
優點
- 靈活性高:可以自定義線程池大小和任務執行策略。
- 獨立性強:不依賴于 Spring 框架,適合非 Spring 環境。
缺點
- 功能有限:不支持復雜的時間調度策略,如 Cron 表達式。
3. 使用 Quartz 框架
Quartz 是一個功能強大的任務調度框架,支持復雜的調度任務,例如動態任務配置和分布式任務調度。
示例代碼
依賴:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
任務類:
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;public class MyJob implements Job {@Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {System.out.println("Quartz 任務執行:" + System.currentTimeMillis());}
}
配置類:
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class QuartzConfig {@Beanpublic JobDetail jobDetail() {return JobBuilder.newJob(MyJob.class).withIdentity("myJob").storeDurably().build();}@Beanpublic Trigger jobTrigger(JobDetail jobDetail) {return TriggerBuilder.newTrigger().forJob(jobDetail).withIdentity("myTrigger").withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever()).build();}
}
優點
- 功能強大:支持復雜的調度策略,如動態任務配置和分布式任務調度。
- 高可靠性:支持任務持久化和恢復。
缺點
- 配置復雜:需要額外的配置和依賴。
- 學習曲線:相比
@Scheduled
,Quartz 的學習成本較高。
4. 使用 SchedulingConfigurer
接口
SchedulingConfigurer
是 Spring 提供的一個接口,允許動態配置定時任務,例如從數據庫中讀取任務配置。
示例代碼
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.Date;@Configuration
public class DynamicSchedulingConfig implements SchedulingConfigurer {@Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegistrar) {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(10);executor.initialize();taskRegistrar.setTaskExecutor(executor);taskRegistrar.addTriggerTask(() -> System.out.println("動態任務執行:" + new Date()),new Trigger() {@Overridepublic Date nextExecutionTime(TriggerContext triggerContext) {return new CronTrigger("0/5 * * * * ?").nextExecutionTime(triggerContext);}});}
}
優點
- 動態配置:支持從外部動態加載任務配置。
- 靈活性高:可以結合數據庫或其他存儲實現動態任務管理。
缺點
- 復雜度高:實現動態任務配置需要額外的開發工作。
5. 使用 TaskScheduler
接口
TaskScheduler
是 Spring 提供的一個接口,支持動態任務調度,適合需要動態調整任務執行頻率的場景。
示例代碼
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.Date;@Configuration
@EnableScheduling
public class TaskSchedulerConfig implements SchedulingConfigurer {@Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegistrar) {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(10);executor.initialize();taskRegistrar.setTaskExecutor(executor);taskRegistrar.addFixedRateTask(() -> System.out.println("固定頻率任務執行:" + new Date()), 5000);}
}
優點
- 動態調度:支持動態調整任務執行頻率。
- 簡單易用:與 Spring 容器無縫集成。
缺點
- 功能有限:不支持復雜的時間調度策略。
6. 使用 Redis 實現分布式定時任務
Redis 是一個高性能的鍵值存儲系統,可以利用其特性實現簡單的分布式定時任務。
示例代碼
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;@Component
public class RedisDistributedTask {private final RedisTemplate<String, String> redisTemplate;public RedisDistributedTask(RedisTemplate<String, String> redisTemplate) {this.redisTemplate = redisTemplate;}@Scheduled(fixedRate = 5000)public void executeTask() {String lockKey = "distributedTaskLock";String lockValue = String.valueOf(System.currentTimeMillis());Boolean lock = redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 5, TimeUnit.SECONDS);if (lock != null && lock) {System.out.println("分布式任務執行:" + new Date());}}
}
優點
- 分布式支持:可以實現簡單的分布式任務調度。
- 簡單易用:基于 Redis 的特性,實現簡單。
缺點
- 功能有限:不支持復雜的調度策略。
7. 使用 XXL-JOB 或 Elastic-Job
XXL-JOB 和 Elastic-Job 是輕量級的分布式任務調度平臺,支持動態任務管理和高可用性。
示例代碼(XXL-JOB)
依賴:
<dependency><groupId>com.xuxueli</groupId><artifactId>xxl-job-core</artifactId><version>3.1.2</version>
</dependency>
任務類:
import com.xxl.job.core.handler.annotation.XxlJob;
import org.springframework.stereotype.Component;@Component
public class XxlJobExample {@XxlJob("myJobHandler")public void myJobHandler() {System.out.println("XXL-JOB 任務執行:" + System.currentTimeMillis());}
}
配置類(XXL-JOB)
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class XxlJobConfig {@Beanpublic XxlJobSpringExecutor xxlJobExecutor() {XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();xxlJobSpringExecutor.setAdminAddresses("http://127.0.0.1:8080/xxl-job-admin");xxlJobSpringExecutor.setAppname("xxl-job-executor-sample");xxlJobSpringExecutor.setIp("127.0.0.1");xxlJobSpringExecutor.setPort(9999);return xxlJobSpringExecutor;}
}
優點
- 功能強大:支持動態任務管理、分布式任務調度、任務監控等功能。
- 高可用性:支持任務的容錯和恢復機制。
- 易于集成:與 Spring Boot 集成簡單,配置方便。
缺點
- 學習成本:需要額外學習 XXL-JOB 或 Elastic-Job 的使用方式。
- 依賴外部系統:需要部署額外的調度中心(如 XXL-JOB 的管理平臺)。
總結
在 Spring Boot 中,有多種方式可以實現定時任務,每種方式都有其適用場景和優缺點:
實現方式 | 優點 | 缺點 | 適用場景 |
---|---|---|---|
@Scheduled 注解 | 簡單易用,與 Spring 集成度高 | 不支持分布式任務 | 單節點應用,簡單任務調度 |
ScheduledExecutorService | 靈活性高,適合復雜任務調度 | 不支持復雜的時間調度策略 | 需要自定義線程池的任務調度 |
Quartz 框架 | 功能強大,支持復雜調度策略和分布式任務 | 配置復雜,學習成本高 | 需要復雜調度策略的應用 |
SchedulingConfigurer 接口 | 支持動態任務配置 | 實現復雜,需要額外開發工作 | 動態任務配置需求 |
TaskScheduler 接口 | 動態調度,與 Spring 集成度高 | 功能有限,不支持復雜調度策略 | 動態調整任務執行頻率的場景 |
Redis 分布式任務 | 支持分布式任務調度,實現簡單 | 功能有限,不支持復雜調度策略 | 分布式任務調度,簡單場景 |
XXL-JOB / Elastic-Job | 功能強大,支持動態任務管理和高可用性 | 需要額外部署調度中心,學習成本高 | 分布式任務調度,復雜場景 |
選擇合適的定時任務實現方式
選擇哪種定時任務實現方式取決于你的具體需求:
- 簡單任務調度:如果任務邏輯簡單,且僅在單個節點上運行,推薦使用
@Scheduled
注解。 - 復雜任務調度:如果需要支持復雜的時間調度策略(如 Cron 表達式),或者需要分布式任務調度,可以考慮使用 Quartz 框架。
- 動態任務配置:如果任務配置需要動態加載(如從數據庫中讀取),可以使用
SchedulingConfigurer
接口。 - 分布式任務調度:如果需要在多個節點上運行任務,且任務調度需要高可用性,推薦使用 XXL-JOB 或 Elastic-Job。
- 輕量級任務調度:如果需要快速實現簡單的分布式任務調度,可以考慮使用 Redis。
示例項目結構
以下是一個簡單的 Spring Boot 項目結構,展示了如何集成 @Scheduled
和 Redis 分布式任務:
my-spring-boot-project/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ ├── com.example.demo/
│ │ │ │ ├── application/
│ │ │ │ │ ├── DemoApplication.java
│ │ │ │ ├── config/
│ │ │ │ │ ├── SchedulingConfig.java
│ │ │ │ │ ├── RedisConfig.java
│ │ │ │ ├── service/
│ │ │ │ │ ├── ScheduledTask.java
│ │ │ │ │ ├── RedisDistributedTask.java
│ │ │ │ ├── model/
│ │ │ │ ├── controller/
│ │ │ │ ├── repository/
│ │ │ │ ├── util/
│ │ │ ├── resources/
│ │ │ │ ├── application.properties
│ │ │ │ ├── static/
│ │ │ │ ├── templates/
│ │ ├── test/
│ │ │ ├── java/
│ │ │ │ ├── com.example.demo/
│ │ │ │ │ ├── DemoApplicationTests.java
│ │ │ ├── resources/
│ ├── pom.xml
示例代碼完整版
DemoApplication.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}
SchedulingConfig.java
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;@Configuration
@EnableScheduling
public class SchedulingConfig {// 啟用定時任務支持
}
ScheduledTask.java
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;@Component
public class ScheduledTask {// 固定頻率:每5秒執行一次任務@Scheduled(fixedRate = 5000)public void executeTask() {System.out.println("【@Scheduled 任務】執行時間:" + LocalDateTime.now());}// Cron 表達式:每天中午12點執行一次任務@Scheduled(cron = "0 0 12 * * ?")public void executeCronTask() {System.out.println("【Cron 任務】執行時間:" + LocalDateTime.now());}
}
RedisConfig.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);// 設置 Key 的序列化器template.setKeySerializer(new StringRedisSerializer());template.setHashKeySerializer(new StringRedisSerializer());// 設置 Value 的序列化器template.setValueSerializer(new GenericJackson2JsonRedisSerializer());template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());template.afterPropertiesSet();return template;}
}
RedisDistributedTask.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;import java.util.Date;@Component
public class RedisDistributedTask {private final RedisTemplate<String, String> redisTemplate;@Autowiredpublic RedisDistributedTask(RedisTemplate<String, String> redisTemplate) {this.redisTemplate = redisTemplate;}@Scheduled(fixedRate = 5000)public void executeTask() {String lockKey = "distributedTaskLock";String lockValue = String.valueOf(System.currentTimeMillis());Boolean lock = redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 5, TimeUnit.SECONDS);if (lock != null && lock) {System.out.println("分布式任務執行:" + new Date());}}
}
application.properties
# Redis 配置
spring.data.redis.host=localhost
spring.data.redis.port=6379
spring.data.redis.password=
結語
通過本文的介紹,你應該對 Spring Boot 中的定時任務實現方式有了更全面的了解。無論是簡單的單節點任務,還是復雜的分布式任務,Spring Boot 都提供了靈活的解決方案。希望這些示例代碼能幫助你快速實現定時任務的需求。
如果你有任何問題或建議,歡迎在評論區留言。
如果對你有幫助,點贊👍、收藏💖、關注🔔是我更新的動力!👋🌟🚀