Spring Boot学习笔记(十二)Spring Boot整合Quartz

一、自定义配置类

不使用springBoot的自动配置类,而是自定义配置类。
1、导入依赖
pom文件:

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

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

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.44</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

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

        <!-- 连接数据库需要jdbc-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
        </dependency>
    </dependencies>

2、添加quartz配置文件:quartz.proerties

# Default Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance, if a different
# properties file is not explicitly specified.
#
# ===========================================================================
# Configure Main Scheduler Properties 调度器属性
# ===========================================================================
# 在集群中每个实例都必须有一个唯一的instanceId,但是应该有一个相同的instanceName 【默认“QuartzScheduler”】【非必须】
org.quartz.scheduler.instanceName=DefaultQuartzScheduler
# Scheduler实例ID,全局唯一,【默认值NON_CLUSTERED】,或者可以使用“SYS_PROP”通过系统属性设置id。【非必须】
org.quartz.scheduler.instanceId=AUTO
# 只有在”org.quartz.scheduler.instanceId”设置为”AUTO”的时候才使用该属性设置。
# 默认情况下,“org.quartz.simpl.SimpleInstanceIdGenerator”是基于instanceId和时间戳来自动生成的。
# 其他的id生成器的实现包括 SystemPropertyInstanceIdGenerator 从系统属性获取 “org.quartz.scheduler.instanceId”,
# 和 HostnameInstanceIdGenerator 使用主机名 (InetAddress.getLocalHost().getHostName())。
# 也可以自定义生成方式【默认org.quartz.simpl.SimpleInstanceIdGenerator】【非必须】
#org.quartz.scheduler.instanceIdGenerator.class = org.quartz.simpl.SimpleInstanceIdGenerator
# rmi远程调用设置
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false

# 指定线程名,如果不指定的话,会自动使用org.quartz.scheduler.instanceName属性值加上后缀字符串”_QuartzSchedulerThread”.【默认instanceName+’_QuartzSchedulerThread’】【非必须】
#org.quartz.scheduler.threadName =

# 指定scheduler的主线程是否为后台线程,【默认false】【非必须】
#org.quartz.scheduler.makeSchedulerThreadDaemon = false

# 指定scheduler的主线程是否为后台线程,【默认false】【非必须】
#org.quartz.scheduler.makeSchedulerThreadDaemon = false

# 指定Quartz生成的线程是否继承初始化线程的上下文类加载器。这会影响Quartz的主调度线程、JDBCJobStore的”熄火”处理线程、集群回复线程和线程池里的线程。 将该值设置为“true”可以帮助类加载,JNDI查找,并在应用程序服务器上使用Quartz等相关问题,【默认false】【非必须】
#org.quartz.scheduler.threadsInheritContextClassLoaderOfInitializer = false

# 在调度程序空闲的时候,重复查询是否有可用触发器的等待时间。通常并不会设置为true,除非你是用XA事务,并且延迟触发会导致问题的场景。 5000ms以下是不推荐的,因为它会导致过的的数据库查询。1000ms以下是非法的。【默认30000】【非必须】
#org.quartz.scheduler.idleWaitTime = 30000

# 连接超时重试连接的间隔。使用 RamJobStore时,该参数并没什么用【默认15000】【非必须】
#org.quartz.scheduler.dbFailureRetryInterval = 15000

# 最可靠的方式就是使用【默认”org.quartz.simpl.CascadingClassLoadHelper”】,没必要指定其他类【非必须】
#org.quartz.scheduler.classLoadHelper.class = org.quartz.simpl.CascadingClassLoadHelper

# 指定JobFactory的类(接口)名称。负责实例化jobClass。【默认”org.quartz.simpl.PropertySettingJobFactory”】,只是在job被执行的时候简单调用newInstance()实例化一个job类。PropertySettingJobFactory 会使用反射机制通过SchedulerContext、 Job、Trigger和 JobDataMaps设置job bean的属性。在使用JTA事务时,可设置事务相关的属性【非必须】
#org.quartz.scheduler.jobFactory.class = org.quartz.simpl.PropertySettingJobFactory
#org.quartz.context.key.SOME_KEY = none

# 设置Quartz能够加载UserTransaction换利器的JNDI的 URL。Websphere 的用户可能会设置为“jta/usertransaction。只有在Quartz使用JobStoreCMT的时候,才会使用该属性,并且org.quartz.scheduler.wrapJobExecutionInUserTransaction也会设置为true。默认【默认值是”java:comp/UserTransaction”】【非必须】
#org.quartz.scheduler.userTransactionURL = java:comp/UserTransaction

# 如果想使用Quartz在执行一个job前使用UserTransaction,则应该设置该属性为true。job执行完、在JobDataMap改变之后事务会提交。默认值是false。 可以在你的job类中使用 @ExecuteInJTATransaction注解, 可以控制job是否使用事务。【默认false】【非必须】
#org.quartz.scheduler.wrapJobExecutionInUserTransaction = false

# 建议设置为“org.terracotta.quartz.skipUpdateCheck=true”不会在程序运行中还去检查quartz是否有版本更新。【默认false】【非必须】
#org.quartz.scheduler.skipUpdateCheck = true

# 许调度程序一次性触发的触发器数量。.默认值是1。值越大一次性触发的任务就可以越多,但是在集群环境【非必须】下,不建议设置为很大值。如果值 > 1, 并且使用了 JDBC JobStore的话, org.quartz.jobStore.acquireTriggersWithinLock属性必须设置为true,以避免”弄脏”数据。【默认1】
#org.quartz.scheduler.batchTriggerAcquisitionMaxCount = 1

# 允许触发器被获取并在其预定的触发时间之前触发的数量。【默认0】【非必须】
#org.quartz.scheduler.batchTriggerAcquisitionFireAheadTimeWindow = 0

# ===========================================================================
# Configure ThreadPool 线程池属性
# ===========================================================================

#线程池的实现类(一般使用SimpleThreadPool即可满足几乎所有用户的需求)【必须】
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
#指定线程数,至少为1(无默认值)(一般设置为1-100直接的整数合适)【必须】
org.quartz.threadPool.threadCount = 10
#设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1,默认为5)【非必须】
org.quartz.threadPool.threadPriority = 5
#设置SimpleThreadPool的一些属性
#设置是否为守护线程
#org.quartz.threadpool.makethreadsdaemons = false
#org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
#org.quartz.threadpool.threadsinheritgroupofinitializingthread=false
#线程前缀默认值是:[Scheduler Name]_Worker
#org.quartz.threadpool.threadnameprefix=swhJobThead;

# 配置全局监听(TriggerListener,JobListener) 则应用程序可以接收和执行 预定的事件通知
# ===========================================================================
# Configuring a Global TriggerListener 配置全局的Trigger监听器
# MyTriggerListenerClass 类必须有一个无参数的构造函数,和 属性的set方法,目前2.2.x只支持原始数据类型的值(包括字符串)
# ===========================================================================
#org.quartz.triggerListener.NAME.class = com.swh.MyTriggerListenerClass
#org.quartz.triggerListener.NAME.propName = propValue
#org.quartz.triggerListener.NAME.prop2Name = prop2Value
# ===========================================================================
# Configuring a Global JobListener 配置全局的Job监听器
# MyJobListenerClass 类必须有一个无参数的构造函数,和 属性的set方法,目前2.2.x只支持原始数据类型的值(包括字符串)
# ===========================================================================
#org.quartz.jobListener.NAME.class = com.swh.MyJobListenerClass
#org.quartz.jobListener.NAME.propName = propValue
#org.quartz.jobListener.NAME.prop2Name = prop2Value

# ===========================================================================
# Configure JobStore 存储调度信息(工作,触发器和日历等)
# ===========================================================================
# 最大能忍受的触发超时时间(触发器被认定为“misfired”之前),如果超过则认为“失误”【默认60秒】
org.quartz.jobStore.misfireThreshold = 60000
# 将schedule相关信息保存在RAM中,轻量级,速度快,遗憾的是应用重启时相关信息都将丢失。
#org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore

# ------------------------使用JDBCJobStore配置
# 所有的quartz数据例如job和Trigger的细节信息被保存在内存或数据库中,有两种实现:JobStoreTX(自己管理事务,即在quartz里配置数据源)
# 和JobStoreCMT(application server管理事务,即全局事务JTA,即使用spring单独配置的数据源)
#org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX

#2.6.5版本以后,如果使用另外配置的数据源,需要使用这个
org.quartz.jobStore.class=org.springframework.scheduling.quartz.LocalDataSourceJobStore
# 类似于Hibernate的dialect,用于处理DB之间的差异,StdJDBCDelegate能满足大部分的DB
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# 数据表前缀
rg.quartz.jobStore.tablePrefix = QRTZ_
# 为了指示JDBCJobStore所有的JobDataMaps中的值都是字符串,并且能以“名字-值”对的方式存储而不是以复杂对象的序列化形式存储在BLOB字段中,应该设置为true(缺省方式)
org.quartz.jobStore.useProperties = true

# 配置数据源的名称,在后面配置数据源的时候要用到,例如org.quartz.dataSource.clusterDS.driver = com.mysql.jdbc.Driver
#org.quartz.jobStore.dataSource = clusterDS


# 是否集群、负载均衡、容错,如果应用在集群中设置为false会出错
#org.quartz.jobStore.isClustered = true
# 检入到数据库中的频率(毫秒)。检查是否其他的实例到了应当检入的时候未检入这能指出一个失败的实例,且当前Scheduler会以此来接管执行失败并可恢复的Job通过检入操作,Scheduler也会更新自身的状态记录
#org.quartz.jobStore.clusterCheckinInterval = 20000

# jobStore处理未按时触发的Job的数量
#org.quartz.jobStore.maxMisfiresToHandleAtATime = 20
# true/false,true则调用connection的setAutoCommit(false)方法
#org.quartz.jobStore.dontSetAutoCommitFalse = true

# 加锁的SQL语句,默认为SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE
# {0}=$@org.quartz.jobStore.tablePrefix
#org.quartz.jobStore.selectWithLockSQL = false

# true/false, true则调用connection的setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE) 方法
#org.quartz.jobStore.txIsolationLevelSerializable = false

# 触发job时是否需要拥有锁
#org.quartz.jobStore.acquireTriggersWithinLock = true

# 用于管理数据库中相关信息的锁机制的类名
#org.quartz.jobStore.lockHandler.class =

#============================================================================
# Configure Datasources 数据源
#============================================================================

# ------------------------使用常规数据源配置

# 数据库驱动
#org.quartz.dataSource.NAME.driver = com.mysql.jdbc.Driver
# 数据库连接地址
#org.quartz.dataSource.NAME.URL = jdbc:mysql://${mysql.address}/etc-quartz?useUnicode=true&characterEncoding=utf8
# 数据库用户名
#org.quartz.dataSource.NAME.user = ${mysql.user}
# 数据库密码
#org.quartz.dataSource.NAME.password = ${mysql.password}

# 数据库最大连接数(如果Scheduler很忙,比如执行的任务与线程池的数量差不多相同,那就需要配置DataSource的连接数量为线程池数量+1)
#org.quartz.dataSource.NAME.maxConnections = 30

# dataSource用于检测connection是否failed/corrupt的SQL语句
#org.quartz.dataSource.NAME.validationQuery=select RAND()



# ------------------------使用JNDI数据源配置

# JNDI URL
#org.quartz.dataSource.NAME.jndiURL =
# JNDI InitialContextFactory
#org.quartz.dataSource.NAME.java.naming.factory.initial =
# 后三行为连接到JNDI提供者的相关信息
#org.quartz.dataSource.NAME.java.naming.provider.url =
#org.quartz.dataSource.NAME.java.naming.security.principal =
#org.quartz.dataSource.NAME.java.naming.security.credentials =

# ------------------------用户自定义org.quartz.utils.ConnectionProvider实现类
#org.quartz.dataSource.NAME.connectionProvider.class =

#org.quartz.dataSource.NAME.XXX =

# ===========================================================================
# Configure SchedulerPlugins 插件属性 配置
# ===========================================================================
# 自定义插件
#org.quartz.plugin.NAME.class = com.swh.MyPluginClass
#org.quartz.plugin.NAME.propName = propValue
#org.quartz.plugin.NAME.prop2Name = prop2Value
#配置trigger执行历史日志(可以看到类的文档和参数列表)
org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingTriggerHistoryPlugin  
org.quartz.plugin.triggHistory.triggerFiredMessage = Trigger {1}.{0} fired job {6}.{5} at\: {4, date, HH\:mm\:ss MM/dd/yyyy}  
org.quartz.plugin.triggHistory.triggerCompleteMessage = Trigger {1}.{0} completed firing job {6}.{5} at {4, date, HH\:mm\:ss MM/dd/yyyy} with resulting trigger instruction code\: {9}  
#配置job调度插件  quartz_jobs(jobs and triggers内容)的XML文档

#加载 Job 和 Trigger 信息的类   (1.8之前用:org.quartz.plugins.xml.JobInitializationPlugin)
#org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin

#指定存放调度器(Job 和 Trigger)信息的xml文件,默认是classpath下quartz_jobs.xml
#org.quartz.plugin.jobInitializer.fileNames = my_quartz_job2.xml
#org.quartz.plugin.jobInitializer.failOnFileNotFound = true
#自动扫描任务单并发现改动的时间间隔,单位为秒。设置为0表示不自动加载
#org.quartz.plugin.jobInitializer.scanInterval = 10
#覆盖任务调度器中同名的jobDetail,避免只修改了CronExpression所造成的不能重新生效情况
#org.quartz.plugin.jobInitializer.wrapInUserTransaction = false


# ===========================================================================
# Sample configuration of ShutdownHookPlugin  ShutdownHookPlugin插件的配置样例?
# ===========================================================================
#org.quartz.plugin.shutdownhook.class = \org.quartz.plugins.management.ShutdownHookPlugin
#org.quartz.plugin.shutdownhook.cleanShutdown = true

#
# Configure RMI Settings 远程服务调用配置
#
#如果你想quartz-scheduler出口本身通过RMI作为服务器,然后设置“出口”标志true(默认值为false)。
#org.quartz.scheduler.rmi.export = false

#主机上rmi注册表(默认值localhost)
#org.quartz.scheduler.rmi.registryhost = localhost
#注册监听端口号(默认值1099)
#org.quartz.scheduler.rmi.registryport = 1099

#创建rmi注册,false/never:如果你已经有一个在运行或不想进行创建注册
# true/as_needed:第一次尝试使用现有的注册,然后再回来进行创建
# always:先进行创建一个注册,然后再使用回来使用注册
#org.quartz.scheduler.rmi.createregistry = never

#Quartz Scheduler服务端端口,默认是随机分配RMI注册表
#org.quartz.scheduler.rmi.serverport = 1098
#true:链接远程服务调度(客户端),这个也要指定registryhost和registryport,默认为false

# 如果export和proxy同时指定为true,则export的设置将被忽略
#org.quartz.scheduler.rmi.proxy = false

3、自定义配置类:

import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import javax.sql.DataSource;
import java.io.IOException;
import java.util.Properties;

/**
 * 〈一句话功能简述〉<br>
 *
 * @author dmf
 * @create 2022/11/7
 * @since 1.0.0
 */
@Configuration
public class QuartzConfig {
    @Bean
    public Properties quartzProperties() throws IOException {
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        // 对quartz.properties文件进行读取
        propertiesFactoryBean.setLocation(new ClassPathResource("/quartz/quartz.properties"));
        // 在quartz.properties中的属性被读取并注入后再初始化对象
        propertiesFactoryBean.afterPropertiesSet();
        return propertiesFactoryBean.getObject();
    }

    @Bean
    public SchedulerFactoryBean quartzScheduler(DataSource dataSource,Properties quartzProperties) throws IOException {
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        schedulerFactoryBean.setQuartzProperties(quartzProperties);
        schedulerFactoryBean.setDataSource(dataSource);
        // 延时启动
        schedulerFactoryBean.setStartupDelay(1);
        schedulerFactoryBean.setApplicationContextSchedulerContextKey("applicationContextKey");
        // 可选,QuartzScheduler
        // 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
        schedulerFactoryBean.setOverwriteExistingJobs(true);
        // 设置自动启动,默认为true
        schedulerFactoryBean.setAutoStartup(true);
        return schedulerFactoryBean;
    }

}

4、其他配置。
application.yml配置:主要配置数据源相关。

server:
  servlet:
    context-path: /demo
  port: 8080

spring:
  datasource:
    # 数据源基本配置
    username: root
    password: root1234
    url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
    # driver-class需要注意mysql驱动的版本(com.mysql.cj.jdbc.Driver 或 com.mysql.jdbc.Driver)
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    # Druid的其他属性配置
    druid:
      # 初始化时建立物理连接的个数
      initial-size: 10
      # 连接池的最小空闲数量
      min-idle: 5
      # 连接池最大连接数量
      max-active: 20
      # 获取连接时最大等待时间,单位毫秒
      max-wait: 60000
      # 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
      test-while-idle: true
      # 既作为检测的间隔时间又作为testWhileIdel执行的依据
      time-between-eviction-runs-millis: 60000
      # 销毁线程时检测当前连接的最后活动时间和当前时间差大于该值时,关闭当前连接(配置连接在池中的最小生存时间)
      min-evictable-idle-time-millis: 30000
      # 用来检测数据库连接是否有效的sql 必须是一个查询语句(oracle中为 select 1 from dual)
      validation-query: SELECT 1 FROM DUAL
      # 申请连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
      test-on-borrow: false
      # 归还连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
      test-on-return: false
      # 是否缓存preparedStatement, 也就是PSCache,PSCache对支持游标的数据库性能提升巨大,比如说oracle,在mysql下建议关闭。
      pool-prepared-statements: false
      # 置监控统计拦截的filters,去掉后监控界面sql无法统计,stat: 监控统计、Slf4j:日志记录、waLL: 防御sqL注入
      filters: stat,wall,slf4j
      # 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
      max-pool-prepared-statement-per-connection-size: -1
      # 合并多个DruidDataSource的监控数据
      use-global-data-source-stat: true
      # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
      connect-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
      web-stat-filter:
        # 是否启用StatFilter默认值true
        enabled: true
        # 添加过滤规则
        url-pattern: /*
        # 忽略过滤的格式
        exclusions: /druid/*,*.js,*.gif,*.jpg,*.png,*.css,*.ico

      stat-view-servlet:
        # 是否启用StatViewServlet默认值true
        enabled: true
        # 访问路径为/druid时,跳转到StatViewServlet
        url-pattern: /druid/*
        # 是否能够重置数据
        reset-enable: false
        # 需要账号密码才能访问控制台,默认为root
        login-username: root
        login-password: 123456
        # IP白名单
        allow: 127.0.0.1
        # IP黑名单(共同存在时,deny优先于allow)
        deny:

到这quartz算是配置好了。我们就可以在代码里使用@Autowired注入使用了。
注意:配置类里@Bean配置的是一个FactoryBean类(SchedulerFactoryBean),但是在代码里可以直接注入SchedulerFactoryBean,实际上拿到的是一个Scheduler对象。
代码示例:
定义Job类

public class SimpleJob implements Job {
    public SimpleJob() {
    }
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
       System.out.println("Hello Job!");
    }
}

通过注入Scheduler,就可以使用quartz的定时任务了

@Service
public class QuartzServiceImpl implements QuartzService {
    @Autowired
    @Qualifier("quartzScheduler")
    private Scheduler scheduler;
    @Override
    public void addJob(String jobName) {
        Date startTime = nextGivenSecondDate(null, 15);
        JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class).withIdentity(jobName,"group1").build();

        SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1","group1")
                .startAt(startTime).withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(10)
                .withRepeatCount(3)).build();

        try {
            scheduler.scheduleJob(jobDetail,trigger);
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
}

上例只是注册了一个简单的定时任务。本文章只讲解Spring Boot整合Quartz,对于quartz的详细使用方法,请自行百度或者去quartz官网。
官网:http://quartz-scheduler.org/
学习文档:http://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/
例子:http://www.quartz-scheduler.org/documentation/quartz-2.3.0/examples/
spring集成官网:http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/scheduling.html#scheduling-quartz

二、使用SpringBoot自动配置类

Spring Boot定义了Quartz的自动配置类QuartzAutoConfiguration,我们需要使用quartz时,可以只需要添加相关配置即可。
application.yml

server:
  servlet:
    context-path: /demo
  port: 8080

spring:
  datasource:
    # 数据源基本配置
    username: root
    password: root1234
    url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
    # driver-class需要注意mysql驱动的版本(com.mysql.cj.jdbc.Driver 或 com.mysql.jdbc.Driver)
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    # Druid的其他属性配置
    druid:
      # 初始化时建立物理连接的个数
      initial-size: 10
      # 连接池的最小空闲数量
      min-idle: 5
      # 连接池最大连接数量
      max-active: 20
      # 获取连接时最大等待时间,单位毫秒
      max-wait: 60000
      # 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
      test-while-idle: true
      # 既作为检测的间隔时间又作为testWhileIdel执行的依据
      time-between-eviction-runs-millis: 60000
      # 销毁线程时检测当前连接的最后活动时间和当前时间差大于该值时,关闭当前连接(配置连接在池中的最小生存时间)
      min-evictable-idle-time-millis: 30000
      # 用来检测数据库连接是否有效的sql 必须是一个查询语句(oracle中为 select 1 from dual)
      validation-query: SELECT 1 FROM DUAL
      # 申请连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
      test-on-borrow: false
      # 归还连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
      test-on-return: false
      # 是否缓存preparedStatement, 也就是PSCache,PSCache对支持游标的数据库性能提升巨大,比如说oracle,在mysql下建议关闭。
      pool-prepared-statements: false
      # 置监控统计拦截的filters,去掉后监控界面sql无法统计,stat: 监控统计、Slf4j:日志记录、waLL: 防御sqL注入
      filters: stat,wall,slf4j
      # 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
      max-pool-prepared-statement-per-connection-size: -1
      # 合并多个DruidDataSource的监控数据
      use-global-data-source-stat: true
      # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
      connect-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
      web-stat-filter:
        # 是否启用StatFilter默认值true
        enabled: true
        # 添加过滤规则
        url-pattern: /*
        # 忽略过滤的格式
        exclusions: /druid/*,*.js,*.gif,*.jpg,*.png,*.css,*.ico

      stat-view-servlet:
        # 是否启用StatViewServlet默认值true
        enabled: true
        # 访问路径为/druid时,跳转到StatViewServlet
        url-pattern: /druid/*
        # 是否能够重置数据
        reset-enable: false
        # 需要账号密码才能访问控制台,默认为root
        login-username: root
        login-password: 123456
        # IP白名单
        allow: 127.0.0.1
        # IP黑名单(共同存在时,deny优先于allow)
        deny:

  quartz:
    #相关属性配置
    properties:
      org:
        quartz:
          scheduler:
            instanceName: testScheduler
            instanceId: AUTO

          jobStore:
            # 默认存储在内存中,RAMJobStore快速轻便,但是当进程终止时,所有调度信息都会丢失;
            #此处配置通过事务存储数据库;2.5.6版本之后,配置JobStoreTX要报错,调整配置
            class: org.springframework.scheduling.quartz.LocalDataSourceJobStore
            #            class: org.springframework.scheduling.quartz.LocalDataSourceJobStore
            #您需要为JobStore选择一个DriverDelegate才能使用。DriverDelegate负责执行特定数据库可能需要的任何JDBC工作
            # StdJDBCDelegate是一个使用“vanilla”JDBC代码(和SQL语句)来执行其工作的委托,用于完全符合JDBC的驱动程序
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
            #表前缀
            tablePrefix: QRTZ_
            #数据源别名,自定义
            dataSource: dataSource1
            #是否加入集群(集群时,一个任务只有一个服务实例执行)
            #设置为“true”以打开群集功能。如果您有多个Quartz实例使用同一组数据库表,则此属性必须设置为“true”,否则您将遇到破坏
            #isClustered: true
            #调度实例失效的检查时间间隔
            clusterCheckinInterval: 10000
            #可以将“org.quartz.jobStore.useProperties”配置参数设置为“true”(默认为false),以指示JDBCJobStore将JobDataMaps中的所有值都作为字符串,
            #因此可以作为名称 - 值对存储而不是在BLOB列中以其序列化形式存储更多复杂的对象。从长远来看,这是更安全的,因为您避免了将非String类序列化为BLOB的类版本问题
            useProperties: true
          # quartz线程池配置
          threadPool:
            #实例化ThreadPool时,使用的线程类为SimpleThreadPool
            class: org.quartz.simpl.SimpleThreadPool
            #threadCount和threadPriority将以setter的形式注入ThreadPool实例
            #并发个数:如果只有几个工作每天触发几次 那么1个线程就可以,如果有成千上万的工作,每分钟都有很多工作 那么就需要50-100之间.
            #只有1到100之间的数字是非常实用的
            threadCount: 10
            #优先级 默认值为5
            threadPriority: 5
            #可以是“true”或“false”,默认为false
            threadsInheritContextClassLoaderOfInitializingThread: true

    #数据库方式jdbc或memory
    job-store-type: jdbc
    # 关闭系统的时候,等待定时任务完成
    wait-for-jobs-to-complete-on-shutdown: true
    # 初始化后是否自动启动计划程序
    auto-startup: true
    # 延迟启动
    startup-delay: 5s
    #jdbc:
      # SQL 初始化脚本中单行注释的前缀
      #comment-prefix: --
      # 数据库架构初始化模式--never 从不进行初始化,always 每次都清空数据库进行初始化,embedded 只初始化内存数据库(默认值)
      #initialize-schema: always
      # 用于初始化数据库架构的SQL文件的路径
      #schema: classpath:database/mysql.sql

QuartzAutoConfiguration源码:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.boot.autoconfigure.quartz;

import java.util.Map;
import java.util.Properties;
import javax.sql.DataSource;
import org.quartz.Calendar;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.autoconfigure.sql.init.OnDatabaseInitializationCondition;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
import org.springframework.transaction.PlatformTransactionManager;

@AutoConfiguration(
    after = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class, LiquibaseAutoConfiguration.class, FlywayAutoConfiguration.class}
)
@ConditionalOnClass({Scheduler.class, SchedulerFactoryBean.class, PlatformTransactionManager.class})
@EnableConfigurationProperties({QuartzProperties.class})
public class QuartzAutoConfiguration {
    public QuartzAutoConfiguration() {
    }

    @Bean
    @ConditionalOnMissingBean
    public SchedulerFactoryBean quartzScheduler(QuartzProperties properties, ObjectProvider<SchedulerFactoryBeanCustomizer> customizers, ObjectProvider<JobDetail> jobDetails, Map<String, Calendar> calendars, ObjectProvider<Trigger> triggers, ApplicationContext applicationContext) {
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        SpringBeanJobFactory jobFactory = new SpringBeanJobFactory();
        jobFactory.setApplicationContext(applicationContext);
        schedulerFactoryBean.setJobFactory(jobFactory);
        if (properties.getSchedulerName() != null) {
            schedulerFactoryBean.setSchedulerName(properties.getSchedulerName());
        }

        schedulerFactoryBean.setAutoStartup(properties.isAutoStartup());
        schedulerFactoryBean.setStartupDelay((int)properties.getStartupDelay().getSeconds());
        schedulerFactoryBean.setWaitForJobsToCompleteOnShutdown(properties.isWaitForJobsToCompleteOnShutdown());
        schedulerFactoryBean.setOverwriteExistingJobs(properties.isOverwriteExistingJobs());
        if (!properties.getProperties().isEmpty()) {
            schedulerFactoryBean.setQuartzProperties(this.asProperties(properties.getProperties()));
        }

        schedulerFactoryBean.setJobDetails((JobDetail[])jobDetails.orderedStream().toArray((x$0) -> {
            return new JobDetail[x$0];
        }));
        schedulerFactoryBean.setCalendars(calendars);
        schedulerFactoryBean.setTriggers((Trigger[])triggers.orderedStream().toArray((x$0) -> {
            return new Trigger[x$0];
        }));
        customizers.orderedStream().forEach((customizer) -> {
            customizer.customize(schedulerFactoryBean);
        });
        return schedulerFactoryBean;
    }

    private Properties asProperties(Map<String, String> source) {
        Properties properties = new Properties();
        properties.putAll(source);
        return properties;
    }

    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnSingleCandidate(DataSource.class)
    @ConditionalOnProperty(
        prefix = "spring.quartz",
        name = {"job-store-type"},
        havingValue = "jdbc"
    )
    @Import({DatabaseInitializationDependencyConfigurer.class})
    protected static class JdbcStoreTypeConfiguration {
        protected JdbcStoreTypeConfiguration() {
        }

        @Bean
        @Order(0)
        public SchedulerFactoryBeanCustomizer dataSourceCustomizer(QuartzProperties properties, DataSource dataSource, @QuartzDataSource ObjectProvider<DataSource> quartzDataSource, ObjectProvider<PlatformTransactionManager> transactionManager, @QuartzTransactionManager ObjectProvider<PlatformTransactionManager> quartzTransactionManager) {
            return (schedulerFactoryBean) -> {
                DataSource dataSourceToUse = this.getDataSource(dataSource, quartzDataSource);
                schedulerFactoryBean.setDataSource(dataSourceToUse);
                PlatformTransactionManager txManager = this.getTransactionManager(transactionManager, quartzTransactionManager);
                if (txManager != null) {
                    schedulerFactoryBean.setTransactionManager(txManager);
                }

            };
        }

        private DataSource getDataSource(DataSource dataSource, ObjectProvider<DataSource> quartzDataSource) {
            DataSource dataSourceIfAvailable = (DataSource)quartzDataSource.getIfAvailable();
            return dataSourceIfAvailable != null ? dataSourceIfAvailable : dataSource;
        }

        private PlatformTransactionManager getTransactionManager(ObjectProvider<PlatformTransactionManager> transactionManager, ObjectProvider<PlatformTransactionManager> quartzTransactionManager) {
            PlatformTransactionManager transactionManagerIfAvailable = (PlatformTransactionManager)quartzTransactionManager.getIfAvailable();
            return transactionManagerIfAvailable != null ? transactionManagerIfAvailable : (PlatformTransactionManager)transactionManager.getIfUnique();
        }

        @Bean
        @ConditionalOnMissingBean({QuartzDataSourceScriptDatabaseInitializer.class, QuartzDataSourceInitializer.class})
        @Conditional({QuartzAutoConfiguration.JdbcStoreTypeConfiguration.OnQuartzDatasourceInitializationCondition.class})
        public QuartzDataSourceScriptDatabaseInitializer quartzDataSourceScriptDatabaseInitializer(DataSource dataSource, @QuartzDataSource ObjectProvider<DataSource> quartzDataSource, QuartzProperties properties) {
            DataSource dataSourceToUse = this.getDataSource(dataSource, quartzDataSource);
            return new QuartzDataSourceScriptDatabaseInitializer(dataSourceToUse, properties);
        }

        static class OnQuartzDatasourceInitializationCondition extends OnDatabaseInitializationCondition {
            OnQuartzDatasourceInitializationCondition() {
                super("Quartz", new String[]{"spring.quartz.jdbc.initialize-schema"});
            }
        }
    }
}

QuartzAutoConfiguration帮我们注入了一个SchedulerFactoryBean,使用@Autowired注入即可(同上)。
quartz自带的建表sql可以在 org.quartz-scheduler:quartzjar包下的org.quartz.impl.jdbcjobstore包下找到。
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值