SpringBoot2.0接入quartz

SpringBoot的出現給我們帶來了很多方便,基本上可以基於註解解決掉所有的配置,但是正因爲它的迅速迭代,相關文檔跟不上,所以有很多坑需要我們去踩,下面將給大家介紹Spinigboot2.0版本對接Quartz任務。

首先我們來了解一下spring常用的任務框架:

1.Spring Schedule

2.Quartz

Spring Schedule是Spring自帶的任務框架,簡單說他就是一個簡化版本的Quartz,但是正因爲它有個 與Springboot的集成非常簡單,

@SpringBootApplication
@ComponentScan(basePackages = {"com.hik.tool","com.hik.dealexcel"})
@EnableCaching
@EnableScheduling
public class ProjectApplication extends SpringBootServletInitializer {

   public static void main(String[] args) {
      SpringApplication.run(ProjectApplication.class, args);
   }
}

只需要在springboot的啓動類上加上

@EnableScheduling

然後寫一個任務執行類,其中cron表示任務執行的時間表示式

@Component
public class ScheduledTask {
    @Scheduled(cron = "0 11 15 * * *")
    public void reportCurrentTimeCron() throws InterruptedException {
        System.out.println("任務執行!");
    }
}

這樣就可以完成一個簡單的定時任務,不需要依賴其他包,不需要任何配置,是不是很簡單,但是這個定時其有個問題,據一位大佬的博客說,一旦某個任務在執行過程中拋出異常,則整個定時器生命週期就結束,以後永遠不會再執行定時器任務,但是Quartz就不一樣,上次任務出錯不會影響下次任務的執行,所以我還是選擇了quartz,那麼我們開始進入今天正題。

    springboot在2.0版本之前,還沒有出quartz的starter,所以集成起來相對麻煩點,需要引入多個jar包,然後做相關配置,但是2.0後,只需要引入starter就可以了,以下就是相關步驟(quartz的用法分爲內存版本和數據庫版本,這裏主要講解內存版本,springboot官方文檔裏面有講到直接在application配置文件中如何切換成數據庫版本,已經數據庫相關信息的配置,總體比之前使用非starter簡單很多):

1.引入starter

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

2.編寫任務類繼承QuartzJobBean類,實現excuteInternal方法,方法中寫自己需要定時執行的

public class UploadTask extends QuartzJobBean {
    @Resource
    private TencentYunService tencentYunService;
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("任務開始");
        try {
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("任務結束");
    }
}

3.創建一個配置類,分別制定具體任務類和觸發的規則,我們可以和之前的xml配置對應起來看,

uploadTaskDetail指定了具體需要執行的類,只不過具體的方法就是我們需要實現的excuteInternal
uploadTaskTrigger指定了觸發的規則

@Configuration
public class QuartzConfig {
    @Bean
    public JobDetail uploadTaskDetail() {
        return JobBuilder.newJob(UploadTask.class).withIdentity("uploadTask").storeDurably().build();
    }

    @Bean
    public Trigger uploadTaskTrigger() {
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("*/5 * * * * ?");
        return TriggerBuilder.newTrigger().forJob(uploadTaskDetail())
                .withIdentity("uploadTask")
                .withSchedule(scheduleBuilder)
                .build();
    }
}
<bean id="cleanupStatusTaskMethod" class= "org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
   <property name="targetObject" ref="cleanupStatusTask"/>
   <property name="targetMethod" value="cleanupStatus"/>
   <property name="concurrent" value="false"/>
</bean>

<bean id="cleanupStatusTrigger" class= "org.springframework.scheduling.quartz.SimpleTriggerBean">
   <property name="jobDetail" ref="cleanupStatusTaskMethod"/>
   <property name="startDelay" value="300000"/>
   <property name="repeatInterval" value="60000"/>
</bean>

如此一個Quartz集成Springboot就完成了,是不是很簡單,在集成的過程中遇到了一個坑,我們看到在xml配置時我們配置了concurrent爲false,這個意思是是否併發執行,系統默認爲true,即第一個任務還未執行完整,第二個任務如果到了執行時間,則會立馬開啓新線程執行任務,這樣如果我們是從數據庫讀取信息,兩次重複讀取可能出現重複執行任務的情況,所以我們需要將這個值設置爲false,這樣第二個任務會往後推遲,只有在第一個任務執行完成後纔會執行第二個任務。

我們只需要在任務類上加入disallowconcurrentExeution就可以了

@DisallowConcurrentExecution
public class UploadTask extends QuartzJobBean {
    @Resource
    private TencentYunService tencentYunService;
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("任務開始");
        try {
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("任務結束");
    }
}

我們可以看一下效果,我們規定了任務每5s執行一次,而線程等待6秒,如果是併發執行會導致任務開始和任務結束雜亂出現


但是如果我們加上如上註解,那麼只會成對先後出現開始和結束


這裏只是簡單講解了一下quartz和springboot的集成方法,還有很多內容我們可以去探索,例如job間參數傳遞,可以使用上述job的biulderd的usingJobData等,以上就是全部內容,如果有不當的地方請幫忙指正,謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章