druid 数据库连接池基础配置检验连接有效性连接保活 KeepAliveexception-sorter连接泄露处理filter打印 JDBC 执行日志统计与打印慢 SQL防止 SQL 注入加密 passwordspring boot Maven 依赖dependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-4-starter/artifactIdversion1.2.28/versionscopecompile/scope/dependency基础配置spring:datasource:druid:url:jdbc:mysql://localhost:3306/test# 基础信息username:rootpassword:rootdriver-class-name:com.mysql.cj.jdbc.Driver# 初始化数据源时建立物理连接的个数。initial-size:5# 连接池最大活跃连接数量当连接数量达到该值时再获取新连接时将处于等待状态直到有连接被释放才能借用成功max-active:20# 连接池最小空闲连接数min-idle:5# 获取连接时最大等待时间单位毫秒。配置了maxWait之后缺省启用公平锁并发效率会有所下降如果需要可以通过配置useUnfairLock属性为true使用非公平锁。max-wait:5000use-unfair-lock:true# 连接保持空闲而不被驱逐的最小时间min-evictable-idle-time-millis:1800000# 最大空闲时间超过该时间间隔空闲连接将被关闭max-evictable-idle-time-millis:3600000# 有两个含义#1) Destroy线程会检测连接的间隔时间如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。#2) testWhileIdle的判断依据详细看testWhileIdle属性的说明time-between-eviction-runs-millis:60000# 强制回收物理连接的最大超时时长大于0的情况下才生效当物理创建之后存活的时长超过该值时该连接会强制销毁便于重新创建新连接建议可以配置成7小时的毫秒值比如25200000这样可以规避MySQL的8小时连接断开问题phy-timeout-millis:25200000检验连接有效性spring:datasource:druid:# 用来检测连接是否有效的 sql。如果 validationQuery 为nulltestOnBorrow、testOnReturn、testWhileIdle 都不会起作用。# 如果数据库为 mysql不配置的话默认为 /* ping */ SELECT 1validation-query:/* ping*/SELECT 1# 单位秒检测连接是否有效的超时时间大于0才生效。底层调用jdbc Statement对象的void setQueryTimeout(int seconds)方法validation-query-timeout:1# 申请连接时执行 validationQuery 检测连接是否有效做了这个配置会降低性能其实一般情况下都可以开启只有性能要求极其高且连接使用很频繁的情况下才有必要禁用。test-on-borrow:false# 归还连接时执行 validationQuery 检测连接是否有效做了这个配置会降低性能这个一般不需要开启。test-on-return:false# 申请连接的时候检测如果空闲时间大于 timeBetweenEvictionRunsMillis执行 validationQuery 检测连接是否有效。test-while-idle:true连接保活 KeepAlivespring:datasource:druid:# 连接池中的 minIdle 数量以内的连接空闲时间超过minEvictableIdleTimeMillis则会执行keepAlive操作。keep-alive:true# 执行 keepAlive 的间隔时间必须大于 time-between-eviction-runs-milliskeep-alive-between-time-millis:120000# 用来检测连接是否有效的 sql。如果 validationQuery 为nulltestOnBorrow、testOnReturn、testWhileIdle 都不会起作用。# 如果数据库为 mysql不配置的话默认为 /* ping */ SELECT 1validation-query:/* ping*/SELECT 1# 单位秒检测连接是否有效的超时时间大于0才生效。底层调用jdbc Statement对象的void setQueryTimeout(int seconds)方法validation-query-timeout:1# 申请连接时执行 validationQuery 检测连接是否有效做了这个配置会降低性能其实一般情况下都可以开启只有性能要求极其高且连接使用很频繁的情况下才有必要禁用。test-on-borrow:false# 归还连接时执行 validationQuery 检测连接是否有效做了这个配置会降低性能这个一般不需要开启。test-on-return:false# 申请连接的时候检测如果空闲时间大于 timeBetweenEvictionRunsMillis执行 validationQuery 检测连接是否有效。test-while-idle:true打开KeepAlive之后的效果初始化连接池时会填充到 minIdle 数量。连接池中的 minIdle 数量以内的连接空闲时间超过 minEvictableIdleTimeMillis则会执行 keepAlive 操作。当网络断开等原因产生的由 ExceptionSorter 检测出来的死连接被清除后自动补充连接到 minIdle 数量。区别特性testWhileIdle (空闲时检测)keepAlive (连接保活)核心目的清理发现并剔除连接池中已经失效断连的空闲连接。维持主动发送心跳防止连接因长时间空闲被数据库或防火墙强制断开。作用对象连接池中所有满足空闲时间条件的连接。仅针对连接池中数量在minIdle最小空闲连接数以内的连接。触发时机由后台驱逐线程定期执行受timeBetweenEvictionRunsMillis控制。同样由后台驱逐线程触发但逻辑是“保活”而非“驱逐”。执行动作执行validationQuery如SELECT 1。如果失败直接关闭并丢弃该连接。执行心跳检测通常也是validationQuery。如果失败则关闭如果成功连接继续保留在池中。exception-sorter当网络断开或者数据库服务器Crash时连接池里面会存在“不可用连接”连接池需要一种机制剔除这些“不可用连接”。在 Druid 和 JBoss 连接池中剔除“不可用连接”的机制称为ExceptionSorter实现的原理是根据异常类型 /Code/Reason/Message 来识别“不可用连接”。没有类似 ExceptionSorter 的连接池在数据库重启或者网络中断之后不能恢复工作所以ExceptionSorter是连接池是否稳定的重要标志。在Druid中会根据连接池连接数据库的类型自动匹配不同类型的ExceptionSorter不需要额外配置。也可通过spring.datasource.druid.exception-sorter-class-name手动配置。spring:datasource:druid:exception-sorter-class-name:com.alibaba.druid.pool.vendor.MySqlExceptionSorter连接泄露处理spring:datasource:druid:# 是否回收泄露的连接,默认不开启建议只在测试环境设置未开启利用测试环境发现业务代码中未正常关闭连接的情况remove-abandoned:true# 开启回收泄露连接的最大超时默认300秒表示连接被借出超过5分钟后且removeAbandoned开启的情况下强制关闭该泄露连接remove-abandoned-timeout-millis:300000# 在开启removeAbandoned为true的情况可以开启该设置druid在销毁未及时关闭的连接时则会输出日志信息便于定位连接泄露问题log-abandoned:true当 removeAbandonedtrue 之后可以在内置监控界面的数据源 tab 中的查看 ActiveConnection StackTrace 属性的可以看到未关闭连接的具体堆栈信息从而方便查出哪些连接泄漏了。filterdruid 使用 filter 实现了日志、统计、防止 SQL 注入等功能。druid-xxx.jar!/META-INF/druid-filter.properties文件记录的各个 filter 的别名druid.filters.defaultcom.alibaba.druid.filter.stat.StatFilter druid.filters.statcom.alibaba.druid.filter.stat.StatFilter druid.filters.mergeStatcom.alibaba.druid.filter.stat.MergeStatFilter druid.filters.countercom.alibaba.druid.filter.stat.StatFilter druid.filters.encodingcom.alibaba.druid.filter.encoding.EncodingConvertFilter druid.filters.log4jcom.alibaba.druid.filter.logging.Log4jFilter druid.filters.log4j2com.alibaba.druid.filter.logging.Log4j2Filter druid.filters.slf4jcom.alibaba.druid.filter.logging.Slf4jLogFilter druid.filters.commonloggingcom.alibaba.druid.filter.logging.CommonsLogFilter druid.filters.commonLoggingcom.alibaba.druid.filter.logging.CommonsLogFilter druid.filters.wallcom.alibaba.druid.wall.WallFilter druid.filters.configcom.alibaba.druid.filter.config.ConfigFilter druid.filters.haRandomValidatorcom.alibaba.druid.pool.ha.selector.RandomDataSourceValidateFilter druid.filters.mysql8DateTimecom.alibaba.druid.filter.mysql8datetime.MySQL8DateTimeSqlTypeFilter打印 JDBC 执行日志logging:level:sql:debugspring:datasource:druid:filter:slf4j:enabled:true# 会将 ? 和参数拼接成可直接执行的 sql 打印statement-executable-sql-log-enable:true还有更细致地控制 connection、statement、resultSet、dataSource 方面的配置。参见com.alibaba.druid.filter.logging.LogFilter。统计与打印慢 SQLspring:datasource:druid:filter:stat:enabled:truemerge-sql:true# 在执行语句前记录连接的堆栈信息connection-stack-trace-enable:true# 打印慢 SQLlog-slow-sql:true# 慢 SQL 日志级别slow-sql-log-level:ERROR# 慢 SQL 阈值slow-sql-millis:1000# 内置监控页面stat-view-servlet:enabled:true# 监控页面、接口的 url 前缀url-pattern:/druid/*login-username:druidlogin-password:druidreset-enable:true# 可配置访问权限# allow: 127.0.0.1# deny: 127.0.0.1# 每个 30s 将统计信息打印到日志time-between-log-stats-millis:3000merge-sql 的作用当程序中存在没有参数化的sql执行时sql统计的效果会不好。比如select*fromtwhereid1select*fromtwhereid2select*fromtwhereid3在统计中显示为 3 条 SQL这不是我们希望要的效果。merge-sql 提供合并的功能能够将这 3 个SQL合并为如下的 SQLselect*fromtwhereid?内置监控页面访问 http://localhost:8080/druid/index.html输入配置的 login-username、login-password。防止 SQL 注入spring:datasource:druid:filter:wall:enabled:true# 对被认为是攻击的SQL进行LOG.error输出log-violation:true# 对被认为是攻击的SQL抛出SQLExceptionthrow-exception:trueconfig:# 禁用 drop tabledrop-table-allow:false# 禁用 truncate tabletruncate-allow:false更多配置参见com.alibaba.druid.wall.WallConfig。加密 password执行以下命令获取公私钥和加密后的 passwordjava -cp druid-1.2.28.jar com.alibaba.druid.filter.config.ConfigTools root输出privateKey:MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAhR87kBRzRaCHgK0fZhOPjBAcL8vYGGDw16/mJOwPz2G5eYXOavGWQEZ71aDTxGipCf8OTzDxXL0ywtAWfvQIDAQABAkAScN3JQR44rBTFOM3Ae3Imu0qLYk5uEF2enhV3AZe5xQ80weuSFwoUtIQaxDQDCeHChMD6x5LoePmiojLAiEApYPDcaITQrdKqqQB6w0xn75D3hr3nVpm8iYhKt6CQMCIQDSLwVIC8zGcYkfcDd7CYvUt7i4toLVkjR2cfoPqux4PwIgDKPkcDAtgmHXHPMLhnTqfkWcj0DFklmJWh1BWTHHBsCIQC2sUJQ9li/IM7EseC3pHuToUIB5Dpi81uAnN9zoOk8NwIgcG1kS3Dyo7hl7hUqdba1BvTMcmJKSnxEFtMhAg13oV0 publicKey:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAIfkfO5AUc0Wgh4CtH2YTj4wQHC/L2Bhg8Nev5iTsD89huXmFzmrxlvkBGe9Wg08RoqQn/vDk8w8Vy9MsLQFn70CAwEAAQ password:CM5VRs6Rur3N9FFR6U2gXjVHF2ZfSWIjnj5krPswwrBOJKWJZKInAbcfEBpGxMmedqettwmWmGaIKrlB2BWmcQspring:datasource:druid:url:jdbc:mysql://localhost:3306/testusername:rootpassword:CM5VRs6Rur3N9FFR6U2gXjVHF2ZfSWIjnj5krPswwrBOJKWJZKInAbcfEBpGxMmedqettwmWmGaIKrlB2BWmcQdriver-class-name:com.mysql.cj.jdbc.Driverpublic-key:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAIfkfO5AUc0Wgh4CtH2YTj4wQHC/L2Bhg8Nev5iTsD89huXmFzmrxlvkBGe9Wg08RoqQn/vDk8w8Vy9MsLQFn70CAwEAAQfilter:config:enabled:trueconnection-properties:config.decrypttrue;config.decrypt.key${spring.datasource.druid.public-key}