quartz报错Couldn’t obtain triggers for job:connection closed

运行环境 springboot2.1.1  quarz2.3.0 jdk8 war包运行在tomcat9

11:00:57.624 [http-nio-8082-exec-2] ERROR c.k.f.w.e.GlobalExceptionHandler - [handleException,83] - Couldn't obtain triggers for job: connection closed
org.quartz.JobPersistenceException: Couldn't obtain triggers for job: connection closed
	at org.quartz.impl.jdbcjobstore.JobStoreSupport.getTriggersForJob(JobStoreSupport.java:2190)
	at org.quartz.impl.jdbcjobstore.JobStoreSupport$29.execute(JobStoreSupport.java:2176)
	at org.quartz.impl.jdbcjobstore.JobStoreCMT.executeInLock(JobStoreCMT.java:245)
	at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeWithoutLock(JobStoreSupport.java:3785)
	at org.quartz.impl.jdbcjobstore.JobStoreSupport.getTriggersForJob(JobStoreSupport.java:2173)
	at org.quartz.core.QuartzScheduler.getTriggersOfJob(QuartzScheduler.java:1445)
	at org.quartz.core.QuartzScheduler.deleteJob(QuartzScheduler.java:958)
	at org.quartz.impl.StdScheduler.deleteJob(StdScheduler.java:301)

我出现的原因是因为没注意到项目本身有类继承了SpringBootServletInitializer(springboot war包部署需要继承这个类),然后配置打war包在tomcat部署时给@SpringApplication注解的类也继承了SpringBootServletInitializer.

因此导致tomcat在运行的时候创建了两个ApplicationContext(第二个ApplicationContext的parent是第一个ApplicationContext)

两个ApplicationContext都会创建一个SchedulerFactoryBean并执行afterPropertiesSet初始化Scheduler所以Scheduler会初始化两次,分别放入两个ApplicationContext,在依赖注入的时候会取第一个ApplicationContext里面的Scheduler.

在初始化Scheduler的时候会调用DBConnectionManager.addConnectionProvider往provides里面放入ConnectionProvider

ConnectionProvider是一个可以用来获取数据库连接的对象,provides是一个HashMap

DBConnectionManager是单例,所以对于两次初始化Scheduler用的是同一个实例,所以第二次初始化会把第一次放入provides里面的ConnectionProvider覆盖掉,所以这时如果从DBConnectionManager里面获取数据库连接的话获取到的是第二个ApplicationContext里面的连接

在执行Scheduler的某些方法时会调用JobStoreCMT.executeInLock方法,这个方法会从DBConnectionManager里面获取到数据库连接执行sql,也就是说获取的连接是第二个ApplicationContext的连接

执行完sql的后执行cleanupConnection清理连接,清理逻辑是从ConnectionHolder里面获取连接和当前执行sql的连接比较是否一样,一样就不关闭连接,不一样就关闭连接.而当前执行sql的连接是DBConnectionManager里面的属于第二次初始化Scheduler,而这里ConnectionHolder取到的是第一次初始化的Scheduler里面的连接,比较不一样,所以连接会被关闭。因此后面如果还执行其他sql 获取到的连接就会是一个被关闭的连接,所以就报connection closed(至于ConnectionHolder里面为什么会是第一次初始化的Scheduler里面的连接主要是因为代码Autowired注入的是第一次初始化的Scheduler,具体的可以自己了解)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值