一、使用@Scheduled注解配置定時(shí)任務(wù)
SpringBoot提供了一種簡(jiǎn)單易用的定時(shí)任務(wù)實(shí)現(xiàn)方式,即使用@Scheduled注解。使用該注解可以方便地定義定時(shí)任務(wù),無(wú)需額外引入Quartz等第三方庫(kù)。
首先,在啟動(dòng)類(lèi)上添加@EnableScheduling注解,開(kāi)啟定時(shí)任務(wù)功能:
@SpringBootApplication
@EnableScheduling
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}然后,在需要定時(shí)執(zhí)行的方法上添加@Scheduled注解,配置定時(shí)策略。@Scheduled注解支持多種定時(shí)策略,常用的有:
fixedDelay:上一次任務(wù)執(zhí)行完成后,經(jīng)過(guò)指定的時(shí)間才開(kāi)始執(zhí)行下一次任務(wù)
fixedRate:固定頻率執(zhí)行任務(wù),不管上一次任務(wù)是否執(zhí)行完成
cron:支持Cron表達(dá)式,可以實(shí)現(xiàn)更加靈活的定時(shí)策略
示例代碼如下:
@Component
public class ScheduledTask {
@Scheduled(fixedDelay = 5000)
public void taskWithFixedDelay() {
// 執(zhí)行任務(wù)的代碼
}
@Scheduled(fixedRate = 10000)
public void taskWithFixedRate() {
// 執(zhí)行任務(wù)的代碼
}
@Scheduled(cron = "0 0 3 * * ?")
public void taskWithCron() {
// 執(zhí)行任務(wù)的代碼
}
}二、使用Quartz定時(shí)框架
除了使用SpringBoot自帶的@Scheduled注解,我們還可以使用Quartz定時(shí)框架來(lái)實(shí)現(xiàn)更加復(fù)雜的定時(shí)任務(wù)。Quartz是一個(gè)功能強(qiáng)大的定時(shí)任務(wù)框架,提供了豐富的配置選項(xiàng)和API,可以滿足更加復(fù)雜的定時(shí)需求。
要使用Quartz,首先需要在項(xiàng)目中添加相關(guān)依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>然后,創(chuàng)建一個(gè)Job類(lèi),實(shí)現(xiàn)Job接口,并在其中編寫(xiě)定時(shí)任務(wù)的具體邏輯:
@Slf4j
@PrimaryJob
public class DemoJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
// 執(zhí)行任務(wù)的代碼
log.info("Quartz Job executed!");
}
}接下來(lái),我們需要配置Quartz的相關(guān)參數(shù),如任務(wù)調(diào)度器、任務(wù)觸發(fā)器等??梢栽赼pplication.properties或application.yml文件中進(jìn)行配置:
spring.quartz.job-store-type=memory spring.quartz.scheduler-name=demoScheduler spring.quartz.properties.org.quartz.scheduler.instanceName=demoScheduler spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO spring.quartz.properties.org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool spring.quartz.properties.org.quartz.threadPool.threadCount=5
最后,創(chuàng)建一個(gè)Quartz任務(wù)調(diào)度器,并在其中注冊(cè)定時(shí)任務(wù):
@Configuration
public class QuartzConfiguration {
@Autowired
private JobDetail demoJobDetail;
@Autowired
private Trigger demoTrigger;
@Bean
public Scheduler scheduler(Trigger demoTrigger, JobDetail demoJobDetail) throws SchedulerException {
Scheduler scheduler = schedulerFactoryBean().getScheduler();
scheduler.scheduleJob(demoJobDetail, demoTrigger);
return scheduler;
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setJobFactory(springBeanJobFactory());
schedulerFactoryBean.setQuartzProperties(quartzProperties());
return schedulerFactoryBean;
}
@Bean
public SpringBeanJobFactory springBeanJobFactory() {
return new SpringBeanJobFactory();
}
@Bean
public Properties quartzProperties() {
Properties properties = new Properties();
properties.setProperty("org.quartz.scheduler.instanceName", "demoScheduler");
properties.setProperty("org.quartz.scheduler.instanceId", "AUTO");
properties.setProperty("org.quartz.jobStore.class", "org.quartz.simpl.RAMJobStore");
properties.setProperty("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
properties.setProperty("org.quartz.threadPool.threadCount", "5");
return properties;
}
}三、動(dòng)態(tài)添加和刪除定時(shí)任務(wù)
在某些場(chǎng)景下,我們可能需要?jiǎng)討B(tài)地添加或刪除定時(shí)任務(wù),而不是在啟動(dòng)時(shí)就完全確定。SpringBoot提供了相應(yīng)的API,可以幫助我們實(shí)現(xiàn)這一需求。
以Quartz為例,我們可以通過(guò)以下步驟動(dòng)態(tài)添加任務(wù):
1. 獲取Quartz的Scheduler實(shí)例
2. 創(chuàng)建JobDetail和Trigger對(duì)象
3. 使用Scheduler的scheduleJob()方法添加任務(wù)
示例代碼如下:
@Service
public class DynamicSchedulerService {
@Autowired
private Scheduler scheduler;
public void scheduleJob(String jobName, String jobGroup, String triggerName, String triggerGroup, JobDataMap jobDataMap) {
try {
JobDetail jobDetail = JobBuilder.newJob(DemoJob.class)
.withIdentity(jobName, jobGroup)
.usingJobData(jobDataMap)
.build();
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(triggerName, triggerGroup)
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(10)
.repeatForever())
.build();
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
// 處理異常
}
}
}刪除任務(wù)的過(guò)程也類(lèi)似,通過(guò)Scheduler的unscheduleJob()方法即可。
四、定時(shí)任務(wù)錯(cuò)誤處理
在實(shí)際應(yīng)用中,定時(shí)任務(wù)可能會(huì)由于各種原因而出現(xiàn)異常,比如網(wǎng)絡(luò)故障、數(shù)據(jù)庫(kù)連接失敗等。為了保證應(yīng)用的穩(wěn)定性,我們需要對(duì)定時(shí)任務(wù)的錯(cuò)誤進(jìn)行適當(dāng)?shù)奶幚怼?/p>
對(duì)于使用@Scheduled注解的定時(shí)任務(wù),可以通過(guò)try-catch語(yǔ)句捕獲異常,并在catch塊中進(jìn)行錯(cuò)誤處理:
@Scheduled(fixedDelay = 5000)
public void taskWithFixedDelay() {
try {
// 執(zhí)行任務(wù)的代碼
} catch (Exception e) {
// 處理異常
log.error("Task execution failed", e);
}
}對(duì)于使用Quartz的定時(shí)任務(wù),可以在Job實(shí)現(xiàn)類(lèi)中捕獲異常,并在execute()方法中進(jìn)行錯(cuò)誤處理:
@Slf4j
@PrimaryJob
public class DemoJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
try {
// 執(zhí)行任務(wù)的代碼
} catch (Exception e) {
// 處理異常
log.error("Job execution failed", e);
// 拋出JobExecutionException,通知Quartz調(diào)度器任務(wù)執(zhí)行失敗
throw new JobExecutionException(e);
}
}
}五、定時(shí)任務(wù)監(jiān)控與報(bào)警
在生產(chǎn)環(huán)境中,我們需要對(duì)定時(shí)任務(wù)的運(yùn)行情況進(jìn)行監(jiān)控,以便及時(shí)發(fā)現(xiàn)并處理異常情況。SpringBoot提供了actuator模塊,可以幫助我們實(shí)現(xiàn)定時(shí)任務(wù)的監(jiān)控。
首先,在項(xiàng)目中引入actuator依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>然后,在application.properties或application.yml文件中,配置需要暴露的監(jiān)控端點(diǎn):
management.endpoints.web.exposure.include=health,info,conditions,metrics,scheduledtasks
這樣,我們就可以通過(guò)/actuator/scheduledtasks端點(diǎn),查看當(dāng)前應(yīng)用