在 IT 基础设施管理中,网络设备配置定时备份是保障运维安全的核心需求(避免配置丢失、支持故障回滚)。本文基于 Spring Boot 2.x 环境,详细讲解如何整合 Quartz 实现动态任务调度,解决数据源配置、任务增删改查、Spring Bean 注入等关键问题,附完整可复用代码。
一、环境准备与核心依赖
1. 技术栈选型
- 基础框架:Spring Boot 2.x
- 任务调度:Quartz 2.3.x(Spring Boot Starter 集成)
- 数据源:Druid 连接池 + MySQL 8.0
- 工具类:Hutool(JSON 序列化/反序列化)
- 其他:Spring WebSecurity(权限控制,可选)
手动执行 Quartz 建表脚本(路径:quartz-core-2.3.x.jar!/org/quartz/impl/jdbcjobstore/tables_mysql_innodb.sql)
2. Maven 核心依赖
在 pom.xml 中引入 Quartz Starter 及 Druid 依赖(已集成的可忽略):
<!-- Quartz 任务调度 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<!-- Druid 数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.16</version> <!-- 版本可按需调整 -->
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Hutool 工具类(JSON 处理) -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.22</version>
</dependency>
二、Quartz 核心配置(解决数据源与 Bean 注入问题)
Quartz 默认不依赖 Spring 数据源,且 Job 实例无法直接注入 Spring Bean(如 Mapper/Service)。以下配置从 数据源绑定 和 Spring 上下文集成 两方面解决核心痛点。
1. 自定义 Quartz 数据源提供者
手动将 Druid 数据源注入 Quartz,避免 Quartz 找不到数据源的问题:
import com.alibaba.druid.pool.DruidDataSource;
import org.quartz.utils.ConnectionProvider;
import org.springframework.stereotype.Component;
import java.sql.Connection;
import java.sql.SQLException;
/**
* Quartz 自定义数据源提供者(绑定 Druid 数据源)
*/
@Component
public class DruidQuartzConnectionProvider implements ConnectionProvider {
private final DruidDataSource dataSource;
// 构造器注入 Spring 管理的 Druid 数据源
public DruidQuartzConnectionProvider(DruidDataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public Connection getConnection() throws SQLException {
// 直接从 Druid 连接池获取连接
return dataSource.getConnection();
}
@Override
public void shutdown() {
// 数据源由 Spring 管理,无需手动关闭
}
@Override
public void initialize() throws SQLException {
// 避免重复初始化(依赖 Spring 初始化 Druid)
}
}
2. Quartz 核心配置类
配置 Scheduler 工厂、任务工厂(支持 Spring Bean 注入)、Quartz 集群属性:
import com.alibaba.druid.pool.DruidDataSource;
import org.quartz.Scheduler;
import org.quartz.spi.TriggerFiredBundle;
import org.quartz.utils.DBConnectionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import javax.annotation.PostConstruct;
import java.util.Properties;
/**
* Quartz 核心配置类(数据源绑定 + 任务工厂配置)
*/
@Configuration
@Order(1) // 确保配置优先加载
public class QuartzConfig {
@Autowired
private DruidDataSource dataSource;
@Autowired
private ApplicationContext applicationContext;
/**
* 初始化 Quartz 数据源(解决 Quartz 找不到数据源问题)
*/
@PostConstruct
public void initDataSourceProvider() {
DBConnectionManager.getInstance()
.addConnectionProvider("druidDataSource", new DruidQuartzConnectionProvider(dataSource));
}
/**
* 配置 Scheduler 工厂(核心)
*/
@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
// 1. 绑定数据源
factory.setDataSource(dataSource);
// 2. 配置 Quartz 属性(集群 + 线程池)
factory.setQuartzProperties(quartzProperties());
// 3. 应用启动时自动启动调度器
factory.setAutoStartup(true);
// 4. 覆盖已存在的任务(避免重复)
factory.setOverwriteExistingJobs(true);
// 5. 关键:配置 Job 工厂,支持 Spring Bean 注入
ConfigurableApplicationContext configurableContext = (ConfigurableApplicationContext) applicationContext;
AutowireCapableBeanFactory autowireBeanFactory = configurableContext.getAutowireCapableBeanFactory();
factory.setJobFactory(new AdaptableJobFactory() {
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
// 第一步:Quartz 默认创建 Job 实例
Object jobInstance = super.createJobInstance(bundle);
// 第二步:Spring 自动注入 Job 中的 Bean(如 Mapper/Service)
autowireBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
});
return factory;
}
/**
* 注册 Scheduler 实例(供业务代码调用)
*/
@Bean
public Scheduler scheduler(SchedulerFactoryBean factory) {
return factory.getScheduler();
}
/**
* Quartz 核心属性配置(集群模式 + 线程池)
*/
private Properties quartzProperties() {
Properties properties = new Properties();
// 调度器实例名(集群内统一)
properties.setProperty("org.quartz.scheduler.instanceName", "NetDeviceBackupScheduler");
// 实例 ID 自动生成(集群模式必备)
properties.setProperty("org.quartz.scheduler.instanceId", "AUTO");
// 线程池配置(25 个线程,优先级 5)
properties.setProperty("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
properties.setProperty("org.quartz.threadPool.threadCount", "25");
properties.setProperty("org.quartz.threadPool.threadPriority", "5");
// 持久化配置(JDBC 存储,支持集群)
properties.setProperty("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
properties.setProperty("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate");
properties.setProperty("org.quartz.jobStore.tablePrefix", "QRTZ_"); // 数据库表前缀
properties.setProperty("org.quartz.jobStore.isClustered", "true"); // 启用集群
properties.setProperty("org.quartz.jobStore.clusterCheckinInterval", "20000"); // 集群

最低0.47元/天 解锁文章

702

被折叠的 条评论
为什么被折叠?



