在spring-boot启动期间tomcat数据源不检查有效连接?
Posted
技术标签:
【中文标题】在spring-boot启动期间tomcat数据源不检查有效连接?【英文标题】:tomcat datasource not checking for valid connection during spring-boot start up? 【发布时间】:2016-07-29 19:48:27 【问题描述】:我有两个 spring-boot 应用程序。应用程序 A 正在使用使用 HikariDataSource 数据源配置的 mysql 数据库。应用程序 B 正在使用使用 tomcat 数据源配置的 SQL Server 数据库。
当我为数据库参数提供错误的用户名时,应用程序 A 无法启动并且出现以下异常错误。但是应用程序 B 启动正常,但是当我进行使用数据源的服务调用时,会抛出错误。为什么后者忽略了数据源连接检查?
注意:我有另一个 spring 应用程序(应用程序 C),它使用 tomcat 数据源连接到 SQL SERVER,如果提供了错误的凭据,则会在容器启动期间出错。虽然它不是一个 spring-boot 应用程序
这是我的应用程序 A 数据源配置
@Bean
public DataSource dataSource()
HikariDataSource dataSource = new HikariDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driver"));
dataSource.setJdbcUrl(environment.getRequiredProperty("jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
return dataSource;
应用B数据源配置
import org.apache.tomcat.jdbc.pool.DataSource;
@Bean
public DataSource datasource()
DataSource ds = new DataSource();
ds.setDriverClassName(hostdb_driver);
ds.setUrl(hostdb_url);
ds.setUsername(hostdb_user);
ds.setPassword(pass);
ds.setMaxActive(hostdb_maxActive);
ds.setMaxIdle(hostdb_maxIdle);
ds.setInitialSize(hostdb_initialSize);
ds.setMinIdle(hostdb_minIdle);
ds.setTestOnBorrow(hostdb_testOnBorrow);
ds.setTestWhileIdle(hostdb_testWhileIdle);
ds.setValidationQuery(hostdb_validationQuery);
ds.setRemoveAbandoned(hostdb_removeAbandoned);
ds.setRemoveAbandonedTimeout(hostdb_removeAbandonedTimeout);
ds.setLogAbandoned(hostdb_logAbandoned);
ds.setValidationInterval(hostdb_validationInterval);
return ds;
异常信息:
dg.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_102]
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) [idea_rt.jar:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean]: Factory method 'entityManagerFactory' threw exception; nested exception is com.zaxxer.hikari.pool.PoolInitializationException: Exception during pool initialization
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
... 23 common frames omitted
Caused by: com.zaxxer.hikari.pool.PoolInitializationException: Exception during pool initialization
at com.zaxxer.hikari.pool.BaseHikariPool.initializeConnections(BaseHikariPool.java:544) ~[HikariCP-2.3.8.jar:na]
at com.zaxxer.hikari.pool.BaseHikariPool.<init>(BaseHikariPool.java:171) ~[HikariCP-2.3.8.jar:na]
at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:60) ~[HikariCP-2.3.8.jar:na]
at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:48) ~[HikariCP-2.3.8.jar:na]
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:104) ~[HikariCP-2.3.8.jar:na]
at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) ~[spring-jdbc-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) ~[spring-jdbc-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:338) ~[spring-jdbc-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConnection.isEmbedded(EmbeddedDatabaseConnection.java:139) ~[spring-boot-autoconfigure-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate.getDefaultDdlAuto(JpaProperties.java:198) ~[spring-boot-autoconfigure-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate.getOrDeduceDdlAuto(JpaProperties.java:186) ~[spring-boot-autoconfigure-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate.getAdditionalProperties(JpaProperties.java:165) ~[spring-boot-autoconfigure-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate.access$000(JpaProperties.java:126) ~[spring-boot-autoconfigure-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.getHibernateProperties(JpaProperties.java:123) ~[spring-boot-autoconfigure-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration.getVendorProperties(HibernateJpaAutoConfiguration.java:99) ~[spring-boot-autoconfigure-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.entityManagerFactory(JpaBaseConfiguration.java:115) ~[spring-boot-autoconfigure-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$425788ff.CGLIB$entityManagerFactory$5(<generated>) ~[spring-boot-autoconfigure-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$425788ff$$FastClassBySpringCGLIB$$cee5d89e.invoke(<generated>) ~[spring-boot-autoconfigure-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) ~[spring-core-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:356) ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$425788ff.entityManagerFactory(<generated>) ~[spring-boot-autoconfigure-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_102]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_102]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_102]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_102]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
... 24 common frames omitted
Caused by: java.sql.SQLException: Access denied for user 'foobar'@'localhost' (using password: YES)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:998) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3835) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3771) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:870) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1659) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1206) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2239) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2270) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2069) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:794) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:44) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_102]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_102]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_102]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_102]
at com.mysql.jdbc.Util.handleNewInstance(Util.java:389) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:399) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:325) ~[mysql-connector-java-5.1.35.jar:5.1.35]
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:92) ~[HikariCP-2.3.8.jar:na]
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:98) ~[HikariCP-2.3.8.jar:na]
at com.zaxxer.hikari.pool.BaseHikariPool.addConnection(BaseHikariPool.java:438) ~[HikariCP-2.3.8.jar:na]
at com.zaxxer.hikari.pool.BaseHikariPool.initializeConnections(BaseHikariPool.java:542) ~[HikariCP-2.3.8.jar:na]
... 49 common frames omitted
【问题讨论】:
应用程序 A 发生故障,因为配置 Hibernate 的代码在其初始化期间正在调用数据库。应用程序 B 是否也在使用 Hibernate? @AndyWilkinson:你怎么说应用程序 A 在初始化期间使用休眠。你是对的,应用程序 A 使用休眠。但错误日志没有显示任何与休眠相关的数据库初始化。 Spring Boot 的 JPA/Hibernate 自动配置正在进行 JDBC 调用,作为确定数据库默认 DDL 自动行为的一部分。 【参考方案1】:根据DataSource超类的source code,当你用No-Args构造函数实例化DataSource时,底层连接池没有被初始化。
您必须实际调用 DataSource 上的 createPool()
方法才能对其进行初始化。我建议您将以下内容添加到您的 @Bean
注释中。
@Bean(initMethod="createPool")
【讨论】:
它如何与我在上面定义的没有“initMethod”的 HikariDataSource 数据源一起工作 HikariDataSource 不会自动初始化(请参阅github.com/brettwooldridge/HikariCP/blob/dev/src/main/java/com/…)。您的应用程序中必须有一些其他正在初始化的东西试图使用连接。如果您不相信,请在应用程序 B 中使用 HikariDataSource,也应该不会失败。以上是关于在spring-boot启动期间tomcat数据源不检查有效连接?的主要内容,如果未能解决你的问题,请参考以下文章
Tomcat需要很长时间才能识别spring-boot应用程序的启动
使用 Spring-Boot 启动 Tomcat 上下文时出错:java.lang.ClassNotFoundException: org.apache.tomcat.dbcp.dbcp.BasicD
如何解决tomcat的问题? Spring-Boot“扫描失败”