如何在springboot中利用Quartz實(shí)現(xiàn)一個(gè)定時(shí)任務(wù)功能

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

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

一、新建一個(gè)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對(duì)schedule的支持 --> 
            <groupId>org.springframework</groupId> 
            <artifactId>spring-context-support</artifactId> 
    </dependency> 

二、配置文件application.properties

# 服務(wù)器端口號(hào)  
server.port=7902 
# 是否生成ddl語句  
spring.jpa.generate-ddl=false  
# 是否打印sql語句  
spring.jpa.show-sql=true  
# 自動(dòng)生成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方法…… 
} 

四、任務(wù)類

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

六、定時(shí)查庫,并更新任務(wù)

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è)置定時(shí)任務(wù) 
  public void scheduleUpdateCronTrigger() throws SchedulerException { 
    CronTrigger trigger = (CronTrigger) scheduler.getTrigger(cronTrigger.getKey()); 
    String currentCron = trigger.getCronExpression();// 當(dāng)前Trigger使用的 
    String searchCron = repository.findOne(1L).getCron();// 從數(shù)據(jù)庫查詢出來的 
    System.out.println(currentCron); 
    System.out.println(searchCron); 
    if (currentCron.equals(searchCron)) { 
      // 如果當(dāng)前使用的cron表達(dá)式和從數(shù)據(jù)庫中查詢出來的cron表達(dá)式一致,則不刷新任務(wù) 
    } else { 
      // 表達(dá)式調(diào)度構(gòu)建器 
      CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(searchCron); 
      // 按新的cronExpression表達(dá)式重新構(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í)行一次定時(shí)任務(wù)

2、schema.sql

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

六、運(yùn)行測試

測試結(jié)果如下:(Quartz默認(rèn)的線程池大小為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!!! 

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

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

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

網(wǎng)頁名稱:如何在springboot中利用Quartz實(shí)現(xiàn)一個(gè)定時(shí)任務(wù)功能
標(biāo)題來源:http://muchs.cn/article10/iidsgo.html

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

廣告

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

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