SpringBoot3.x多数据源配置与Druid监控实战
1. 项目概述在当今企业级应用开发中多数据源支持已成为标配需求。无论是读写分离、分库分表还是对接不同业务系统的数据库都需要我们掌握多数据源配置的核心技术。最近我在一个金融项目中实践了SpringBoot3.x MybatisPlus Druid的多数据源方案并完整实现了Druid监控统计功能过程中踩了不少坑也积累了些实战经验今天就来系统梳理下这套技术栈的配置要点。这套组合拳的优势很明显SpringBoot3.x提供了现代化的开发体验MybatisPlus极大简化了数据库操作而Druid作为阿里开源的数据库连接池不仅性能优异其内置的监控功能更是排查SQL性能问题的利器。但在实际配置时三者的版本兼容性、多数据源的线程隔离、监控页面的安全防护等问题都需要特别注意。2. 环境准备与基础配置2.1 依赖管理首先确保你的项目是基于SpringBoot3.x构建的。在pom.xml中需要引入以下核心依赖dependencies !-- SpringBoot Starter -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- MybatisPlus Starter -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3.1/version /dependency !-- Druid Starter -- dependency groupIdcom.alibaba/groupId artifactIddruid-spring-boot-3-starter/artifactId version1.2.18/version /dependency !-- 数据库驱动 (以MySQL为例) -- dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency /dependencies特别注意SpringBoot3.x必须使用druid-spring-boot-3-starter传统starter不兼容。这是很多开发者容易踩的第一个坑。2.2 基础配置在application.yml中配置主数据源这里以MySQL为例spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/main_db?useSSLfalseserverTimezoneUTC username: root password: 123456 druid: initial-size: 5 min-idle: 5 max-active: 20 max-wait: 600003. 多数据源配置实现3.1 数据源配置类我们需要为每个数据源创建独立的配置类。以下是主从两个数据源的典型配置Configuration MapperScan(basePackages com.example.mapper.primary, sqlSessionTemplateRef primarySqlSessionTemplate) public class PrimaryDataSourceConfig { Bean(name primaryDataSource) ConfigurationProperties(prefix spring.datasource.primary) public DataSource primaryDataSource() { return DruidDataSourceBuilder.create().build(); } Bean(name primarySqlSessionFactory) public SqlSessionFactory primarySqlSessionFactory(Qualifier(primaryDataSource) DataSource dataSource) throws Exception { MybatisSqlSessionFactoryBean factory new MybatisSqlSessionFactoryBean(); factory.setDataSource(dataSource); factory.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources(classpath:mapper/primary/*.xml)); return factory.getObject(); } Bean(name primaryTransactionManager) public DataSourceTransactionManager primaryTransactionManager(Qualifier(primaryDataSource) DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } Bean(name primarySqlSessionTemplate) public SqlSessionTemplate primarySqlSessionTemplate(Qualifier(primarySqlSessionFactory) SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } }从数据源配置类似只需更换bean名称和路径前缀。完整的配置应该包含数据源beanSqlSessionFactory事务管理器SqlSessionTemplate3.2 动态数据源路由对于需要动态切换数据源的场景我们可以实现AbstractRoutingDataSourcepublic class DynamicDataSource extends AbstractRoutingDataSource { Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); } } public class DataSourceContextHolder { private static final ThreadLocalString contextHolder new ThreadLocal(); public static void setDataSourceType(String dataSourceType) { contextHolder.set(dataSourceType); } public static String getDataSourceType() { return contextHolder.get(); } public static void clearDataSourceType() { contextHolder.remove(); } }使用时通过AOP或手动调用切换DataSourceContextHolder.setDataSourceType(secondary); // 执行数据库操作 DataSourceContextHolder.clearDataSourceType();4. Druid监控配置与安全防护4.1 监控中心配置在application.yml中启用Druid监控spring: datasource: druid: stat-view-servlet: enabled: true url-pattern: /druid/* login-username: admin login-password: druid123 reset-enable: false web-stat-filter: enabled: true url-pattern: /* exclusions: *.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/* filter: stat: enabled: true log-slow-sql: true slow-sql-millis: 1000 merge-sql: true wall: enabled: true config: drop-table-allow: false4.2 安全防护要点Druid监控页面如果暴露在外网非常危险必须做好防护强制修改默认账号密码添加IP白名单限制通过配置stat-view-servlet.allow生产环境建议通过内网访问或添加额外认证层定期检查Druid版本及时修复安全漏洞重要提示我曾遇到过因Druid监控页面未授权访问导致数据库信息泄露的事故。建议在安全要求高的场景下通过Spring Security添加额外保护。5. 常见问题与解决方案5.1 连接池耗尽问题症状系统运行一段时间后出现获取连接超时异常。解决方案检查连接泄漏在Druid配置中添加spring: datasource: druid: remove-abandoned: true remove-abandoned-timeout: 300 log-abandoned: true合理设置连接池参数根据实际负载调整确保每次操作后关闭Connection/Statement/ResultSet5.2 多数据源事务问题跨数据源的事务需要引入分布式事务解决方案如Seata。对于单数据源事务确保在Service方法上添加Transactional注解指定正确的事务管理器Transactional(transactionManager primaryTransactionManager) public void businessMethod() { // ... }5.3 MybatisPlus分页失效在多数据源环境下分页插件需要单独配置Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; }6. 性能优化建议连接池参数调优initialSize: 初始连接数建议5-10minIdle: 最小空闲连接建议与initialSize相同maxActive: 最大连接数根据并发量设置通常20-100maxWait: 获取连接超时时间建议1000-3000msSQL监控开启慢SQL记录slow-sql-millis定期分析Druid监控中的SQL执行统计多数据源负载均衡对于读多写少的场景可以考虑使用读写分离使用DS注解动态切换数据源需集成dynamic-datasource组件这套配置方案在我们生产环境已经稳定运行半年多支撑了日均百万级的数据库操作。关键在于合理的连接池参数严格的监控告警定期的性能分析安全防护措施到位最后分享一个实用技巧在开发环境可以开启Druid的SQL防火墙功能它能有效拦截危险SQL如全表删除避免开发人员误操作导致数据丢失。配置如下spring: datasource: druid: filter: wall: enabled: true config: delete-allow: false drop-table-allow: false