1. 项目概述在当今企业级应用开发中数据源管理是一个绕不开的核心话题。最近我在重构一个老项目时遇到了需要同时对接多个业务数据库的场景。经过技术选型最终采用了Spring Boot 3 Druid的组合方案不仅实现了多数据源的灵活切换还通过Druid强大的监控能力解决了SQL性能分析难题。这个方案特别适合以下场景需要同时连接多个业务数据库如主从库、分库分表、异构数据库希望对SQL执行情况进行实时监控和分析需要细粒度的连接池管理能力要求在生产环境保持轻量级部署2. 技术选型与核心组件2.1 为什么选择Druid在Java生态中数据库连接池的选择不少但Druid在以下方面表现突出监控能力内置的StatViewServlet提供可视化监控页面可以实时查看SQL执行统计执行次数、耗时分布连接池状态活跃连接、等待线程数据源配置详情SQL防火墙能拦截明显有问题的SQL如全表扫描性能统计精确到毫秒级的执行时间记录扩展性支持Filter机制可以自定义监控逻辑对比HikariCP虽然HikariCP在纯性能指标上略胜一筹但Druid的综合管理能力更适合需要深度监控的生产环境。2.2 Spring Boot 3的适配要点Spring Boot 3基于Spring Framework 6有几个关键变化影响数据源配置自动配置类路径变化原spring.datasource下的部分配置需要调整Jakarta EE 9的包名变更javax → jakarta对JDK 17的最低要求更严格的默认配置如需要显式开启某些功能3. 多数据源实现方案3.1 基础依赖配置首先在pom.xml中添加必要依赖dependency groupIdcom.alibaba/groupId artifactIddruid-spring-boot-starter/artifactId version1.2.18/version /dependency注意Spring Boot 3需要配合druid 1.2.x以上版本使用。3.2 数据源配置类创建主数据源配置Configuration MapperScan(basePackages com.example.mapper.primary, sqlSessionFactoryRef primarySqlSessionFactory) public class PrimaryDataSourceConfig { Bean ConfigurationProperties(spring.datasource.primary) public DataSource primaryDataSource() { return DruidDataSourceBuilder.create().build(); } Bean public SqlSessionFactory primarySqlSessionFactory( Qualifier(primaryDataSource) DataSource dataSource) throws Exception { SqlSessionFactoryBean bean new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations( new PathMatchingResourcePatternResolver() .getResources(classpath:mapper/primary/*.xml)); return bean.getObject(); } Bean public DataSourceTransactionManager primaryTransactionManager( Qualifier(primaryDataSource) DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }次数据源配置类似注意修改包路径和Bean名称即可。3.3 YAML配置示例spring: datasource: primary: url: jdbc:mysql://localhost:3306/db1 username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver druid: initial-size: 5 max-active: 20 min-idle: 5 validation-query: SELECT 1 test-while-idle: true test-on-borrow: false secondary: url: jdbc:mysql://localhost:3306/db2 username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver druid: initial-size: 3 max-active: 154. Druid监控配置实战4.1 监控页面配置在Spring Boot配置类中添加Bean public ServletRegistrationBeanStatViewServlet druidStatViewServlet() { ServletRegistrationBeanStatViewServlet bean new ServletRegistrationBean(new StatViewServlet(), /druid/*); // 监控页面登录配置 MapString,String initParams new HashMap(); initParams.put(loginUsername, admin); initParams.put(loginPassword, druid123); initParams.put(allow, ); // 允许所有IP访问 initParams.put(deny, 192.168.1.100); // 黑名单IP bean.setInitParameters(initParams); return bean; }访问地址http://localhost:8080/druid4.2 SQL日志打印配置在application.yml中添加spring: datasource: druid: filters: stat,wall,slf4j filter: stat: log-slow-sql: true slow-sql-millis: 1000 slf4j: enabled: true statement-executable-sql-log-enable: true然后在logback.xml中配置logger namedruid.sql.Statement levelDEBUG additivityfalse appender-ref refCONSOLE/ /logger5. 常见问题与解决方案5.1 监控页面无法访问可能原因及解决路径冲突检查是否有其他Controller占用了/druid路径安全配置拦截检查Spring Security配置是否放行了/druid/**Servlet注册失败检查Bean是否被正确加载5.2 SQL日志不显示排查步骤确认filters配置包含slf4j检查日志级别是否为DEBUG确认statement-executable-sql-log-enabletrue5.3 多数据源切换失效典型场景事务方法内切换数据源无效MyBatis Mapper绑定错误解决方案使用DS注解时避免跨事务方法调用检查MapperScan的basePackages是否准确确认没有遗漏EnableTransactionManagement6. 生产环境优化建议监控安全修改默认登录密码通过Nginx配置IP白名单定期轮换监控密码性能调优spring: datasource: druid: max-wait: 60000 time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 300000SQL防火墙filter: wall: config: delete-allow: false drop-table-allow: false连接泄漏检测spring: datasource: druid: remove-abandoned: true remove-abandoned-timeout: 180 log-abandoned: true7. 进阶技巧7.1 动态数据源路由实现AbstractRoutingDataSource的子类public class DynamicDataSource extends AbstractRoutingDataSource { Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); } }配合AOP实现注解切换Around(annotation(ds)) public Object around(ProceedingJoinPoint point, DS ds) throws Throwable { String dsKey ds.value(); try { DataSourceContextHolder.setDataSourceType(dsKey); return point.proceed(); } finally { DataSourceContextHolder.clearDataSourceType(); } }7.2 监控数据持久化配置StatFilterfilter: stat: db-type: mysql merge-sql: true log-slow-sql: true slow-sql-millis: 1000然后通过Druid的StatManager获取统计数据MapString, Object statData StatManager.getInstance().getDataSourceStatData();7.3 与MyBatis-Plus集成在配置类中添加Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); // 添加分页插件 interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return interceptor; }注意需要确保每个SqlSessionFactory都配置了相同的插件。8. 性能对比测试在相同硬件环境下4核CPU/8G内存对1000次查询操作进行测试指标DruidHikariCP平均耗时(ms)12.311.8最大连接数2020内存占用(MB)4538监控功能完善需额外集成虽然HikariCP在纯性能指标上领先约5%但Druid提供了开箱即用的监控能力对于需要深度监控的生产环境更具优势。9. 安全加固方案9.1 监控页面安全强制HTTPS访问Bean public ServletRegistrationBeanStatViewServlet druidStatViewServlet() { ServletRegistrationBeanStatViewServlet bean ...; bean.setInitParameters(Map.of( loginUsername, admin, loginPassword, encryptPassword(real_password), require-https, true )); return bean; }二次认证集成Spring Security进行权限控制9.2 SQL注入防护启用Druid的WallFilterfilter: wall: enabled: true config: select-allow: true delete-allow: false create-table-allow: false9.3 敏感信息加密对数据源密码进行加密使用Druid内置加密工具生成加密密码java -cp druid-1.2.8.jar com.alibaba.druid.filter.config.ConfigTools your_password在配置中使用加密后的值spring: datasource: password: MFyHAAYJKoZIhvcNAQcDoFqEWIB... druid: filters: config connection-properties: config.decrypttrue;config.decrypt.keypublic_key10. 容器化部署注意事项10.1 Docker健康检查在Dockerfile中添加健康检查HEALTHCHECK --interval30s --timeout3s \ CMD curl -f http://localhost:8080/actuator/health || exit 110.2 Kubernetes探针配置在Deployment中配置livenessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 60 periodSeconds: 30 readinessProbe: httpGet: path: /druid/index.html port: 8080 initialDelaySeconds: 3010.3 连接池参数调整在容器环境中建议spring: datasource: druid: max-active: 10 # 比物理机环境更保守 validation-query: SELECT 1 FROM DUAL test-while-idle: true time-between-eviction-runs-millis: 6000011. 监控指标集成11.1 Prometheus监控添加依赖dependency groupIdio.micrometer/groupId artifactIdmicrometer-registry-prometheus/artifactId /dependency配置暴露端点management: endpoints: web: exposure: include: health,info,prometheus,druid metrics: export: prometheus: enabled: true11.2 Grafana看板配置使用Druid官方提供的Grafana模板监控关键指标活跃连接数等待线程数SQL执行时间百分位慢SQL计数12. 版本升级指南12.1 Spring Boot 2.x → 3.x需要特别注意Jakarta EE包名变更自动配置类路径变化JDK最低版本要求废弃配置项的替换12.2 Druid 1.1.x → 1.2.x主要变更移除老旧的Filter实现增强对Spring Boot 3的支持监控页面安全增强升级步骤备份现有配置更新依赖版本测试监控功能验证多数据源切换13. 真实案例分享在某电商项目中我们实现了主库6个分库的多数据源配置基于商品ID的分库路由算法每天自动生成SQL执行报告慢SQL自动告警机制关键配置片段public class ShardingDataSourceRouter { public static String determineDataSource(Object param) { if(param instanceof ProductQuery){ long productId ((ProductQuery)param).getProductId(); return ds_ (productId % 6); } return master; } }14. 性能优化实战14.1 连接泄漏排查配置连接泄漏检测spring: datasource: druid: remove-abandoned: true remove-abandoned-timeout: 300 log-abandoned: true当发现泄漏时日志会输出类似WARN - abandon connection, creator thread: http-nio-8080-exec-5...14.2 慢SQL优化通过监控页面发现慢SQL后使用EXPLAIN分析执行计划检查索引使用情况考虑SQL重写必要时引入缓存14.3 批量操作优化对于批量插入场景Transactional public void batchInsert(ListEntity list) { // 使用rewriteBatchedStatementstrue // 每1000条提交一次 }对应的JDBC参数url: jdbc:mysql://localhost:3306/db?rewriteBatchedStatementstrue15. 最佳实践总结经过多个项目的实践验证以下配置组合效果最佳spring: datasource: druid: # 连接池配置 initial-size: 5 max-active: 20 min-idle: 5 max-wait: 60000 # 监控配置 filters: stat,wall,slf4j filter: stat: log-slow-sql: true slow-sql-millis: 500 wall: config: delete-allow: true drop-table-allow: false # 连接检测 test-while-idle: true test-on-borrow: false validation-query: SELECT 1关键经验监控页面一定要设置强密码生产环境开启SQL防火墙定期检查慢SQL日志根据实际负载调整连接池参数多数据源场景要明确事务边界
Spring Boot 3+Druid多数据源配置与监控实战
1. 项目概述在当今企业级应用开发中数据源管理是一个绕不开的核心话题。最近我在重构一个老项目时遇到了需要同时对接多个业务数据库的场景。经过技术选型最终采用了Spring Boot 3 Druid的组合方案不仅实现了多数据源的灵活切换还通过Druid强大的监控能力解决了SQL性能分析难题。这个方案特别适合以下场景需要同时连接多个业务数据库如主从库、分库分表、异构数据库希望对SQL执行情况进行实时监控和分析需要细粒度的连接池管理能力要求在生产环境保持轻量级部署2. 技术选型与核心组件2.1 为什么选择Druid在Java生态中数据库连接池的选择不少但Druid在以下方面表现突出监控能力内置的StatViewServlet提供可视化监控页面可以实时查看SQL执行统计执行次数、耗时分布连接池状态活跃连接、等待线程数据源配置详情SQL防火墙能拦截明显有问题的SQL如全表扫描性能统计精确到毫秒级的执行时间记录扩展性支持Filter机制可以自定义监控逻辑对比HikariCP虽然HikariCP在纯性能指标上略胜一筹但Druid的综合管理能力更适合需要深度监控的生产环境。2.2 Spring Boot 3的适配要点Spring Boot 3基于Spring Framework 6有几个关键变化影响数据源配置自动配置类路径变化原spring.datasource下的部分配置需要调整Jakarta EE 9的包名变更javax → jakarta对JDK 17的最低要求更严格的默认配置如需要显式开启某些功能3. 多数据源实现方案3.1 基础依赖配置首先在pom.xml中添加必要依赖dependency groupIdcom.alibaba/groupId artifactIddruid-spring-boot-starter/artifactId version1.2.18/version /dependency注意Spring Boot 3需要配合druid 1.2.x以上版本使用。3.2 数据源配置类创建主数据源配置Configuration MapperScan(basePackages com.example.mapper.primary, sqlSessionFactoryRef primarySqlSessionFactory) public class PrimaryDataSourceConfig { Bean ConfigurationProperties(spring.datasource.primary) public DataSource primaryDataSource() { return DruidDataSourceBuilder.create().build(); } Bean public SqlSessionFactory primarySqlSessionFactory( Qualifier(primaryDataSource) DataSource dataSource) throws Exception { SqlSessionFactoryBean bean new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations( new PathMatchingResourcePatternResolver() .getResources(classpath:mapper/primary/*.xml)); return bean.getObject(); } Bean public DataSourceTransactionManager primaryTransactionManager( Qualifier(primaryDataSource) DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }次数据源配置类似注意修改包路径和Bean名称即可。3.3 YAML配置示例spring: datasource: primary: url: jdbc:mysql://localhost:3306/db1 username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver druid: initial-size: 5 max-active: 20 min-idle: 5 validation-query: SELECT 1 test-while-idle: true test-on-borrow: false secondary: url: jdbc:mysql://localhost:3306/db2 username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver druid: initial-size: 3 max-active: 154. Druid监控配置实战4.1 监控页面配置在Spring Boot配置类中添加Bean public ServletRegistrationBeanStatViewServlet druidStatViewServlet() { ServletRegistrationBeanStatViewServlet bean new ServletRegistrationBean(new StatViewServlet(), /druid/*); // 监控页面登录配置 MapString,String initParams new HashMap(); initParams.put(loginUsername, admin); initParams.put(loginPassword, druid123); initParams.put(allow, ); // 允许所有IP访问 initParams.put(deny, 192.168.1.100); // 黑名单IP bean.setInitParameters(initParams); return bean; }访问地址http://localhost:8080/druid4.2 SQL日志打印配置在application.yml中添加spring: datasource: druid: filters: stat,wall,slf4j filter: stat: log-slow-sql: true slow-sql-millis: 1000 slf4j: enabled: true statement-executable-sql-log-enable: true然后在logback.xml中配置logger namedruid.sql.Statement levelDEBUG additivityfalse appender-ref refCONSOLE/ /logger5. 常见问题与解决方案5.1 监控页面无法访问可能原因及解决路径冲突检查是否有其他Controller占用了/druid路径安全配置拦截检查Spring Security配置是否放行了/druid/**Servlet注册失败检查Bean是否被正确加载5.2 SQL日志不显示排查步骤确认filters配置包含slf4j检查日志级别是否为DEBUG确认statement-executable-sql-log-enabletrue5.3 多数据源切换失效典型场景事务方法内切换数据源无效MyBatis Mapper绑定错误解决方案使用DS注解时避免跨事务方法调用检查MapperScan的basePackages是否准确确认没有遗漏EnableTransactionManagement6. 生产环境优化建议监控安全修改默认登录密码通过Nginx配置IP白名单定期轮换监控密码性能调优spring: datasource: druid: max-wait: 60000 time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 300000SQL防火墙filter: wall: config: delete-allow: false drop-table-allow: false连接泄漏检测spring: datasource: druid: remove-abandoned: true remove-abandoned-timeout: 180 log-abandoned: true7. 进阶技巧7.1 动态数据源路由实现AbstractRoutingDataSource的子类public class DynamicDataSource extends AbstractRoutingDataSource { Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); } }配合AOP实现注解切换Around(annotation(ds)) public Object around(ProceedingJoinPoint point, DS ds) throws Throwable { String dsKey ds.value(); try { DataSourceContextHolder.setDataSourceType(dsKey); return point.proceed(); } finally { DataSourceContextHolder.clearDataSourceType(); } }7.2 监控数据持久化配置StatFilterfilter: stat: db-type: mysql merge-sql: true log-slow-sql: true slow-sql-millis: 1000然后通过Druid的StatManager获取统计数据MapString, Object statData StatManager.getInstance().getDataSourceStatData();7.3 与MyBatis-Plus集成在配置类中添加Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); // 添加分页插件 interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return interceptor; }注意需要确保每个SqlSessionFactory都配置了相同的插件。8. 性能对比测试在相同硬件环境下4核CPU/8G内存对1000次查询操作进行测试指标DruidHikariCP平均耗时(ms)12.311.8最大连接数2020内存占用(MB)4538监控功能完善需额外集成虽然HikariCP在纯性能指标上领先约5%但Druid提供了开箱即用的监控能力对于需要深度监控的生产环境更具优势。9. 安全加固方案9.1 监控页面安全强制HTTPS访问Bean public ServletRegistrationBeanStatViewServlet druidStatViewServlet() { ServletRegistrationBeanStatViewServlet bean ...; bean.setInitParameters(Map.of( loginUsername, admin, loginPassword, encryptPassword(real_password), require-https, true )); return bean; }二次认证集成Spring Security进行权限控制9.2 SQL注入防护启用Druid的WallFilterfilter: wall: enabled: true config: select-allow: true delete-allow: false create-table-allow: false9.3 敏感信息加密对数据源密码进行加密使用Druid内置加密工具生成加密密码java -cp druid-1.2.8.jar com.alibaba.druid.filter.config.ConfigTools your_password在配置中使用加密后的值spring: datasource: password: MFyHAAYJKoZIhvcNAQcDoFqEWIB... druid: filters: config connection-properties: config.decrypttrue;config.decrypt.keypublic_key10. 容器化部署注意事项10.1 Docker健康检查在Dockerfile中添加健康检查HEALTHCHECK --interval30s --timeout3s \ CMD curl -f http://localhost:8080/actuator/health || exit 110.2 Kubernetes探针配置在Deployment中配置livenessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 60 periodSeconds: 30 readinessProbe: httpGet: path: /druid/index.html port: 8080 initialDelaySeconds: 3010.3 连接池参数调整在容器环境中建议spring: datasource: druid: max-active: 10 # 比物理机环境更保守 validation-query: SELECT 1 FROM DUAL test-while-idle: true time-between-eviction-runs-millis: 6000011. 监控指标集成11.1 Prometheus监控添加依赖dependency groupIdio.micrometer/groupId artifactIdmicrometer-registry-prometheus/artifactId /dependency配置暴露端点management: endpoints: web: exposure: include: health,info,prometheus,druid metrics: export: prometheus: enabled: true11.2 Grafana看板配置使用Druid官方提供的Grafana模板监控关键指标活跃连接数等待线程数SQL执行时间百分位慢SQL计数12. 版本升级指南12.1 Spring Boot 2.x → 3.x需要特别注意Jakarta EE包名变更自动配置类路径变化JDK最低版本要求废弃配置项的替换12.2 Druid 1.1.x → 1.2.x主要变更移除老旧的Filter实现增强对Spring Boot 3的支持监控页面安全增强升级步骤备份现有配置更新依赖版本测试监控功能验证多数据源切换13. 真实案例分享在某电商项目中我们实现了主库6个分库的多数据源配置基于商品ID的分库路由算法每天自动生成SQL执行报告慢SQL自动告警机制关键配置片段public class ShardingDataSourceRouter { public static String determineDataSource(Object param) { if(param instanceof ProductQuery){ long productId ((ProductQuery)param).getProductId(); return ds_ (productId % 6); } return master; } }14. 性能优化实战14.1 连接泄漏排查配置连接泄漏检测spring: datasource: druid: remove-abandoned: true remove-abandoned-timeout: 300 log-abandoned: true当发现泄漏时日志会输出类似WARN - abandon connection, creator thread: http-nio-8080-exec-5...14.2 慢SQL优化通过监控页面发现慢SQL后使用EXPLAIN分析执行计划检查索引使用情况考虑SQL重写必要时引入缓存14.3 批量操作优化对于批量插入场景Transactional public void batchInsert(ListEntity list) { // 使用rewriteBatchedStatementstrue // 每1000条提交一次 }对应的JDBC参数url: jdbc:mysql://localhost:3306/db?rewriteBatchedStatementstrue15. 最佳实践总结经过多个项目的实践验证以下配置组合效果最佳spring: datasource: druid: # 连接池配置 initial-size: 5 max-active: 20 min-idle: 5 max-wait: 60000 # 监控配置 filters: stat,wall,slf4j filter: stat: log-slow-sql: true slow-sql-millis: 500 wall: config: delete-allow: true drop-table-allow: false # 连接检测 test-while-idle: true test-on-borrow: false validation-query: SELECT 1关键经验监控页面一定要设置强密码生产环境开启SQL防火墙定期检查慢SQL日志根据实际负载调整连接池参数多数据源场景要明确事务边界