Quartz 调度器
Spring Boot 为使用 Quartz 调度器 提供了多种便利,包括 spring-boot-starter-quartz
starter。如果 Quartz 可用,则会自动配置一个 Scheduler
(通过 SchedulerFactoryBean
抽象)。
以下类型的 Bean 会被自动检测并与 Scheduler
关联起来:
-
JobDetail
:定义特定的 Job。JobDetail
实例可以使用JobBuilder
API 构建。 -
Trigger
:定义特定 Job 的触发时间。
默认情况下,使用内存中的 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 使用一个不同于应用主要 DataSource
的 DataSource
,请声明一个 DataSource
bean,并用 @QuartzDataSource
注解其 @Bean
方法。这样做可以确保 Quartz 专用的 DataSource
被 SchedulerFactoryBean
和 schema 初始化所使用。类似地,要让 Quartz 使用一个不同于应用主要 TransactionManager
的 TransactionManager
,请声明一个 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)
}
}