SpringBoot 2.x кварцевая конфигурация задачи синхронизации с несколькими источниками данных

Spring Boot

основная среда

SpringBootНачиная с версии 2.0 официальныйquartzАвтоматическая настройка временных задач поддерживает зависимостиspring-boot-starter-quartzкомпоненты без самоинтеграции

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

Версия среды:

  1. SpringBoot 2.1.6.RELEASE
  2. Java 8

Настройка запланированной задачи

добавить зависимости

Добавьте кварц, Jpa, драйвер mysql, зависимости lombok в pom.xml


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

Добавить файл конфигурации

Добавить конфигурацию базы данных

spring:
  datasource:
    primary:
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: root
      password: hmdt
      url: jdbc:mysql://db/bussines_db?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    quartz:
      url: jdbc:mysql://db/bussines_quartz?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: root
      password: hmdt

  quartz:
    #相关属性配置
    properties:
      org:
        quartz:
          scheduler:
            instanceName: clusteredScheduler
            instanceId: AUTO
          jobStore:
            # 数据源名称
            dataSource: quartzDataSource
            class: org.quartz.impl.jdbcjobstore.JobStoreTX
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
            tablePrefix: QRTZ_
            isClustered: true
            clusterCheckinInterval: 1000
            useProperties: false
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool
            threadCount: 10
            threadPriority: 5
            threadsInheritContextClassLoaderOfInitializingThread: true
    job-store-type: jdbc
    #初始化表结构
    jdbc:
      initialize-schema: never
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    database-platform: org.hibernate.dialect.MySQL55Dialect
    properties:
      hibernate:
        format_sql: true
        use_sql_comments: true

Конфигурация базы данных также приведена вspring.quartz.properties, но конфигурация pro-test недействительна, и, поскольку пул соединений и другую информацию также необходимо указать, конфигурацией здесь проще управлять в пуле соединений spring.

Скачать заявление о построении таблицы с официального сайта

несмотря на использованиеJPA, но так как ассоциации сущностей нет,springЭто не поможет нам построить таблицу автоматически, вам нужно перейти на официальный сайт, чтобы скачатьsqlсценарий

официальный сайт кварца

Путь к сжатому пакету официального веб-сайтаquartz-2.3.0-SNAPSHOT\src\org\quartz\impl\jdbcjobstoreПоддержка большого количества операторов построения таблиц базы данных в

1564406464554.png

Настройка нескольких источников данных

Несколько источников конфигурации были подробно описаны в статье ранее, и здесь не будут повторяться примеры конфигурации и причины.

SpringBoot2.x Data JPA лазание по нескольким источникам данных

Напишите конфигурацию базы данных и используйте ее единообразноHikariCPпул соединений

package com.gcb.invest.config;

import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.quartz.QuartzDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

/**
 * 定时任务数据源配置
 *
 * @author F嘉阳
 * @date 2019-07-28 21:52
 */
@Configuration
public class DataSourceConfig {

    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource.primary")
    public DataSourceProperties primaryDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource.primary.configuration")
    public HikariDataSource firstDataSource() {
        return primaryDataSourceProperties().initializeDataSourceBuilder()
                .type(HikariDataSource.class).build();
    }

    @Bean
    @ConfigurationProperties("spring.datasource.quartz")
    public DataSourceProperties quartzDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @QuartzDataSource
    @ConfigurationProperties("spring.datasource.quartz.configuration")
    public HikariDataSource quartzDataSource() {
        return quartzDataSourceProperties().initializeDataSourceBuilder()
                .type(HikariDataSource.class).build();
    }
}

Настройка запланированной задачи

Пример конфигурации 1 — Bean-инъекция

Напишите временные задачи, которые удобнее использовать из-за инкапсуляции Spring.

Здесь временная задача настраивается через внутренний класс и используется@DisallowConcurrentExecutionВ аннотации указано, что он не может выполняться одновременно в распределенной среде.

import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.QuartzJobBean;

/**
 * 定时任务配置
 *
 * @author :F嘉阳
 * @date :2019/7/29 9:16
 */
@Slf4j
@Configuration
public class QuartzConfig {

    /**
     * 测试定时任务构建
     *
     * @return
     */
    @Bean
    public JobDetail testTaskJobDetail() {
        return JobBuilder.newJob(TestTask.class)
                .withIdentity(TestTask.class.getName())
                .storeDurably(true)
                .build();
    }

    /**
     * 测试定时任务配置
     *
     * @return
     */
    @Bean
    public Trigger testTaskTrigger() {
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/2 * * * * ?");
        return TriggerBuilder.newTrigger()
                .forJob(testTaskJobDetail())
                .withIdentity(TestTask.class.getName())
                .withSchedule(scheduleBuilder)
                .build();
    }

    @DisallowConcurrentExecution
    private class TestTask extends QuartzJobBean {
        @Override
        protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            log.debug("执行测试定时任务");
        }
    }
}

Пример конфигурации 2 — внедрение планировщика

Другой способ — использовать планировщик инъекций для ручного построения задачи, но для этого требуетсявызовите этот методПосле этого планировщик будет создан.

import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.UUID;

/**
 * @author :F嘉阳
 * @date :2019/7/29 8:59
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class QuartzTimerService {

    @Autowired
    private Scheduler scheduler;

    public void buildGoodStockTimer() throws Exception {
        //任务名称
        String name = UUID.randomUUID().toString();
        //任务所属分组
        String group = CustomQuartzJob.class.getName();

        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/1 * * * * ?");
        //创建任务
        JobDetail jobDetail = JobBuilder.newJob(CustomQuartzJob.class).withIdentity(name,group).build();
        //创建任务触发器
        Trigger trigger = TriggerBuilder.newTrigger().withIdentity(name,group).withSchedule(scheduleBuilder).build();
        //将触发器与任务绑定到调度器内
        scheduler.scheduleJob(jobDetail, trigger);
    }
}

Запланированные задачи

import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

/**
 * @author :F嘉阳
 * @date :2019/7/29 8:55
 */
@Slf4j
@DisallowConcurrentExecution
public class CustomQuartzJob extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        log.info("执行定时任务");
    }
}

Результаты

выполнение успешно

1564383676571.png

Автоматическая миграция узлов заданий в распределенной среде

1564383705389.png