由于希望可以在集群环境中运行定时job,但考虑到多个job实例有可能带来job重复执行的问题,新项目的job打算从原生的spring task实现改成quartz job实现,并采用jdbc的存储方式。

如果是把quartz的表初始化到原先springboot配置的同一个数据库,并没有太多问题,但考虑到这样做会在业务表中插入很多不相关的表,决定把quartz的表建在单独的一个库中。查了quartz和springboot文档,quartz中的配置

org.quartz.jobStore.dataSource=NAME

org.quartz.dataSource.NAME.driver
org.quartz.dataSource.NAME.URL
org.quartz.dataSource.NAME.user
org.quartz.dataSource.NAME.password
org.quartz.dataSource.NAME.maxConnections
org.quartz.dataSource.NAME.validationQuery
org.quartz.dataSource.NAME.validateOnCheckout
org.quartz.dataSource.NAME.discardIdleConnectionsSeconds

但集成到springboot中,在application.yml用了自己的配置

By default, an in-memory JobStore is used. However, it is possible to configure a JDBC-based store if a DataSource bean is available in your application and if the spring.quartz.job-store-type property is configured accordingly, as shown in the following example:

spring.quartz.job-store-type=jdbc
When the JDBC store is used, the schema can be initialized on startup, as shown in the following example: spring.quartz.jdbc.initialize-schema=always

Advanced Quartz configuration properties can be customized using spring.quartz.properties.*.

查了些资料后,application.yml配置如下

spring:
redis:
host: localhost
database: 2
password: guanlouyi
port: 6399
datasource:
url: jdbc:mysql://192.168.40.241:3306/fintech_public?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
username: root
password: 20.112@,l
driver-class-name: com.mysql.jdbc.Driver
quartz:
job-store-type: jdbc
jdbc:
initialize-schema: always
properties:
org:
quartz:
dataSource:
quartzDS:
driver: com.mysql.jdbc.Driver
URL: jdbc:mysql://192.168.40.241:3306/fintech_quartz?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
user: root
password: 20.112@,l
scheduler:
instanceName: clusteredScheduler
instanceId: AUTO
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
dataSource: quartzDS
tablePrefix: QRTZ_
isClustered: true
clusterCheckinInterval: 10000
useProperties: false
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true

但是这样配置的datasouce并不生效,用的还是原来的数据库。查了些网上的资料,要给scheduler单独的dataSource,而且发现springboot文档里有

To have Quartz use a DataSource other than the application’s main DataSource, declare a DataSource bean, annotating its @Bean method with @QuartzDataSource. Doing so ensures that the Quartz-specific DataSource is used by both the SchedulerFactoryBean and for schema initialization.

于是application.yml改成(spring.datasource去掉改成@Bean@Primary形式,不这样会报同时存在两个dataSrouce,然后把quartz.dataSource的配置去掉了,加@QuartzDataSource注入:自以为)

spring:
redis:
host: localhost
database: 2
password: guanlouyi
port: 6399
quartz:
job-store-type: jdbc
jdbc:
initialize-schema: never
properties:
org:
quartz:
dataSource:
scheduler:
instanceName: clusteredScheduler
instanceId: AUTO
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
tablePrefix: QRTZ_
isClustered: false
clusterCheckinInterval: 10000
useProperties: true
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true datasource:
primary:
url: jdbc:mysql://192.168.40.241:3306/fintech_public?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
username: root
password: 20.112@,l
driver-class-name: com.mysql.jdbc.Driver
scheduler:
url: jdbc:mysql://192.168.40.241:3306/fintech_quartz
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver

代码加上DataSourceConfig

    @Bean
@Primary
@ConfigurationProperties(prefix = "datasource.primary")
public DataSourceProperties primaryDataSourceProperties() {
return new DataSourceProperties();
} @Bean
@ConfigurationProperties(prefix = "datasource.scheduler")
public DataSourceProperties quartzDataSourceProperties() {
return new DataSourceProperties();
} @Bean(name = "primaryDataSource")
public DataSource primaryDataSource() {
return primaryDataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class).build();
} @Bean(name = "quartzDataSource")
@ConfigurationProperties(prefix = "datasource.scheduler")
@QuartzDataSource
public DataSource quartzDataSource() {
DataSource datasource = quartzDataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class)
.build();
return datasource;
}

启动报错:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'adminEventsMapper' defined in file [E:\git\fintech-parent\fintech-microservice-dao\target\classes\com\panshi\fintech\microservice\dao\mapper\AdminEventsMapper.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required

分析:可能是把spring.datasource去掉,用@Bean和@Primary的形式生成的DataSource顺序发生了改变,导致sqlSessionFactory和sqlSessionTemplate没有生成,mybatis的Mapper初始化时没有找到,在Mapper注入的地方加上@Lazy可以解决,但不打算采用此方法。后来网上看到有人也自己初始化sqlSessionFactory和sqlSessionTemplate,于是加上:

    /**
* 创建 SqlSessionFactory
*/
@Bean(name = "sqlSessionFactory")
@Primary
public SqlSessionFactory primarySqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
// bean.setMapperLocations(new
// PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/db1/*.xml"));
return bean.getObject();
} @Bean(name = "sqlSessionTemplate")
@Primary
public SqlSessionTemplate primarySqlSessionTemplate(
@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}

这个问题解决,但又出现另一个问题:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'quartzScheduler' defined in class path resource [org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.class]: Invocation of init method failed; nested exception is org.quartz.SchedulerConfigException: DataSource name not set.

后来折腾了老半天,还是把dataSource加回application.yml

eureka:
client:
serviceUrl:
defaultZone: http://localhost:8762/eureka
logging:
path: /opt
level:
ROOT: DEBUG
com.panshi.fintech: DEBUG
spring:
redis:
host: localhost
database: 2
password: guanlouyi
port: 6399
quartz:
job-store-type: jdbc
jdbc:
initialize-schema: always
properties:
org:
quartz:
dataSource:
quartzDataSource:
driver: com.mysql.jdbc.Driver
URL: jdbc:mysql://192.168.40.241:3306/fintech_quartz
user: root
password: 20.112@,l
scheduler:
instanceName: clusteredScheduler
instanceId: AUTO
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
tablePrefix: QRTZ_
isClustered: false
dataSource: quartzDataSource
clusterCheckinInterval: 10000
useProperties: true
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true
datasource:
primary:
url: jdbc:mysql://192.168.40.241:3306/fintech_public?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
username: root
password: 20.112@,l
driver-class-name: com.mysql.jdbc.Driver
scheduler:
url: jdbc:mysql://192.168.40.241:3306/fintech_quartz
username: root
password: 20.112@,l
driver-class-name: com.mysql.jdbc.Driver
file:
path: /opt
access-path: http://localhost
swagger:
enabled: true

原来这个配置还是需要的,但同时还要@Bean生成schedule的dataSource,同时加上

@QuartzDataSource

springboot 2.x 集成quartz持久化到一个单独的dataSource时遇到的坑的更多相关文章

  1. 记录一个修改application.properties时遇到的坑

    有一个需求是会频繁修改配置文件中的常量,为了方便就会用unzip解压war包,修改propertites中的值后重新打war 包,部署,但是发现修改的值没有起作用,,一直在纠结...后来发现其实在编译 ...

  2. SpringBoot 1.5.x 集成 Quartz 任务调度框架

    Quartz 有分 内存方式 和 数据库方式 内存方式任务信息保存在内存中, 停机会丢失, 需手动重新执行, 数据库方式: 任务信息保存在数据库中, 重点是支持集群. 内存方式 RAMJobStore ...

  3. SpringBoot集成Quartz(解决@Autowired空指针Null问题即依赖注入的属性为null)

    使用spring-boot作为基础框架,其理念为零配置文件,所有的配置都是基于注解和暴露bean的方式. Quartz的4个核心概念: 1.Job表示一个工作,要执行的具体内容.此接口中只有一个方法v ...

  4. SpringBoot集成Quartz实现定时任务

    1 需求 在我的前后端分离的实验室管理项目中,有一个功能是学生状态统计.我的设计是按天统计每种状态的比例.为了便于计算,在每天0点,系统需要将学生的状态重置,并插入一条数据作为一天的开始状态.另外,考 ...

  5. SpringBoot定时任务 - 集成quartz实现定时任务(单实例和分布式两种方式)

    最为常用定时任务框架是Quartz,并且Spring也集成了Quartz的框架,Quartz不仅支持单实例方式还支持分布式方式.本文主要介绍Quartz,基础的Quartz的集成案例本,以及实现基于数 ...

  6. springboot自带定时任务和集成quartz

    1,springboot自带的定时任务  默认是单线程 有这个依赖就可以 <dependency> <groupId>org.springframework.boot</ ...

  7. SpringBoot整合任务调度框架Quartz及持久化配置

    目录 本篇要点 SpringBoot与Quartz单机版快速整合 引入依赖 创建Job 调度器Scheduler绑定 自动配置,这里演示SimpleScheduleBuilder 手动配置,这里演示C ...

  8. quartz的持久化任务调度使用应用的dataSource

    Quartz提供两种基本作业存储类型--->第一种类型叫做RAMJobStore:     最佳的性能,因为内存中数据访问最快     不足之处是缺乏数据的持久性,当程序路途停止或系统崩溃时,所 ...

  9. SpringBoot12 QueryDSL01之QueryDSL介绍、springBoot项目中集成QueryDSL

    1 QueryDSL介绍 1.1 背景 QueryDSL的诞生解决了HQL查询类型安全方面的缺陷:HQL查询的扩展需要用字符串拼接的方式进行,这往往会导致代码的阅读困难:通过字符串对域类型和属性的不安 ...

  10. SpringBoot(十)_springboot集成Redis

    Redis 介绍 Redis是一款开源的使用ANSI C语言编写.遵守BSD协议.支持网络.可基于内存也可持久化的日志型.Key-Value高性能数据库. 数据模型 Redis 数据模型不仅与关系数据 ...

随机推荐

  1. yarn serve 开启项目服务失败 assets emit different content to the same filename

    error: answer: 删除public的文件,重新 yarn serve :

  2. Cookie、sessionStorage、localStorage的区别 ?

    共同点:都是保存在浏览器端的. 区别: 1.cookie数据始终携带在同源的http请求中,即cookie在浏览器和服务器间来回传递,而sessionStorage和Localstorage不会自动把 ...

  3. 《使用Gin框架构建分布式应用》阅读笔记:p1-p19

    <使用Gin框架构建分布式应用>学习第1天,p1-p19总结,总计19页. 一.技术总结 1.go get & go install 执行go get 或者 go install ...

  4. KubeSphere 社区双周报 | FluentBit 新增 tcp 输入插件 | 2023.09.29-10.12

    KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书.新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列 ...

  5. OpenFunction 应用系列之一: 以 Serverless 的方式实现 Kubernetes 日志告警

    概述 当我们将容器的日志收集到消息服务器之后,我们该如何处理这些日志?部署一个专用的日志处理工作负载可能会耗费多余的成本,而当日志体量骤增.骤降时亦难以评估日志处理工作负载的待机数量.本文提供了一种基 ...

  6. 数据运算中关于字符串""的拼接问题

    例子中准备了3种类型数据,分别针对是否在运算存在空字符串参与运算进行了演示,结果如下: 1 int x = 10; 2 double y = 20.2; 3 long z = 10L; 4 Syste ...

  7. LeetCode题目练习记录 _数组和链表03 _20211011

    LeetCode题目练习记录 _数组和链表03 _20211011 206. 反转链表 难度简单2015收藏分享切换为英文接收动态反馈 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表 ...

  8. Next.js 深度教程:服务端渲染、静态生成到增量静态再生 | 2024最新版

    优化字体和图像 书接上回,我们学习了如何设计Next.js应用程序,让我们继续优化主页和添加自定义字体.图像. 在网站设计中,字体扮演着关键角色,然而,若需获取并加载字体文件,项目中引入自定义字体可能 ...

  9. 4.3 Linux压缩文件或目录为.zip格式(zip命令)

    我们经常会在 Windows 系统上使用 ".zip"格式压缩文件,其实".zip"格式文件是 Windows 和 Linux 系统都通用的压缩文件类型,属于几 ...

  10. 接口测试中Groovy引擎的接入实现!

    接口测试中Groovy可以作为上下游接口参数化传递的前置脚本和后置脚本使用,无缝衔接Java语法,groovy的引入对于动态参数化的设置方便很多. 其中核心部分就是接入groovy的引擎,下面介绍gr ...