首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring 整合 Quartz 進階:TriggerListener 實現作業鏈式執行

     編輯:Java 相關知識

前言:為什麼需要作業鏈?

實際業務常有順序依賴:如資料遷移需先導入主檔(被參考資料),再導入明細檔(關聯資料)。Quartz TriggerListener 可在觸發器完成時自動排程下一個作業,實現聲明式作業鏈。

核心實作:NextJobTriggerListener

public class NextJobTriggerListener extends TriggerListenerSupport {
  private Logger logger = Logger.getLogger(getClass());
  private String name;
  private SimpleTriggerBean nextTrigger; // 要鏈接的下一個觸發器

  public String getName() { return name; }
  public void setName(String name) { this.name = name; }
  public void setNextTrigger(SimpleTriggerBean nextTrigger) { this.nextTrigger = nextTrigger; }

  @Override
  public void triggerComplete(Trigger trigger, JobExecutionContext context, int code) {
    try {
      Scheduler scheduler = context.getScheduler();
      JobDetail nextJob = nextTrigger.getJobDetail();
      Trigger oldTrigger = scheduler.getTrigger(nextTrigger.getName(), nextTrigger.getGroup());
      JobDetail oldJob = scheduler.getJobDetail(nextJob.getName(), nextJob.getGroup());

      if (oldJob == null && oldTrigger == null) { // 尚未註冊
        logger.debug("Scheduling next job: " + code);
        scheduler.scheduleJob(nextJob, nextTrigger);
      } else {
        logger.debug("Job/Trigger already exists, skip scheduling");
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    super.triggerComplete(trigger, context, code);
  }
}

關鍵邏輯:檢查目標 Job/Trigger 是否已存在於 Scheduler,避免重複註冊導致異常。

Spring 配置:聲明式作業鏈

<!-- 主作業 -->
<bean id="mainJob" class="org.springframework.scheduling.quartz.JobDetailBean">
  <property name="jobClass" value="jobs.MainJob"/>
</bean>

<!-- 主作業觸發器,掛載 Listener -->
<bean id="mainTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
  <property name="jobDetail" ref="mainJob"/>
  <property name="startDelay" value="6000"/>
  <property name="repeatCount" value="0"/>
  <property name="repeatInterval" value="3600000"/>
  <property name="triggerListenerNames">
    <list><value>mainTriggerListener</value></list>
  </property>
</bean>

<!-- 監聽器,指定下一個觸發器 -->
<bean id="mainTriggerListener" class="listeners.NextJobTriggerListener">
  <property name="name" value="mainTriggerListener"/>
  <property name="nextTrigger" ref="secondTrigger"/>
</bean>

<!-- 後續作業 -->
<bean id="secondJob" class="org.springframework.scheduling.quartz.JobDetailBean">
  <property name="jobClass" value="jobs.SecondJob"/>
</bean>

<!-- 後續觸發器(不立即排程,由 Listener 動態添加) -->
<bean id="secondTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
  <property name="jobDetail" ref="secondJob"/>
  <property name="startDelay" value="6000"/>
  <property name="repeatCount" value="0"/>
  <property name="repeatInterval" value="6000"/>
</bean>

<!-- Scheduler 工廠,註冊主觸發器與監聽器 -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
  <property name="triggers">
    <list><ref bean="mainTrigger"/></list>
  </property>
  <property name="triggerListeners">
    <list><ref bean="mainTriggerListener"/></list>
  </property>
  <!-- quartzProperties 同前例 -->
</bean>

執行流程與日誌輸出

DEBUG [MainJob.executeInternal] Just say hi.
DEBUG [NextJobTriggerListener.triggerComplete] inside scheduleJob.3
DEBUG [SecondJob.executeInternal] I'm the second job.
DEBUG [NextJobTriggerListener.triggerComplete] oldJob==null:false
DEBUG [NextJobTriggerListener.triggerComplete] oldTrigger==null:false
  1. 應用啟動,mainTrigger 註冊到 Scheduler
  2. 6 秒後 MainJob 執行
  3. mainTrigger 完成,TriggerListener 檢測並動態排程 secondTrigger
  4. 6 秒後 SecondJob 執行
  5. 後續 mainTrigger 再次觸發時,檢測到 SecondJob 已存在,跳過排程

設計要點與擴充建議

  • 冪等性:Listener 檢查既有 Job/Trigger 避免重複排程
  • 錯誤處理:triggerComplete 的 code 參數指示完成狀態(正常/錯誤/否決),可據此決定是否啟動下一個作業
  • 多層鏈:SecondJob 的 Trigger 同樣可掛載 Listener 鏈接第三個作業
  • 參數傳遞:透過 JobDataMap 在作業間傳遞業務資料
  • 替代方案:Quartz 2.1+ 支援 JobChaining 內建功能,Spring 4.1+ 亦有 JobBuilder 流式 API

結語

透過 TriggerListener 實現作業鏈,保持配置聲明式、邏輯集中於 Listener、避免硬編碼排程依賴。適合資料遷移、批次處理流水線等有嚴格執行順序的業務場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved