阿里生态项目加入Activiti7遇到初始化异常的问题
在阿里生态项目(nacos/dubbo/sentinel/seata)里面加入Activiti7,出现下面异常,初始化拿不到数据库链接 排查的过程一波三折,经过一番捣鼓发现是druid的连接抛出的异常: com.alibaba.druid.pool.DruidPooledConnection#setSchema public void setSchema(String schema) throws SQLException { throw new SQLFeatureNotSupportedException(); } 我用的是默认的HikariDataSource,怎么冒出个druid??查依赖。
翻查依赖树发现spring-cloud-starter-alibaba-nacos-config和seata-all两个包依赖了druid,于是在依赖里面排除druid,启动正常了。
于是就发了一条issue给seata,得到的回复是seata依赖druid是为了用它的sqlparser, 也就是说,用排除Druid的方法是不能真正解决问题的,会给seata带来异常隐患!
因为看依赖树并没发现有druid-spring-boot-starter,也并没在配置里面有druid的参数,理应不会自动配置druidsource的!于是再继续查!
最后发现依赖里面的baomidou动态数据源导致:
-
com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceCreatorAutoConfiguration.DruidDataSourceCreatorConfiguration#druidDataSourceCreator 只要发现有druid的依赖就会建立DruidDataSourceCreator
/** * 存在Druid数据源时, 加入创建器 */ @ConditionalOnClass(DruidDataSource.class) @Configuration public class DruidDataSourceCreatorConfiguration { @Bean @Order(DRUID_ORDER) @ConditionalOnMissingBean public DruidDataSourceCreator druidDataSourceCreator() { return new DruidDataSourceCreator(properties); } } /** * 存在Hikari数据源时, 加入创建器 */ @ConditionalOnClass(HikariDataSource.class) @Configuration public class HikariDataSourceCreatorConfiguration { @Bean @Order(HIKARI_ORDER) @ConditionalOnMissingBean public HikariDataSourceCreator hikariDataSourceCreator() { return new HikariDataSourceCreator(properties); } }
最后将兼容的Datasource收集到com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator.creators 然后做匹配,因为Druid先于Hikari,所以就抢占了:
public DataSource createDataSource(DataSourceProperty dataSourceProperty) { DataSourceCreator dataSourceCreator = null; for (DataSourceCreator creator : this.creators) { if (creator.support(dataSourceProperty)) { dataSourceCreator = creator; break; } } if (dataSourceCreator == null) { throw new IllegalStateException("creator must not be null,please check the DataSourceCreator"); } return dataSourceCreator.createDataSource(dataSourceProperty); }
找到原因就好办,DataSourceCreattor要通过support返回当前creator是否支持app配置,而其中会用上type这个条件:
@Override public boolean support(DataSourceProperty dataSourceProperty) { Class<? extends DataSource> type = dataSourceProperty.getType(); return (type == null && druidExists) || (type != null && DRUID_DATASOURCE.equals(type.getName())); }
所以,最终完美的解决方法不是用pom排除,也不是放弃使用动态数据源,而是在配置文件中指定type:
spring: datasource: dynamic: primary: master strict: false datasource: master: url: jdbc:mysql://127.0.0.1:3306/seata_sample_nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC&nullCatalogMeansCurrent=true username: root password: 123456 type: com.zaxxer.hikari.HikariDataSource
Druid不是一般的烂!