alibaba / druid

阿里云计算平台DataWorks(https://help.aliyun.com/document_detail/137663.html) 团队出品,为监控而生的数据库连接池
https://github.com/alibaba/druid/wiki
Apache License 2.0
27.9k stars 8.57k forks source link

spring boot 3.2.0 + druid-spring-boot-3-starter 1.2.22,属性绑定失败 #5785

Closed xiaozcy closed 5 months ago

xiaozcy commented 6 months ago

我使用spring boot 3.2.0 + druid-spring-boot-3-starter 1.2.22,配置文件内容如下

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      filter:
        config:
          enabled: true
        stat:
          enabled: true
      filters: stat,wall,slf4j
      initial-size: 5
      max-active: 20
      max-pool-prepared-statement-per-connection-size: -1
      max-wait: 60000
      min-evictable-idle-time-millis: 300000
      min-idle: 5
      pool-prepared-statements: false
      test-on-borrow: false
      test-on-return: false
      test-while-idle: true
      time-between-eviction-runs-millis: 60000
      validation-query: SELECT 1
      validation-query-timeout: 1
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/xxx?charset=utf8mb4&useSSL=false&serverTimezone=Asia/Shanghai
      username: root
      password: xxx
      db-type: mysql

启动时抛出如下异常,配置信息无法正常绑定:

ERROR [main] com.alibaba.druid.pool.DruidDataSource:977 - {dataSource-1} init error
java.sql.SQLException: url not set
    at com.alibaba.druid.pool.DruidDataSource.resolveDriver(DruidDataSource.java:1275) ~[druid-1.2.22.jar:?]
    at com.alibaba.druid.pool.DruidDataSource.init(DruidDataSource.java:885) ~[druid-1.2.22.jar:?]
    at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1467) ~[druid-1.2.22.jar:?]
    at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1463) ~[druid-1.2.22.jar:?]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
    at org.springframework.boot.context.properties.bind.JavaBeanBinder$BeanProperty.lambda$getValue$0(JavaBeanBinder.java:383) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.DefaultBindConstructorProvider.getBindConstructor(DefaultBindConstructorProvider.java:46) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.ValueObjectBinder$ValueObject.get(ValueObjectBinder.java:195) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.ValueObjectBinder.bind(ValueObjectBinder.java:72) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:482) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:596) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:582) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:480) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:419) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:348) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$4(Binder.java:478) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:99) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:87) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:63) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:482) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:596) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:582) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:480) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:419) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:348) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:337) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:267) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:254) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.ConfigurationPropertiesBinder.bind(ConfigurationPropertiesBinder.java:94) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.bind(ConfigurationPropertiesBindingPostProcessor.java:96) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:79) ~[spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:421) ~[spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1767) ~[spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601) ~[spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523) ~[spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1441) ~[spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1348) ~[spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:911) ~[spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:789) ~[spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:546) ~[spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1336) ~[spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1166) ~[spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:563) ~[spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523) ~[spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) [spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) [spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) [spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:312) [spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) [spring-beans-6.1.1.jar:6.1.1]
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1173) [spring-context-6.1.1.jar:6.1.1]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:936) [spring-context-6.1.1.jar:6.1.1]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:616) [spring-context-6.1.1.jar:6.1.1]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) [spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:753) [spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:455) [spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:323) [spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1342) [spring-boot-3.2.0.jar:3.2.0]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1331) [spring-boot-3.2.0.jar:3.2.0]

Description:

Failed to bind properties under 'spring.datasource.druid.connection' to com.alibaba.druid.pool.DruidPooledConnection:

    Reason: java.sql.SQLException: url not set

Action:

Update your application's configuration
lizongbo commented 6 months ago

我在https://start.spring.io/ 初始化工程,然后下载到本地,添加druid配置, 将application.properties去除,使用application.yml, 且使用你的配置,只是将db换成H2,验证一切正常。

请核实你的配置,感觉是你把application.properties和application.yml并存使用,导致解析配置触发了别的逻辑导致问题出现在,注意看我特意改了application.properties的名字为applicationbak.properties

image

image

application.yml配置如下:

  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      filter:
        config:
          enabled: true
        stat:
          enabled: true
      filters: stat,wall,slf4j
      initial-size: 5
      max-active: 20
      max-pool-prepared-statement-per-connection-size: -1
      max-wait: 60000
      min-evictable-idle-time-millis: 300000
      min-idle: 5
      pool-prepared-statements: false
      test-on-borrow: false
      test-on-return: false
      test-while-idle: true
      time-between-eviction-runs-millis: 60000
      validation-query: SELECT 1
      validation-query-timeout: 1
      url: jdbc:h2:mem:testdb
      username: sa
      password: sa

build.gradle配置如下:

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.0'
    id 'io.spring.dependency-management' version '1.1.4'
}

group = 'com.lizongbo'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = '17'
}

repositories {
    maven {
        url "https://maven.aliyun.com/nexus/content/groups/public/"
    }
    mavenCentral()
    maven { url 'https://repo.spring.io/milestone' }
}

configurations {
    all {

    resolutionStrategy.cacheChangingModulesFor 60, 'seconds'
    exclude module: 'HikariCP-java7'   // quartz依赖的,我们不需要
    exclude module: 'c3p0'             // quartz依赖的,我们不需要
    exclude module: 'slf4j-log4j12'    // 过滤掉slf4j-log4j12
    exclude module: 'log4j-to-slf4j'    // 过滤掉slf4j-log4j12
    exclude group: 'ch.qos.logback'

    }
}

def log4j2_ver = "2.23.1"
List log4j_lib = [
    "org.apache.logging.log4j:log4j-api:$log4j2_ver",
    "org.apache.logging.log4j:log4j-core:$log4j2_ver",
    'com.lmax:disruptor:3.4.4'
]

dependencies {
    implementation log4j_lib
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-jdbc'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-log4j2'
    implementation 'com.alibaba:druid-spring-boot-3-starter:1.2.22'
    runtimeOnly 'com.h2database:h2'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
    useJUnitPlatform()
}
xiaozcy commented 6 months ago

@lizongbo 我的配置下没有application.properties,我使用了springboot 2.4之后引入的配置组的方式(Spring Boot Config Data Migration Guide),包含多个配置文件,简化后配置项大致如下:

application.yaml

spring:
  profiles:
    group:
      dev: datasource

application-dev.yaml:

# 一些与datasource无关的配置

application-datasource.yaml:

# 与示例基本一致
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/xxx?charset=utf8mb4&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: xxx
    # druid 连接池管理
    druid:
      filter:
        config:
          enabled: true
        stat:
          enabled: true
        filters: stat,wall,slf4j
        initial-size: 5
        max-active: 20
        max-pool-prepared-statement-per-connection-size: -1
        max-wait: 60000
        min-evictable-idle-time-millis: 300000
        min-idle: 5
        pool-prepared-statements: false
        test-on-borrow: false
        test-on-return: false
        test-while-idle: true
        time-between-eviction-runs-millis: 60000
        validation-query: SELECT 1
        validation-query-timeout: 1

启动springboot时指定--spring.profiles.active=dev,此时就会出现上面的问题

以上配置能够被Spring正常装载到org.springframework.boot.autoconfigure.jdbc.DataSourceProperties中: image

但似乎没有被正确装载到Druid的配置中

xiaozcy commented 6 months ago

补充一下,似乎不只是在druid-spring-boot-3-starter 1.2.22版本中如此,在1.2.21和1.2.20中也是如此

xiaozcy commented 6 months ago

同样的配置切换到hikari后,可以正常获取配置建立连接池

lizongbo commented 6 months ago

同样的配置切换到hikari后,可以正常获取配置建立连接池

现在druid里starter的写法其实不太规范,我最近调整一下, 照着 springboot里适配其它数据源的写法调整。

waveBoom commented 3 months ago

同样的问题,换到HikariCP正常