SpringBoot 2.x quartz多數據源定時任務配置

基礎環境

SpringBoot 2.0 開始官方提供了對quartz定時任務的自動配置支持依賴spring-boot-starter-quartz組件,無需自行集成java

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
複製代碼

環境版本:mysql

  1. SpringBoot 2.1.6.RELEASE
  2. Java 8

定時任務配置

添加依賴

在pom.xml中添加quartz、Jpa、mysql驅動、lombok依賴spring

<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>
複製代碼

添加配置文件

添加數據庫配置sql

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中,但親測配置無效,而且因爲還須要指定鏈接池等信息,此處配置在spring的鏈接池中更容易管理數據庫

下載官網建表語句

儘管使用了JPA,但因爲沒有實體關聯,spring並不會幫咱們自動建表,還須要去官網下載sql腳本併發

quartz官網dom

官網壓縮包路徑quartz-2.3.0-SNAPSHOT\src\org\quartz\impl\jdbcjobstore中支持大量數據庫建表語句,選擇對應的使用便可分佈式

1564406464554.png

配置多數據源

多配置源以前在文章中詳細說過配置樣例和緣由,這裏再也不贅述ide

SpringBoot2.x Data JPA 多數據源爬坑spring-boot

編寫數據庫配置,統一使用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
相關文章
相關標籤/搜索