Springboot整合Quartz实现定时任务数据库动态配置

文章目录

  • Springboot整合Quartz实现定时任务数据库动态配置
    • 1.引入相关依赖,包括Spring Boot、Quartz和数据库驱动等,例如:
    • 2.配置数据源,例如:
    • 3.创建QuartzConfig实体类,用于表示定时任务的配置信息,例如:
    • 4.创建MyJob类,用于实现具体的定时任务逻辑,例如:
    • 5.创建定时任务配置的Repository接口,例如:
    • 6.创建定时任务调度器的配置类,例如:
    • 7.创建QuartzConfigService类,用于初始化调度器,并从数据库中读取定时任务配置信息,例如:

Springboot整合Quartz实现定时任务数据库动态配置

以下是Spring Boot整合Quartz实现定时任务数据库动态配置的步骤:

1.引入相关依赖,包括Spring Boot、Quartz和数据库驱动等,例如:

<!-- Quartz依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

<!-- 数据库连接依赖 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

2.配置数据源,例如:

spring.datasource.url=jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

3.创建QuartzConfig实体类,用于表示定时任务的配置信息,例如:

@Entity
@Data
public class QuartzConfig {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // 任务名称
    private String name;

    // 任务分组
    private String group;

    // Cron表达式
    private String cronExpression;

    // Job描述
    private String jobDescription;
}

4.创建MyJob类,用于实现具体的定时任务逻辑,例如:

public class MyJob implements Job {

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {

        // 获取JobDataMap中的参数信息
        JobDataMap dataMap = context.getMergedJobDataMap();
        // 不同任务 相同的 key 可以拿到不同的 value
        String param1 = dataMap.getString("param1");
        // 不同任务 相同的 key 可以拿到不同的 value
        String param2 = dataMap.getString("param2");
        
        // 执行具体的定时任务逻辑,使用参数信息等
        System.out.println("Hello, Quartz!");
    }
}

5.创建定时任务配置的Repository接口,例如:

@Repository
public interface QuartzConfigRepository extends JpaRepository<QuartzConfig, Long> {

    // 省略自定义查询方法

    // 新增定时任务配置
    QuartzConfig save(QuartzConfig quartzConfig);
}

6.创建定时任务调度器的配置类,例如:

@Configuration
public class QuartzConfig {

    @Autowired
    private DataSource dataSource;

    // 配置SchedulerFactoryBean,用于创建调度器实例
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() {
        // 创建 SchedulerFactoryBean 实例
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        // 设置数据源
        schedulerFactoryBean.setDataSource(dataSource);
        // 设置 ApplicationContext 在 SchedulerContext 中的 key 值,在 Scheduler 调度任务时,可以通过 SchedulerContext 获取当前的 ApplicationContext 对象
        schedulerFactoryBean.setApplicationContextSchedulerContextKey("applicationContext");
        // 设置任务执行器
        schedulerFactoryBean.setTaskExecutor(schedulerThreadPool());
        // 设置是否自动启动 Scheduler
        schedulerFactoryBean.setAutoStartup(true);
        // 设置是否覆盖已存在的 job
        /*
        当该属性设置为 true 时,如果 Quartz 发现已有相同名称和分组的触发器和任务存在,
        则会替换掉原来的触发器和任务。如果该属性设置为 false,则不会覆盖已经存在的任务,
        而是抛出一个异常。需要注意的是,如果调度器中有正在执行的任务,它们不受此属性的影响,
        仍然会继续执行直到完成。
         */
        schedulerFactoryBean.setOverwriteExistingJobs(true);
        // 调用了方法 quartzProperties() 来获取 Properties 对象
        schedulerFactoryBean.setQuartzProperties(quartzProperties());
        // 返回创建好的 SchedulerFactoryBean 实例
        return schedulerFactoryBean;
    }

    // 配置线程池,用于执行定时任务
    @Bean
    public TaskExecutor schedulerThreadPool() {
        // 创建 ThreadPoolTaskExecutor 实例
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置线程池中线程的名称前缀为 "quartz-thread-"
        executor.setThreadNamePrefix("quartz-thread-");
        // 设置核心线程数为 5
        executor.setCorePoolSize(5);
        // 设置最大线程数为 10
        executor.setMaxPoolSize(10);
        // 设置队列容量为 1024
        executor.setQueueCapacity(1024);
        // 初始化线程池
        executor.initialize();
        // 返回创建好的 ThreadPoolTaskExecutor 实例。这个实例可以用来执行调度任务
        return executor;
    }

    // 配置Quartz的属性,例如jobStore、schedulerName等
    private Properties quartzProperties() {
        // 创建一个 Properties 实例,用于存储 Quartz 的配置属性
        Properties properties = new Properties();
        // 设置调度器实例的名称
        properties.setProperty("org.quartz.scheduler.instanceName", "HandsomeScheduler");
        // 让 Quartz 自动生成调度器实例 ID
        properties.setProperty("org.quartz.scheduler.instanceId", "AUTO");
        // 指定 Quartz 使用数据库作为作业存储器,并启用事务
        properties.setProperty("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
        // 指定 Quartz 使用标准 JDBC 委托类来管理数据库和作业存储器
        properties.setProperty("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate");
        // 指定 Quartz 使用名为 "HandsomeDB" 的数据源
        properties.setProperty("org.quartz.jobStore.dataSource", "HandsomeDB");
        // 指定 Quartz 在数据库中使用的表名前缀
        properties.setProperty("org.quartz.jobStore.tablePrefix", "QRTZ_");
        // 设置 Quartz 集群模式为非集群模式
        properties.setProperty("org.quartz.jobStore.isClustered", "false");
        // 指定 "HandsomeDB" 数据源使用的 JDBC 驱动程序
        properties.setProperty("org.quartz.dataSource.HandsomeDB.driver", "com.mysql.cj.jdbc.Driver");
        // 指定 "HandsomeDB" 数据源使用的 JDBC URL
        properties.setProperty("org.quartz.dataSource.myDS.URL", "jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai");
        // 指定 "HandsomeDB" 数据源使用的用户名
        properties.setProperty("org.quartz.dataSource.HandsomeDB.user", "root");
        // 指定 "HandsomeDB" 数据源使用的密码
        properties.setProperty("org.quartz.dataSource.HandsomeDB.password", "root");
        // 指定 "HandsomeDB" 数据源允许的最大连接数
        properties.setProperty("org.quartz.dataSource.HandsomeDB.maxConnections", "10");
        // 为 "HandsomeDB" 数据源设置一个用于测试连接是否可用的 SQL 查询语句
        properties.setProperty("org.quartz.dataSource.HandsomeDB.validationQuery", "select 1");
        // 返回创建好的 Quartz 的配置属性 Properties 实例
        return properties;
    }
}

在以上示例代码中,我们通过@Configuration注解标记了QuartzConfig类,并在其中进行SchedulerFactoryBean的配置。具体包括:

配置数据源dataSource,用于SchedulerFactoryBean连接数据库。
创建schedulerFactoryBean Bean实例,并设置相关属性,例如调度器名称、线程池、自动启动等,最后返回schedulerFactoryBean。
创建schedulerThreadPool Bean实例,用于执行定时任务的线程池配置。
配置quartzProperties,用于定义Quartz的属性,例如jobStore、schedulerName等。

需要注意的是,在实际生产环境中,我们可能还需要根据具体业务需求,对线程池、数据源等进行进一步的优化配置。

7.创建QuartzConfigService类,用于初始化调度器,并从数据库中读取定时任务配置信息,例如:

@Service
public class QuartzConfigService {

    @Autowired
    private QuartzConfigRepository quartzConfigRepository;

    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    // 初始化调度器,并从数据库中读取定时任务配置信息,创建对应的定时任务
    @PostConstruct
    public void initScheduler() throws Exception {
        // 获取调度器实例
        Scheduler scheduler = schedulerFactoryBean.getScheduler();

        // 查询数据库中所有的定时任务配置信息
        List<QuartzConfig> quartzConfigs = quartzConfigRepository.findAll();

        // 遍历定时任务配置信息列表,为每个定时任务创建JobDetail和Trigger对象,并添加到调度器中
        for (QuartzConfig config : quartzConfigs) {
            // 创建一个JobDetail对象,用于描述Job实现类及其他一些静态信息
            JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
                .withIdentity(config.getName(), config.getGroup()) // 定义任务名称和分组
                .usingJobData("param1", "value1")
                .build();
            // 创建一个Trigger对象,用于定义周期性执行的时间规则等
            CronTrigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(config.getName(), config.getGroup()) // 定义任务名称和分组
                .withSchedule(CronScheduleBuilder.cronSchedule(config.getCronExpression())) // 定义Cron表达式
                .usingJobData("param2", "value2")
                .build();

            // 将JobDetail和Trigger关联到调度器中,实现任务的调度
            scheduler.scheduleJob(jobDetail, trigger);
        }

        // 启动调度器
        scheduler.start();
    }

    // 新增定时任务配置 不影响原来的定时任务
    public void addQuartzConfig(QuartzConfig config) throws Exception {
        // 保存定时任务配置信息到数据库
        quartzConfigRepository.save(config);
        
        // 获取调度器实例
        Scheduler scheduler = schedulerFactoryBean.getScheduler();

        // 创建一个JobDetail对象,用于描述Job实现类及其他一些静态信息
        JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
            .withIdentity(config.getName(), config.getGroup()) // 定义任务名称和分组
            .build();
        // 创建一个Trigger对象,用于定义周期性执行的时间规则等
        CronTrigger trigger = TriggerBuilder.newTrigger()
            .withIdentity(config.getName(), config.getGroup()) // 定义任务名称和分组
            .withSchedule(CronScheduleBuilder.cronSchedule(config.getCronExpression())) // 定义Cron表达式
            .build();

        // 将JobDetail和Trigger关联到调度器中,实现任务的调度
        scheduler.scheduleJob(jobDetail, trigger);
    }
}

在以上示例代码中,我们通过@PostConstruct注解标记的initScheduler()方法,在Spring容器初始化完成后自动执行,实现从数据库中读取定时任务配置信息,并创建对应的JobDetail和Trigger对象,添加到调度器中,最后启动调度器,实现自动运行定时任务的功能。addQuartzConfig方法实现新增定时任务配置。

需要注意的是,在实际生产环境中,我们可能还需要根据具体业务需求,对定时任务的配置信息进行更新、删除等操作,因此需要在QuartzConfigService中添加相应的方法来实现这些功能。

你可能感兴趣的:(HandsomeForum,Quartz,SpringBoot)