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

news2024/11/26 2:42:36

一、自定义配置类

不使用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包下找到。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/143686.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android---Toolbar

目录 Toolbar Toolbar 加上 menu Toolbar 设置 Theme 完整 Demo Toolbar Toolbar 是在 Android 5.0 开始推出的一个 Materal Design 风格的导航控件 &#xff0c;Google 非常推荐大家使用 Toobar 来作为 Android 客户端的导航栏&#xff0c;以此来取代之前的 Actionbar。与 …

联想昭阳E4电脑U盘安装Win10系统操作教学

联想昭阳E4电脑U盘安装Win10系统操作教学分享。有用户想要将自己的联想昭阳E4电脑重装到Win10系统来使用。那么今天教大家一个U盘重装系统的方法&#xff0c;使用这个方法能够在系统出现问题的时候进行系统的重置&#xff0c;解决系统问题。一起来看看具体的重装教学吧。 准备工…

Exynos_4412——PWM实验

目录 一、PWM简介 1.1蜂鸣器工作原理 有源蜂鸣器 无源蜂鸣器 1.2使用GPIO控制 1.3PWM控制 1.4PWM参数 周期​ 占空比 二、Exynos_4412下的PWM控制器 三、PWM寄存器详解 四、PWM编程 一、PWM简介 1.1蜂鸣器工作原理 有源蜂鸣器 有源蜂鸣器只要接上额定电源就可以发…

主流的4种跨隔离网文件摆渡方式对比介绍

网络上承载了太多企业的业务&#xff0c;其安全性一定要得到保障&#xff0c;所以很多企业和机构都会选择将网络进行隔离划分&#xff0c;比如内外网隔离&#xff0c;办公网、研发网隔离等&#xff0c;也有不少企业会选择用云桌面的形式。 然而网络的建设就是为了互通的&#x…

【学vue跟玩一样】快速搞懂vue渲染

Vue的渲染分为条件渲染和列表渲染&#xff0c;那究竟什么式渲染呢?1.条件渲染1.v-if写法:(1)v-if"表达式"(2)v-else-if"表达式"(3)v-else"表达式"&#xff08;和我们曾经学过的JavaScript里面的if语句几乎一样&#xff09;适用于:切换频率较低的…

React umi中使用sass

umi默认支持less和css&#xff0c;如果想要使用sass&#xff0c;需要安装插件以及配置 一、安装umi的sass插件 yarn add umijs/plugin-sass 二、安装sass依赖 yarn add sass-loader node-sass 三、配置sass 在config/config.js或者 .umirc.ts文件中配置如下&#xff1a; sa…

linux 卸载elasticsearch及安装elasticsearch8.5(rpm)

目录 卸载elasticsearch rpm安装elasticsearch8.5 卸载elasticsearch # 检查elasticsearch服务状态 systemctl status elasticsearch.service; # 停止elasticsearch服务状态 systemctl stop elasticsearch.service; # 剔除elasticsearch服务 systemctl disable elasticsea…

宏任务和微任务JS执行顺序题目+总结

宏任务和微任务 resolve&#xff08;传的参数&#xff09;标记成功&#xff0c;会调用promise.then 练习网站&#xff1a; 关于promise深入理解太长没来及看 博客文章&#xff1a; promise本身是同步的&#xff0c;then/catch的回调函数是异步的 直接做题加深理解 点常见面…

漱玉转债,合力转债上市价格预测

漱玉转债基本信息转债名称&#xff1a;漱玉转债&#xff0c;评级&#xff1a;AA-&#xff0c;发行规模&#xff1a;8.0亿元。正股名称&#xff1a;漱玉平民&#xff0c;今日收盘价&#xff1a;18.1&#xff0c;转股价格&#xff1a;21.27。当前转股价值 转债面值 / 转股价格 *…

2.机器学习问题

2.机器学习问题 监督学习 监督学习&#xff08;supervised learning&#xff09;擅长在“给定输入特征”的情况下预测标签。 每个“特征-标签”对都称为一个_样本_&#xff08;example&#xff09;。 有时&#xff0c;即使标签是未知的&#xff0c;样本也可以指代输入特征。 …

手写RPC框架04-过滤器模块实现

源代码地址&#xff1a;https://github.com/lhj502819/IRpc/tree/v5 系列文章&#xff1a; 注册中心模块实现路由模块实现序列化模块实现过滤器模块实现自定义SPI机制增加框架的扩展性的设计与实现 为什么需要过滤器&#xff1f; 目前整个RPC框架的功能基本已经齐全了&…

ArcGIS基础实验操作100例--实验54 Shapfile与Graphic转换

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 高级编辑篇--实验54 Shapfile与Graphic转换 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff…

2022天翼数字科技生态大会 五大亮点看永不落幕的“5G物联生态城”

2022天翼数字科技生态大会&#xff0c;近日于线上隆重开幕。大会首次“云”上绽放&#xff0c;将给我们带来一场怎样的科技盛宴&#xff1f; 本次大会&#xff0c;中国电信天翼物联以“智启物联未来”为主题&#xff0c;运用“元宇宙”VR技术&#xff0c;打造虚拟世界中的“5G物…

Netty 创建高性能聊天室 单聊 群聊 websocket

目录 一、简单实现Netty发送消息的案例 二、websocket连接注册用户 三、实现单聊 四、群聊功能 五、案例代码 一、简单实现Netty发送消息的案例 案例一的依赖有&#xff1a;若没springboot项目有自动对应版本&#xff0c;其他版本可以使用maven仓库的最新版本。 <depe…

img的应用

我的目的是&#xff0c;因为图片足够的大&#xff0c;我想让它在一个小盒子里居中显示&#xff0c;所以我这样做了&#xff1a;<style>.text{width: 375px;height: 100px;} </style> <body><div class"text"><img src"./img/5.png&q…

企业为什么要利用数据中台进行数字化转型?_光点科技

近两年“数字化”已经悄悄的替代了“信息化”。那么什么是“企业的数字化转型”&#xff1f;数字化转型是企业战略层面的概念&#xff0c;它并不是追求眼前效益的机灵战术&#xff0c;其本质&#xff0c;是用数字化技术对业务的重构、流程的重构和组织的重构&#xff0c;目的是…

云呐|什么是固定资产?什么是流动资产

什么是固定资产&#xff1f;什么是流动资产&#xff0c;  1、固定资产  属于产品生产过程中用来改变或者影响劳动对象的劳动资料&#xff0c;是固定资本的实物形态固定资产在生产过程中可以长期发挥作用&#xff0c;长期保持原有的实物形态&#xff0c;但其价值则随着企业生…

自己centos7系统制作iso镜像,并新建虚拟机

一、自己centos7系统制作iso镜像 1. 前置工作 将系统安全配置 SELINUX 改为 disabled&#xff0c;否则制作好的镜像无法登陆&#xff01;&#xff01;&#xff01; vim /etc/selinux/config # 将其从 enforcing 改为 disabled SELINUXdisabled2.安装 mondo rescue cd /etc…

正则表达式的使用

什么是正则表达式 正则表达式&#xff0c;又称规则表达式,&#xff08;Regular Expression&#xff0c;在代码中常简写为regex、regexp或RE&#xff09;&#xff0c;是一种文本模式&#xff0c;包括普通字符&#xff08;例如&#xff0c;a 到 z 之间的字母&#xff09;和特殊字…

使用VC时一些容易犯的错误

本文迁移自本人网易博客&#xff0c;写于2011年1月13日&#xff0c;使用VC时一些容易犯的错误 - lysygyy的日志 - 网易博客 (163.com)1、在调用其他类中的函数时&#xff0c;需要在当前类中声明一个类对象&#xff0c;但是调用的时候&#xff0c;编译会出错。出现很多符号&…