0

0

在Spring Boot中配置多个Quartz定时任务

花韻仙語

花韻仙語

发布时间:2025-10-11 12:27:01

|

1060人浏览过

|

来源于php中文网

原创

在Spring Boot中配置多个Quartz定时任务

本文详细介绍了如何在spring boot应用中配置并管理多个quartz定时任务。通过创建独立的job类、jobdetailfactorybean和simpletriggerfactorybean,并利用spring的依赖注入机制将这些任务和触发器集合注入到schedulerfactorybean中,实现灵活、可扩展的多任务调度,同时提供了完整的配置示例和注意事项。

Quartz调度核心概念回顾

在深入多任务配置之前,我们先简要回顾Quartz的几个核心概念:

  • Job: 一个接口,定义了需要执行的具体任务逻辑。实现org.quartz.Job接口并重写execute方法。
  • JobDetail: Job的实例,包含任务的元数据,如任务名称、组名、是否持久化等。它告诉调度器要执行哪个Job。
  • Trigger: 触发器,定义了任务何时执行的规则,如立即启动、重复间隔、特定时间点等。Quartz提供了多种触发器类型,如SimpleTrigger和CronTrigger。
  • Scheduler: 调度器,是Quartz的核心,负责协调JobDetail和Trigger,启动、停止、暂停任务等。

在Spring Boot中,我们通常通过SchedulerFactoryBean来集成和配置Quartz调度器,并使用JobDetailFactoryBean和SimpleTriggerFactoryBean(或CronTriggerFactoryBean)来定义具体的任务和触发器。

单个Quartz任务的配置模式

在Spring Boot中配置单个Quartz任务通常涉及以下步骤:

  1. 定义一个实现org.quartz.Job接口的Java类。
  2. 创建一个JobDetailFactoryBean来包装这个Job类。
  3. 创建一个SimpleTriggerFactoryBean来定义任务的触发规则,并关联到对应的JobDetail。
  4. 配置SchedulerFactoryBean,将上述JobDetail和Trigger注入其中。

以下是一个典型的单任务配置示例:

@Configuration
public class SchedulerConfig {

    private ApplicationContext applicationContext;

    @Autowired
    public SchedulerConfig(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    // 自定义JobFactory,使Quartz Job能够自动注入Spring Bean
    @Bean
    public JobFactory jobFactory() {
        AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
        jobFactory.setApplicationContext(applicationContext);
        return jobFactory;
    }

    // 配置SchedulerFactoryBean,只设置一个触发器
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(Trigger simpleJobTrigger) throws IOException {
        SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
        schedulerFactory.setQuartzProperties(quartzProperties());
        schedulerFactory.setWaitForJobsToCompleteOnShutdown(true);
        schedulerFactory.setAutoStartup(true);
        schedulerFactory.setTriggers(simpleJobTrigger); // 仅接受一个Trigger
        schedulerFactory.setJobFactory(jobFactory());
        return schedulerFactory;
    }

    // 定义单个JobDetail
    @Bean
    public JobDetailFactoryBean keywordPostJobDetail() {
        JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
        factoryBean.setJobClass(DomainOrgCheckJob.class); // 示例Job类
        factoryBean.setDurability(true); // 任务持久化
        return factoryBean;
    }

    // 定义单个SimpleTrigger,关联到keywordPostJobDetail
    @Bean
    public SimpleTriggerFactoryBean simpleJobTrigger(@Qualifier("keywordPostJobDetail") JobDetail jobDetail,
                                                     @Value("${simplejob.frequency}") long frequency) {
        SimpleTriggerFactoryBean factoryBean = new SimpleTriggerFactoryBean();
        factoryBean.setJobDetail(jobDetail);
        factoryBean.setStartDelay(0L);
        factoryBean.setRepeatInterval(frequency);
        factoryBean.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
        return factoryBean;
    }

    // 加载Quartz配置属性
    public Properties quartzProperties() throws IOException {
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
        propertiesFactoryBean.afterPropertiesSet();
        return propertiesFactoryBean.getObject();
    }
}

在上述配置中,SchedulerFactoryBean的setTriggers方法只接受一个Trigger数组,这意味着如果直接传入一个Trigger对象,它只能调度一个任务。为了调度多个任务,我们需要对SchedulerFactoryBean的配置进行调整。

配置多个Quartz任务的策略

要配置多个Quartz任务,核心思想是为每个任务创建独立的JobDetail和Trigger,然后将所有这些JobDetail和Trigger作为一个集合传递给SchedulerFactoryBean。Spring的依赖注入机制能够自动收集所有类型为JobDetail和Trigger的Bean,并将它们作为列表注入到SchedulerFactoryBean中。

imgAK
imgAK

一站式AI图像处理工具

下载

具体步骤如下:

  1. 创建多个Job类: 每个不同的定时任务都应该有其独立的Job类。
  2. 创建多个JobDetailFactoryBean: 为每个Job类定义一个@Bean方法,返回JobDetailFactoryBean。通过@Bean(name = "...")为每个JobDetail指定一个唯一的名称,便于后续Trigger引用。
  3. 创建多个SimpleTriggerFactoryBean: 为每个JobDetail定义一个@Bean方法,返回SimpleTriggerFactoryBean。使用@Qualifier注解确保每个Trigger关联到正确的JobDetail。
  4. 修改SchedulerFactoryBean配置: 调整SchedulerFactoryBean的构造函数或@Bean方法,使其能够接受一个List和List。SchedulerFactoryBean的setJobDetails和setTriggers方法都接受数组,Spring会自动将列表转换为数组。

完整的多任务配置示例

下面是包含两个独立Quartz任务的完整配置示例:

import org.quartz.JobDetail;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.spi.JobFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

import java.io.IOException;
import java.util.List;
import java.util.Properties;

// 假设存在以下两个Job类
// class FirstDomainOrgCheckJob implements org.quartz.Job { ... }
// class SecondDomainOrgCheckJob implements org.quartz.Job { ... }

@Configuration
public class MultipleJobSchedulerConfig {

    private static final Logger LOG = LoggerFactory.getLogger(MultipleJobSchedulerConfig.class);

    private ApplicationContext applicationContext;

    @Autowired
    public MultipleJobSchedulerConfig(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    // 自定义JobFactory,使Quartz Job能够自动注入Spring Bean
    @Bean
    public JobFactory jobFactory() {
        AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
        jobFactory.setApplicationContext(applicationContext);
        return jobFactory;
    }

    // 核心修改:SchedulerFactoryBean现在接受JobDetail和Trigger的列表
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(List jobDetails,
                                                     List triggers) throws IOException {
        SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
        schedulerFactory.setQuartzProperties(quartzProperties()); // 加载Quartz配置
        schedulerFactory.setJobFactory(jobFactory());
        schedulerFactory.setWaitForJobsToCompleteOnShutdown(true);
        schedulerFactory.setAutoStartup(true);

        // 将所有JobDetail和Trigger列表转换为数组并设置给SchedulerFactoryBean
        schedulerFactory.setJobDetails(jobDetails.toArray(new JobDetail[0]));
        schedulerFactory.setTriggers(triggers.toArray(new Trigger[0]));

        LOG.debug("SchedulerFactoryBean configured with {} jobs and {} triggers.", jobDetails.size(), triggers.size());
        return schedulerFactory;
    }

    // 第一个任务的JobDetail定义
    @Bean(name = "firstJobDetail") // 指定Bean名称
    public JobDetailFactoryBean firstJobDetail() {
        JobDetailFactoryBean jobDetailFactory = new JobDetailFactoryBean();
        jobDetailFactory.setJobClass(FirstDomainOrgCheckJob.class); // 绑定第一个Job类
        jobDetailFactory.setDurability(true);
        return jobDetailFactory;
    }

    // 第一个任务的Trigger定义,通过@Qualifier引用firstJobDetail
    @Bean
    public SimpleTriggerFactoryBean firstJobTrigger(@Qualifier("firstJobDetail") JobDetail job,
                                                    @Value("${first.job.frequency}") long frequency) {
        LOG.info("Configuring First Job Trigger");
        SimpleTriggerFactoryBean factoryBean = new SimpleTriggerFactoryBean();
        factoryBean.setJobDetail(job);
        factoryBean.setStartDelay(0L);
        factoryBean.setRepeatInterval(frequency);
        factoryBean.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
        return factoryBean;
    }

    // 第二个任务的JobDetail定义
    @Bean(name = "secondJobDetail") // 指定Bean名称
    public JobDetailFactoryBean secondJobDetail() {
        JobDetailFactoryBean jobDetailFactory = new JobDetailFactoryBean();
        jobDetailFactory.setJobClass(SecondDomainOrgCheckJob.class); // 绑定第二个Job类
        jobDetailFactory.setDurability(true);
        return jobDetailFactory;
    }

    // 第二个任务的Trigger定义,通过@Qualifier引用secondJobDetail
    @Bean
    public SimpleTriggerFactoryBean secondJobTrigger(@Qualifier("secondJobDetail") JobDetail job,
                                                     @Value("${second.job.frequency}") long frequency) {
        LOG.info("Configuring Second Job Trigger");
        SimpleTriggerFactoryBean factoryBean = new SimpleTriggerFactoryBean();
        factoryBean.setJobDetail(job);
        factoryBean.setStartDelay(0L);
        factoryBean.setRepeatInterval(frequency);
        factoryBean.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
        return factoryBean;
    }

    // 加载Quartz配置属性
    public Properties quartzProperties() throws IOException {
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
        propertiesFactoryBean.afterPropertiesSet();
        return propertiesFactoryBean.getObject();
    }
}

辅助类:AutowiringSpringBeanJobFactory

为了让Quartz的Job类能够自动注入Spring管理的Bean,我们需要一个自定义的JobFactory。

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

public class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {

    private transient AutowireCapableBeanFactory beanFactory;

    @Override
    public void setApplicationContext(final ApplicationContext context) {
        beanFactory = context.getAutowireCapableBeanFactory();
    }

    @Override
    protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
        final Object job = super.createJobInstance(bundle);
        beanFactory.autowireBean(job); // 自动注入Job实例中的依赖
        return job;
    }
}

quartz.properties 配置示例

为了支持外部化配置,例如任务频率,可以在src/main/resources/quartz.properties中定义:

org.quartz.scheduler.instanceName=MyScheduler
org.quartz.threadPool.threadCount=10
org.quartz.jobStore.class=org.quartz.simpl.RAMJobStore
# 任务频率配置
first.job.frequency=5000  # 第一个任务每5秒执行一次
second.job.frequency=10000 # 第二个任务每10秒执行一次

注意事项与最佳实践

  1. JobDetail的命名: 使用@Bean(name = "...")为JobDetailFactoryBean指定唯一的Bean名称,这对于通过@Qualifier注解在Trigger中准确引用是至关重要的。
  2. 配置外部化: 利用Spring的@Value注解将任务的执行频率等参数从代码中分离,存储在application.properties或quartz.properties等配置文件中,提高灵活性。
  3. Job的独立性: 每个Job类应设计为独立的业务逻辑单元,避免任务间的紧密耦合。
  4. 错误处理与日志: 在Job的execute方法中实现健壮的错误处理机制,并利用日志框架记录任务的执行状态和潜在问题,便于监控和调试。
  5. 触发器类型选择:
    • SimpleTriggerFactoryBean适用于固定间隔重复执行的任务。
    • CronTriggerFactoryBean适用于更复杂的调度需求,例如每天特定时间、每周特定日期等,通过Cron表达式定义。
  6. 持久化: 如果需要调度器在应用重启后依然能够恢复任务状态,需要配置Quartz的持久化存储(如JDBC JobStore),而非默认的RAMJobStore。

总结

通过上述方法,我们可以在Spring Boot应用中优雅地配置和管理多个Quartz定时任务。关键在于利用Spring的依赖注入能力,将所有独立的JobDetail和Trigger作为Bean集合注入到SchedulerFactoryBean中。这种模式不仅使得配置清晰,也为未来任务的扩展提供了良好的基础。遵循最佳实践,可以构建出健壮、可维护的定时任务调度系统。

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

832

2023.06.15

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

738

2023.07.05

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

734

2023.07.31

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

397

2023.08.01

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

398

2023.08.02

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

446

2023.08.02

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

430

2023.08.02

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

16925

2023.08.03

Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

8

2026.01.15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2.5万人学习

C# 教程
C# 教程

共94课时 | 6.8万人学习

Java 教程
Java 教程

共578课时 | 46.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号