Quartz 排程器

Spring Boot 為使用 Quartz 排程器 提供了多種便利,包括 spring-boot-starter-quartz starter。如果 Quartz 可用,則會自動配置一個 Scheduler(透過 SchedulerFactoryBean 抽象)。

以下型別的 Bean 會被自動檢測並與 Scheduler 關聯起來:

預設情況下,使用記憶體中的 JobStore。但是,如果您的應用中存在 DataSource bean 並且相應地配置了 spring.quartz.job-store-type 屬性,則可以配置基於 JDBC 的儲存,如下例所示:

  • Properties

  • YAML

spring.quartz.job-store-type=jdbc
spring:
  quartz:
    job-store-type: "jdbc"

使用 JDBC 儲存時,可以在啟動時初始化 schema,如下例所示:

  • Properties

  • YAML

spring.quartz.jdbc.initialize-schema=always
spring:
  quartz:
    jdbc:
      initialize-schema: "always"
預設情況下,資料庫使用 Quartz 庫提供的標準指令碼進行檢測和初始化。這些指令碼會在每次重啟時刪除現有表格,從而刪除所有觸發器。要使用自定義指令碼,請設定 spring.quartz.jdbc.schema 屬性。一些標準指令碼(例如用於 SQL Server、Azure SQL 和 Sybase 的指令碼)無法直接使用,需要修改。在這種情況下,複製指令碼並按照指令碼中的註釋進行編輯,然後設定 spring.quartz.jdbc.schema 以使用您的自定義指令碼。

要讓 Quartz 使用一個不同於應用主要 DataSourceDataSource,請宣告一個 DataSource bean,並用 @QuartzDataSource 註解其 @Bean 方法。這樣做可以確保 Quartz 專用的 DataSourceSchedulerFactoryBean 和 schema 初始化所使用。類似地,要讓 Quartz 使用一個不同於應用主要 TransactionManagerTransactionManager,請宣告一個 TransactionManager bean,並用 @QuartzTransactionManager 註解其 @Bean 方法。

預設情況下,透過配置建立的作業不會覆蓋已從永續性作業儲存中讀取的已註冊作業。要啟用覆蓋現有作業定義,請設定 spring.quartz.overwrite-existing-jobs 屬性。

可以使用 spring.quartz 屬性和 SchedulerFactoryBeanCustomizer Bean 來自定義 Quartz 排程器配置,它們允許對 SchedulerFactoryBean 進行程式設計化自定義。可以使用 spring.quartz.properties.* 自定義高階 Quartz 配置屬性。

特別是,Executor Bean 不與排程器關聯,因為 Quartz 提供了透過 spring.quartz.properties 配置排程器的方法。如果您需要自定義任務執行器,請考慮實現 SchedulerFactoryBeanCustomizer

Job 可以定義 Setter 方法來注入資料對映屬性。常規 Bean 也可以以類似的方式注入,如下例所示:

  • Java

  • Kotlin

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import org.springframework.scheduling.quartz.QuartzJobBean;

public class MySampleJob extends QuartzJobBean {

	// fields ...

	private MyService myService;

	private String name;


	// Inject "MyService" bean
	public void setMyService(MyService myService) {
		this.myService = myService;
	}

	// Inject the "name" job data property
	public void setName(String name) {
		this.name = name;
	}

	@Override
	protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
		this.myService.someMethod(context.getFireTime(), this.name);
	}

}
import org.quartz.JobExecutionContext
import org.springframework.scheduling.quartz.QuartzJobBean

class MySampleJob : QuartzJobBean() {

	// fields ...

	private var myService: MyService? = null

	private var name: String? = null

	// Inject "MyService" bean
	fun setMyService(myService: MyService?) {
		this.myService = myService
	}

	// Inject the "name" job data property
	fun setName(name: String?) {
		this.name = name
	}

	override fun executeInternal(context: JobExecutionContext) {
		myService!!.someMethod(context.fireTime, name)
	}

}