Quartz 排程器
Spring Boot 為使用 Quartz 排程器 提供了多項便利,包括 spring-boot-starter-quartz starter。如果 Quartz 可用,將透過 SchedulerFactoryBean 抽象自動配置一個 Scheduler。
以下型別的 Bean 會自動被識別並與 Scheduler 關聯
-
JobDetail:定義一個特定 Job。JobDetail例項可以使用JobBuilderAPI 構建。 -
Trigger:定義何時觸發特定 Job。
預設情況下,使用記憶體中的 JobStore。但是,如果應用程式中存在 DataSource bean 並且 spring.quartz.job-store-type 屬性配置得當,則可以配置基於 JDBC 的儲存,如下例所示
-
屬性
-
YAML
spring.quartz.job-store-type=jdbc
spring:
quartz:
job-store-type: "jdbc"
使用 JDBC 儲存時,可以在啟動時初始化模式,如下例所示
-
屬性
-
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 使用應用程式主 DataSource 之外的 DataSource,請宣告一個 DataSource bean,並使用 @QuartzDataSource 註解其 @Bean 方法。這樣做可以確保 Quartz 特定的 DataSource 被 SchedulerFactoryBean 和模式初始化所使用。同樣,要讓 Quartz 使用應用程式主 TransactionManager 之外的 TransactionManager,請宣告一個 TransactionManager bean,並使用 @QuartzTransactionManager 註解其 @Bean 方法。
預設情況下,由配置建立的 Job 不會覆蓋已從持久化 Job 儲存中讀取的已註冊 Job。要啟用覆蓋現有 Job 定義,請設定 spring.quartz.overwrite-existing-jobs 屬性。
Quartz 排程器配置可以透過 spring.quartz 屬性和 SchedulerFactoryBeanCustomizer bean 進行定製,這些 bean 允許對 SchedulerFactoryBean 進行程式化定製。高階 Quartz 配置屬性可以使用 spring.quartz.properties.* 進行定製。
特別是,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)
}
}