如何在springboot中利用Quartz實現(xiàn)一個定時任務功能

如何在springboot中利用Quartz實現(xiàn)一個定時任務功能?相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。

成都創(chuàng)新互聯(lián)公司專注于江干企業(yè)網(wǎng)站建設(shè),響應式網(wǎng)站開發(fā),成都商城網(wǎng)站開發(fā)。江干網(wǎng)站建設(shè)公司,為江干等地區(qū)提供建站服務。全流程按需求定制制作,專業(yè)設(shè)計,全程項目跟蹤,成都創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務

一、新建一個springboot工程,并添加依賴

<dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-data-jpa</artifactId> 
    </dependency> 
 
    <dependency><!-- 為了方便測試,此處使用了內(nèi)存數(shù)據(jù)庫 --> 
      <groupId>com.h3database</groupId> 
      <artifactId>h3</artifactId> 
      <scope>runtime</scope> 
    </dependency> 
    <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-test</artifactId> 
      <scope>test</scope> 
    </dependency> 
     
    <dependency> 
      <groupId>org.quartz-scheduler</groupId> 
      <artifactId>quartz</artifactId> 
      <version>2.2.1</version> 
      <exclusions> 
        <exclusion> 
          <artifactId>slf4j-api</artifactId> 
          <groupId>org.slf4j</groupId> 
        </exclusion> 
      </exclusions> 
    </dependency> 
    <dependency><!-- 該依賴必加,里面有sping對schedule的支持 --> 
            <groupId>org.springframework</groupId> 
            <artifactId>spring-context-support</artifactId> 
    </dependency> 

二、配置文件application.properties

# 服務器端口號  
server.port=7902 
# 是否生成ddl語句  
spring.jpa.generate-ddl=false  
# 是否打印sql語句  
spring.jpa.show-sql=true  
# 自動生成ddl,由于指定了具體的ddl,此處設(shè)置為none  
spring.jpa.hibernate.ddl-auto=none  
# 使用H2數(shù)據(jù)庫  
spring.datasource.platform=h3  
# 指定生成數(shù)據(jù)庫的schema文件位置  
spring.datasource.schema=classpath:schema.sql  
# 指定插入數(shù)據(jù)庫語句的腳本位置  
spring.datasource.data=classpath:data.sql  
# 配置日志打印信息  
logging.level.root=INFO  
logging.level.org.hibernate=INFO  
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE  
logging.level.org.hibernate.type.descriptor.sql.BasicExtractor=TRACE  
logging.level.com.itmuch=DEBUG  

三、Entity類

package com.chhliu.springboot.quartz.entity; 
 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
 
@Entity 
public class Config { 
  @Id 
   @GeneratedValue(strategy = GenerationType.AUTO) 
   private Long id; 
 
   @Column 
   private String cron; 
 
  /** 
   * @return the id 
   */ 
  public Long getId() { 
    return id; 
  } 
    ……此處省略getter和setter方法…… 
} 

四、任務類

package com.chhliu.springboot.quartz.entity; 
 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.scheduling.annotation.EnableScheduling; 
import org.springframework.stereotype.Component; 
 
@Configuration 
@Component // 此注解必加 
@EnableScheduling // 此注解必加 
public class ScheduleTask { 
  private static final Logger LOGGER = LoggerFactory.getLogger(ScheduleTask.class); 
  public void sayHello(){ 
    LOGGER.info("Hello world, i'm the king of the world!!!"); 
  } 
} 

五、Quartz配置類

由于springboot追求零xml配置,所以下面會以配置Bean的方式來實現(xiàn)

package com.chhliu.springboot.quartz.entity; 
 
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; 
 
@Configuration 
public class QuartzConfigration { 
  /** 
   * attention: 
   * Details:配置定時任務 
   */ 
  @Bean(name = "jobDetail") 
  public MethodInvokingJobDetailFactoryBean detailFactoryBean(ScheduleTask task) {// ScheduleTask為需要執(zhí)行的任務 
    MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean(); 
    /* 
     * 是否并發(fā)執(zhí)行 
     * 例如每5s執(zhí)行一次任務,但是當前任務還沒有執(zhí)行完,就已經(jīng)過了5s了, 
     * 如果此處為true,則下一個任務會執(zhí)行,如果此處為false,則下一個任務會等待上一個任務執(zhí)行完后,再開始執(zhí)行 
     */ 
    jobDetail.setConcurrent(false); 
     
    jobDetail.setName("srd-chhliu");// 設(shè)置任務的名字 
    jobDetail.setGroup("srd");// 設(shè)置任務的分組,這些屬性都可以存儲在數(shù)據(jù)庫中,在多任務的時候使用 
     
    /* 
     * 為需要執(zhí)行的實體類對應的對象 
     */ 
    jobDetail.setTargetObject(task); 
     
    /* 
     * sayHello為需要執(zhí)行的方法 
     * 通過這幾個配置,告訴JobDetailFactoryBean我們需要執(zhí)行定時執(zhí)行ScheduleTask類中的sayHello方法 
     */ 
    jobDetail.setTargetMethod("sayHello"); 
    return jobDetail; 
  } 
   
  /** 
   * attention: 
   * Details:配置定時任務的觸發(fā)器,也就是什么時候觸發(fā)執(zhí)行定時任務 
   */ 
  @Bean(name = "jobTrigger") 
  public CronTriggerFactoryBean cronJobTrigger(MethodInvokingJobDetailFactoryBean jobDetail) { 
    CronTriggerFactoryBean tigger = new CronTriggerFactoryBean(); 
    tigger.setJobDetail(jobDetail.getObject()); 
    tigger.setCronExpression("0 30 20 * * &#63;");// 初始時的cron表達式 
    tigger.setName("srd-chhliu");// trigger的name 
    return tigger; 
 
  } 
 
  /** 
   * attention: 
   * Details:定義quartz調(diào)度工廠 
   */ 
  @Bean(name = "scheduler") 
  public SchedulerFactoryBean schedulerFactory(Trigger cronJobTrigger) { 
    SchedulerFactoryBean bean = new SchedulerFactoryBean(); 
    // 用于quartz集群,QuartzScheduler 啟動時更新己存在的Job 
    bean.setOverwriteExistingJobs(true); 
    // 延時啟動,應用啟動1秒后 
    bean.setStartupDelay(1); 
    // 注冊觸發(fā)器 
    bean.setTriggers(cronJobTrigger); 
    return bean; 
  } 
} 

六、定時查庫,并更新任務

package com.chhliu.springboot.quartz.entity; 
 
import javax.annotation.Resource; 
 
import org.quartz.CronScheduleBuilder; 
import org.quartz.CronTrigger; 
import org.quartz.JobDetail; 
import org.quartz.Scheduler; 
import org.quartz.SchedulerException; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.scheduling.annotation.EnableScheduling; 
import org.springframework.scheduling.annotation.Scheduled; 
import org.springframework.stereotype.Component; 
 
import com.chhliu.springboot.quartz.repository.ConfigRepository; 
 
@Configuration 
@EnableScheduling 
@Component 
public class ScheduleRefreshDatabase { 
  @Autowired 
  private ConfigRepository repository; 
 
  @Resource(name = "jobDetail") 
  private JobDetail jobDetail; 
 
  @Resource(name = "jobTrigger") 
  private CronTrigger cronTrigger; 
 
  @Resource(name = "scheduler") 
  private Scheduler scheduler; 
 
  @Scheduled(fixedRate = 5000) // 每隔5s查庫,并根據(jù)查詢結(jié)果決定是否重新設(shè)置定時任務 
  public void scheduleUpdateCronTrigger() throws SchedulerException { 
    CronTrigger trigger = (CronTrigger) scheduler.getTrigger(cronTrigger.getKey()); 
    String currentCron = trigger.getCronExpression();// 當前Trigger使用的 
    String searchCron = repository.findOne(1L).getCron();// 從數(shù)據(jù)庫查詢出來的 
    System.out.println(currentCron); 
    System.out.println(searchCron); 
    if (currentCron.equals(searchCron)) { 
      // 如果當前使用的cron表達式和從數(shù)據(jù)庫中查詢出來的cron表達式一致,則不刷新任務 
    } else { 
      // 表達式調(diào)度構(gòu)建器 
      CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(searchCron); 
      // 按新的cronExpression表達式重新構(gòu)建trigger 
      trigger = (CronTrigger) scheduler.getTrigger(cronTrigger.getKey()); 
      trigger = trigger.getTriggerBuilder().withIdentity(cronTrigger.getKey()) 
          .withSchedule(scheduleBuilder).build(); 
      // 按新的trigger重新設(shè)置job執(zhí)行 
      scheduler.rescheduleJob(cronTrigger.getKey(), trigger); 
      currentCron = searchCron; 
    } 
  } 
} 

六、相關(guān)腳本

1、data.sql

insert into config(id,cron) values(1,'0 0/2 * * * &#63;'); # 每2分鐘執(zhí)行一次定時任務

2、schema.sql

drop table config if exists; 
create table config( 
  id bigint generated by default as identity, 
  cron varchar(40), 
  primary key(id) 
); 

六、運行測試

測試結(jié)果如下:(Quartz默認的線程池大小為10)

0 30 20 * * &#63; 
0 0/2 * * * &#63; 
2017-03-08 18:02:00.025 INFO 5328 --- [eduler_Worker-1] c.c.s.quartz.entity.ScheduleTask     : Hello world, i'm the king of the world!!! 
2017-03-08 18:04:00.003 INFO 5328 --- [eduler_Worker-2] c.c.s.quartz.entity.ScheduleTask     : Hello world, i'm the king of the world!!! 
2017-03-08 18:06:00.002 INFO 5328 --- [eduler_Worker-3] c.c.s.quartz.entity.ScheduleTask     : Hello world, i'm the king of the world!!! 
2017-03-08 18:08:00.002 INFO 5328 --- [eduler_Worker-4] c.c.s.quartz.entity.ScheduleTask     : Hello world, i'm the king of the world!!! 

從上面的日志打印時間來看,我們實現(xiàn)了動態(tài)配置,最初的時候,任務是每天20:30執(zhí)行,后面通過動態(tài)刷新變成了每隔2分鐘執(zhí)行一次。

雖然上面的解決方案沒有使用Quartz推薦的方式完美,但基本上可以滿足我們的需求,當然也可以采用觸發(fā)事件的方式來實現(xiàn),例如當前端修改定時任務的觸發(fā)時間時,異步的向后臺發(fā)送通知,后臺收到通知后,然后再更新程序,也可以實現(xiàn)動態(tài)的定時任務刷新

看完上述內(nèi)容,你們掌握如何在springboot中利用Quartz實現(xiàn)一個定時任務功能的方法了嗎?如果還想學到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!

網(wǎng)頁名稱:如何在springboot中利用Quartz實現(xiàn)一個定時任務功能
標題來源:http://bm7419.com/article10/iidsgo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供軟件開發(fā)、小程序開發(fā)、營銷型網(wǎng)站建設(shè)云服務器、Google自適應網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)