SpringBoot+Quartz實現多個定時任務
通過Timer和Spring的scheduler實現定時任務可能會出現一旦定時任務中斷後續的定時任務無法正常執行的問題,Quartz能夠很好的解決這一問題。
專案使用Maven管理,因此在使用之前需要在pom檔案中新增依賴,如下:
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.0.6.RELEASE</version>
</dependency>
不要忘記spring-context-support。
緊接著需要新增Quartz配置類,我把程式碼貼上了下來,如下:
其中需要import的部分內容:
import org.quartz.JobDetail;
import org.quartz.Trigger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;
-----------------------------------------------下邊是配置類的實現-------------------------------------------------------
@Configuration
public class QuartzConfig<CornTriggerFactoryBean> {
//指定了觸發規則
@Bean(name = "firstTrigger")
public CornTriggerFactoryBean uploadTaskTrigger(JobDetail firstJobDetail){
CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
trigger.setJobDetail(firstJobDetail);
trigger.setCronExpression("0 10 10 * * ?");//每天兩點上傳資料
return (CornTriggerFactoryBean) trigger;
}
@Bean(name = "firstJobDetail")
public MethodInvokingJobDetailFactoryBean uploadTaskDetail(){//指定了具體需要執行的類 具體的方法就是我們需要實現的excuteInternal
UploadTask uploadTask = (UploadTask)SpringUtil.getBean(UploadTask.class);
MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
// 是否併發執行
jobDetail.setConcurrent(false);
// 為需要執行的實體類對應的物件
jobDetail.setTargetObject(uploadTask);
// 需要執行的方法
jobDetail.setTargetMethod("task");
return jobDetail;
//return JobBuilder.newJob(UploadTask.class).withIdentity("uploadTask").storeDurably().build();
}
//第二個定時任務的觸發規則
@Bean(name = "secondTrigger")
public SimpleTriggerFactoryBean submitFailDataTaskTrigger(JobDetail secondJobDetail){
SimpleTriggerFactoryBean trigger = new SimpleTriggerFactoryBean();
trigger.setJobDetail(secondJobDetail);
// 設定任務啟動延遲
trigger.setStartDelay(0);
// 每5分鐘執行一次
trigger.setRepeatInterval(300000);//300000
return trigger;
}
//第二個定時任務
@Bean(name = "secondJobDetail")
public MethodInvokingJobDetailFactoryBean SubmitFailedDataTaskDetail(){
SubmitFailedDataTask submitFailedDataTask = (SubmitFailedDataTask)SpringUtil.getBean(SubmitFailedDataTask.class);
MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
// 是否併發執行
jobDetail.setConcurrent(false);
// 為需要執行的實體類對應的物件
jobDetail.setTargetObject(submitFailedDataTask);
// 需要執行的方法
jobDetail.setTargetMethod("task");
return jobDetail;
//return JobBuilder.newJob(SubmitFailedDataTask.class).withIdentity("submitFailedDataTask").storeDurably().build();
}
// 配置Scheduler
@Bean(name = "scheduler")
public SchedulerFactoryBean schedulerFactory(Trigger firstTrigger, Trigger secondTrigger) {
SchedulerFactoryBean bean = new SchedulerFactoryBean();
// 延時啟動,應用啟動1秒後
bean.setStartupDelay(1);
// 註冊觸發器
bean.setTriggers(firstTrigger, secondTrigger);
return bean;
}
}
其中,在配置Scheduler中註冊兩個觸發器,然後專案啟動1秒之後就會啟動定時任務輪訓,到了程式碼設定的corn表示式滿足時,就會觸發相應的定時任務。
需要注意的是上邊拿到要執行的兩個Task的時候定義了Util工具類,也就是SpringUtil工具類,程式碼如下:
其中需要import的內容如下:
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
實現類方法如下:
@Component
public class SpringUtil implements ApplicationContextAware{
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringUtil.applicationContext == null) {
SpringUtil.applicationContext = applicationContext;
}
}
//獲取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通過name獲取 Bean.
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
//通過class獲取Bean.
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
//通過name,以及Clazz返回指定的Bean
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
然後去實現UploadTask和SubmitFailedDataTask兩個定時任務就可以了
需要在任務實現類中實現task()方法
@DisallowConcurrentExecution
@EnableScheduling
@Component
public class UploadTask{
public void task(){ //task方法中實現主要邏輯就可以了。
}
}
最重要的是要在啟動類中新增@EnableScheduling註解。
當前還是有一些比較疑惑的地方,後續也會整理一下,將來用得到的時候會方便一些。