1. 项目概述为什么Spring Boot项目需要Druid如果你正在用Spring Boot开发一个需要连接数据库的应用那么你大概率已经用上了spring-boot-starter-jdbc或者spring-boot-starter-data-jpa。Spring Boot的自动配置确实省心它默认会使用HikariCP作为数据源这玩意儿性能不错开箱即用。但当你把项目推到生产环境或者需要对数据库连接进行更精细化的管理和监控时HikariCP自带的那点功能就有点捉襟见肘了。这时候Druid就该登场了。它不是那个做实时大数据分析的Apache Druid而是阿里巴巴开源的一个数据库连接池。在国内的Java生态里Druid的普及率非常高几乎成了“标配”。原因很简单它不仅仅是一个连接池更是一个集连接池、监控、防御于一体的数据库中间件。想象一下你不仅想知道应用跑得怎么样还想知道数据库连接用了多少、SQL执行得慢不慢、有没有可疑的访问这些需求HikariCP满足不了但Druid可以。很多面试官喜欢问Spring Boot整合Druid不是因为它多难而是因为它能考察你对生产级应用数据层管理的理解深度。从网络热词里频繁出现的“druid监控”、“多数据源”也能看出大家关心的远不止是把依赖加进去那么简单。所以这篇内容的目标很明确不满足于“能用”我们要“用好”。我会带你从零开始把一个全新的Spring Boot项目整合上Druid并且把监控统计、SQL防火墙、加密配置这些生产环境常用的功能都配置上。过程中遇到的坑和最佳实践我也会一并分享出来。2. 环境准备与项目初始化在开始敲代码之前我们得先把“战场”布置好。这里我假设你已经有基本的Spring Boot开发经验。2.1 技术栈与工具选型我选择的技术栈是目前以当前视角最主流、最稳定的组合兼顾了开发效率和生产可靠性Spring Boot 2.7.x 选择2.7这个长期支持版本而不是最新的3.x是为了避免一些依赖兼容性问题特别是和一些老版本的中间件或公司内部组件整合时更稳妥。3.x需要Java 17改动也较大对于整合类教程2.7.x受众更广。Java 8/11 LTS版本企业级开发的事实标准。Maven 3.6 项目管理工具。MySQL 5.7/8.0 最常用的关系型数据库之一其他数据库如PostgreSQL配置思路类似。IDEIntelliJ IDEA 社区版或旗舰版均可它对Spring Boot的支持是最好的。注意 确保你的Maven仓库配置正确能够正常下载中央仓库和阿里云镜像的依赖。国内环境建议配置阿里云镜像加速。2.2 创建Spring Boot项目你可以通过 Spring Initializr 网站生成也可以直接在IDEA里创建。这里列出核心依赖除了Druid我们把Web和数据库访问的基础也加上Project: Maven ProjectLanguage: JavaSpring Boot: 2.7.18 (选择一个2.7.x的稳定版本)Project Metadata: 按你的习惯填写Group、Artifact比如demo-druid。Dependencies:Spring Web(spring-boot-starter-web): 构建Web应用。Spring Data JDBC(spring-boot-starter-data-jdbc) 或Spring Data JPA(spring-boot-starter-data-jpa): 这里我选JDBC更轻量更能看清本质。你用JPA也可以配置方式几乎一样。MySQL Driver(mysql-connector-java): 数据库驱动。Lombok(org.projectlombok:lombok): 选装简化POJO代码非必须。点击生成下载并导入到你的IDE中。打开pom.xml你应该能看到类似下面的依赖dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-jdbc/artifactId /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies2.3 引入Druid依赖关键的一步来了我们需要引入Druid的官方Starter。阿里巴巴提供了专门为Spring Boot打造的druid-spring-boot-starter它比直接引入druid核心包更方便提供了更多的自动配置选项。在pom.xml的dependencies部分添加dependency groupIdcom.alibaba/groupId artifactIddruid-spring-boot-starter/artifactId version1.2.20/version !-- 请检查并使用最新稳定版本 -- /dependency为什么用Starter而不是核心包核心包com.alibaba:druid需要你手动配置DruidDataSourceBean并自己绑定监控的Servlet和Filter步骤繁琐。而Starter利用Spring Boot的自动配置机制只需在application.yml中写配置就能自动创建数据源、注册监控后台的Servlet和Filter大大简化了配置。这是整合的第一步也是正确的一步。添加依赖后Maven会自动下载。你可以先运行mvn clean compile检查一下是否有依赖冲突。通常很顺利。3. 基础整合替换默认数据源为Druid现在项目骨架和依赖都有了我们要告诉Spring Boot“别用Hikari了用Druid”。这个操作非常简单几乎全是配置工作。3.1 配置数据库连接与Druid基础参数在src/main/resources/application.yml文件中进行配置如果你喜欢.properties文件语法自行转换。我们将配置分为两部分通用的数据库连接信息和Druid连接池特有的参数。spring: datasource: # 1. 数据库连接四要素 url: jdbc:mysql://localhost:3306/your_database?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: your_username password: your_password driver-class-name: com.mysql.cj.jdbc.Driver # 2. 指定使用Druid数据源 (关键) type: com.alibaba.druid.pool.DruidDataSource # 3. Druid连接池配置 druid: # 初始化连接数 initial-size: 5 # 最小空闲连接数 min-idle: 5 # 最大活跃连接数 max-active: 20 # 获取连接时最大等待时间毫秒 max-wait: 60000 # 配置间隔多久才进行一次检测检测需要关闭的空闲连接毫秒 time-between-eviction-runs-millis: 60000 # 连接在池中最小生存的时间毫秒 min-evictable-idle-time-millis: 300000 # 验证连接是否有效的查询语句 validation-query: SELECT 1 # 申请连接时是否执行validationQuery检测 test-on-borrow: false # 归还连接时是否执行validationQuery检测 test-on-return: false # 空闲时是否执行validationQuery检测 test-while-idle: true参数解读与经验之谈type: 这是最关键的一行。Spring Boot的DataSourceAutoConfiguration会根据这个属性来实例化对应的数据源类。不指定的话默认就是HikariDataSource。initial-size/min-idle/max-active: 这是连接池的“黄金三角”。initial-size不宜过大避免启动时无谓消耗min-idle保持一定数量应对突发小流量max-active根据你的应用并发量和数据库承受能力来定20是一个常见的起步值。切记这个值不是越大越好数据库连接是昂贵的资源过多连接会导致数据库负载过高。max-wait: 应用从连接池获取连接的最大等待时间。如果超过这个时间还没拿到连接会抛出异常。在生产环境这个值需要根据业务容忍度设置避免线程长时间等待拖垮整个应用。test-while-idle: 建议设为true。Druid会通过后台线程定期检测空闲连接的有效性及时剔除已经失效的连接比如被数据库服务器端踢掉的连接这比test-on-borrow每次借连接都检查性能开销小也更可靠。3.2 验证整合是否成功配置完成后启动你的Spring Boot应用。如果控制台没有报关于数据源的错误基本上就成功了。我们可以写一个简单的测试来验证。创建一个测试Controller注入DataSource然后输出它的类名import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.sql.DataSource; RestController public class TestController { Autowired private DataSource dataSource; GetMapping(/ds) public String dataSourceType() { return 当前数据源是: dataSource.getClass().getName(); } }启动应用访问http://localhost:8080/ds。如果页面上显示当前数据源是: com.alibaba.druid.pool.DruidDataSource那么恭喜你Spring Boot已经成功使用Druid作为数据源了实操心得 有时候即使配置了type输出的还是Hikari。这通常是因为项目中其他依赖比如某些第三方Starter自动配置了Hikari且优先级更高。解决方法是在application.yml中确保spring.datasource.druid下的配置完整或者使用Primary注解在自定义的DataSourceBean上。不过使用官方Starter一般不会出现这个问题。4. 核心功能配置监控、统计与防御基础整合只是让Druid跑起来了它的威力在于监控和防护。接下来我们配置它的几个核心功能。4.1 启用Druid内置监控台Druid自带一个功能强大的监控后台可以可视化地查看连接池状态、SQL执行、URI请求等统计信息。在application.yml中接着上面的druid配置继续添加spring: datasource: druid: # ... 上面已有的连接池配置 ... # 4. 监控统计相关配置 stat-view-servlet: enabled: true # 启用StatViewServlet url-pattern: /druid/* # 监控后台的访问路径 login-username: admin # 登录账号强烈建议修改 login-password: admin123 # 登录密码强烈建议修改 reset-enable: false # 禁用HTML页面上的“Reset All”功能生产环境一定要关 allow: 127.0.0.1 # 白名单多个用逗号分隔。生产环境务必配置例如 allow: 192.168.1.100,10.0.0.1 deny: 192.168.1.73 # 黑名单 # 5. 配置监控统计的Filter web-stat-filter: enabled: true # 启用WebStatFilter用于统计Web请求 url-pattern: /* # 过滤所有URL exclusions: *.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/* # 排除一些静态资源和监控本身的请求 session-stat-enable: true # 启用Session统计 session-stat-max-count: 1000 # Session最大统计数 # 6. 配置SQL监控和防火墙Filter filter: stat: enabled: true # 启用StatFilter用于SQL执行统计 log-slow-sql: true # 记录慢查询 slow-sql-millis: 2000 # 慢查询阈值单位毫秒超过此时间的SQL会被记录 merge-sql: true # 合并相似的SQL比如select * from user where id? 无论参数是什么都统计为一条 wall: enabled: true # 启用WallFilter用于SQL防火墙防御 config: drop-table-allow: false # 禁止删除表 truncate-allow: false # 禁止清空表配置详解与安全警告stat-view-servlet: 这是监控后台的入口。login-username和login-password务必修改不要使用默认值这是最基本的安全措施。reset-enable在生产环境必须设为false否则任何人都可以通过页面重置所有监控数据。allow和deny用于IP访问控制对于暴露在公网的应用这是必须配置的。web-stat-filter: 这个Filter会统计应用中每个URI的请求情况你可以在监控台的“Web应用”模块看到。exclusions配置很重要避免无用的静态资源请求干扰统计结果。filter.stat: SQL统计过滤器。slow-sql-millis定义了慢SQL的阈值需要根据你的业务数据库性能来调整。merge-sql开启后统计视图会更清晰。filter.wall: SQL防火墙。这是Druid的一大亮点可以防止恶意的SQL注入。默认配置已经比较严格比如禁止SELECT *需单独配置select-all-column-allow: true、禁止没有WHERE条件的UPDATE/DELETE等。上述配置额外禁止了DROP TABLE和TRUNCATE TABLE这类高危操作。配置完成后重启应用。访问http://localhost:8080/druid输入你设置的用户名密码就能看到Druid强大的监控后台了。在这里你可以实时看到数据源活跃连接数、等待数等。SQL监控每条SQL的执行次数、时间、最慢等信息。SQL防火墙被拦截的SQL统计。Web应用URI请求统计。Session监控当前会话信息。4.2 配置日志输出与慢SQL记录监控台是给人看的日志则是给系统看的。我们需要将Druid的日志特别是慢SQL日志集成到项目的日志框架中比如Logback/SLF4J。首先确保你的pom.xml里有SLF4J的依赖Spring Boot默认包含。然后在src/main/resources下创建或修改logback-spring.xml文件添加Druid相关日志器的配置?xml version1.0 encodingUTF-8? configuration !-- 其他已有的配置... -- !-- 专门记录Druid的慢SQL日志 -- appender nameSLOW_SQL_FILE classch.qos.logback.core.rolling.RollingFileAppender filelogs/slow-sql.log/file rollingPolicy classch.qos.logback.core.rolling.TimeBasedRollingPolicy fileNamePatternlogs/slow-sql.%d{yyyy-MM-dd}.log/fileNamePattern maxHistory30/maxHistory /rollingPolicy encoder pattern%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n/pattern /encoder /appender !-- 将Druid中StatFilter的日志即慢SQL输出到单独的文件 -- logger namecom.alibaba.druid.filter.stat.StatFilter levelDEBUG additivityfalse appender-ref refSLOW_SQL_FILE/ /logger !-- 调整Druid其他日志级别避免过多DEBUG日志 -- logger namecom.alibaba.druid levelINFO/ /configuration这样配置后所有执行时间超过slow-sql-millis我们之前设置的2000毫秒的SQL其详细信息包括执行时间、参数、堆栈都会被记录到logs/slow-sql.log文件中便于后续分析和优化。踩坑记录 如果不配置additivityfalse慢SQL日志既会输出到单独文件也会输出到root logger配置的appender比如控制台可能造成日志重复。additivityfalse表示此logger的日志不再向上传递。5. 高级特性与生产环境调优基础功能和监控都配好了但想在生产环境用得稳还得深入一些。5.1 多数据源配置很多业务场景需要连接多个数据库。Spring Boot默认的自动配置只支持一个数据源。配置多数据源需要手动定义多个DataSourceBean。步骤一修改配置文件在application.yml中定义两套配置用不同的前缀区分# 主数据源 (例如业务库) spring: datasource: master: url: jdbc:mysql://localhost:3306/master_db?... username: master_user password: master_pass driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource druid: initial-size: 5 max-active: 20 # ... 其他druid配置 slave: url: jdbc:mysql://localhost:3307/slave_db?... username: slave_user password: slave_pass driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource druid: initial-size: 3 max-active: 10 # ... 其他druid配置步骤二创建配置类我们需要手动创建两个DataSourceBean并指定它们各自的监控Servlet和Filter。import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import javax.sql.DataSource; Configuration public class MultiDataSourceConfig { /** * 主数据源使用 Primary 注解指定默认数据源 */ Primary Bean(name masterDataSource) ConfigurationProperties(spring.datasource.master) // 绑定配置前缀 public DataSource masterDataSource() { // 使用DruidDataSourceBuilder构建它会自动读取spring.datasource.master.druid下的配置 return DruidDataSourceBuilder.create().build(); } /** * 从数据源 */ Bean(name slaveDataSource) ConfigurationProperties(spring.datasource.slave) public DataSource slaveDataSource() { return DruidDataSourceBuilder.create().build(); } }步骤三在Service或Repository中使用在使用时通过Qualifier注解指定要注入哪个数据源。import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import javax.sql.DataSource; Repository public class SomeRepository { private final JdbcTemplate masterJdbcTemplate; private final JdbcTemplate slaveJdbcTemplate; Autowired public SomeRepository(Qualifier(masterDataSource) DataSource masterDs, Qualifier(slaveDataSource) DataSource slaveDs) { this.masterJdbcTemplate new JdbcTemplate(masterDs); this.slaveJdbcTemplate new JdbcTemplate(slaveDs); } public void writeOperation() { // 使用 masterJdbcTemplate 执行写操作 masterJdbcTemplate.update(INSERT INTO ...); } public ListMapString, Object readOperation() { // 使用 slaveJdbcTemplate 执行读操作 return slaveJdbcTemplate.queryForList(SELECT * FROM ...); } }多数据源监控 这样配置后每个DruidDataSource实例都会有自己的连接池。但是Druid的监控Servlet默认只注册一个它只会显示第一个被初始化的数据源通常是Primary的那个的监控信息。如果需要监控多个需要更复杂的配置来注册多个StatViewServlet并指定不同的url-pattern这超出了基础整合的范围通常生产环境中监控一个核心主库也基本够用。5.2 生产环境关键参数调优建议根据不同的业务场景Druid的参数需要做针对性调整。下面是一份生产环境通用调优清单参数默认值/常见值生产环境建议与说明max-active20核心参数。计算公式参考max-active ≈ (应用实例数 * 每个实例的峰值线程数) * 1.2。例如4台实例每实例Tomcat最大线程200则总连接数需求约4*200*1.2960。但需考虑数据库服务器承受能力通常单库建议不超过500。min-idle同initial-size建议设置为max-active的1/10到1/5保持一定预热连接应对流量波动。max-wait60000 (60秒)重要。根据业务容忍度设置。对于高并发、低延迟业务可以设为1000-3000毫秒。超时拿不到连接应快速失败而不是长时间等待拖垮应用。time-between-eviction-runs-millis60000 (60秒)检测空闲连接的间隔。生产环境可以适当延长如120000毫秒2分钟减少检测开销。min-evictable-idle-time-millis300000 (5分钟)连接在池中最小的空闲生存时间。建议设置为time-between-eviction-runs-millis的2-3倍避免频繁回收和创建。validation-querySELECT 1对于MySQL 8.0建议使用SELECT 1。对于某些数据库如Oracle可能需要更简单的查询如SELECT 1 FROM DUAL。test-while-idletrue必须开启。这是保证连接有效性的推荐方式。test-on-borrowfalse建议关闭。每次借连接都检查性能损耗大。依靠test-while-idle和数据库的wait_timeout配合即可。filtersstat,wall除了stat和wall还可以考虑log4j2或slf4j来输出SQL日志但注意日志量。connection-properties-可在此设置连接属性例如设置MySQL的sessionVariables如connectionProperties: druid.stat.mergeSqltrue;druid.stat.slowSqlMillis1000。一个重要的经验 数据库服务器端也有连接超时设置如MySQL的wait_timeout默认8小时。必须确保Druid的min-evictable-idle-time-millis小于数据库的wait_timeout。例如MySQLwait_timeout28800秒8小时那么Druid的min-evictable-idle-time-millis应设置为例如25200000毫秒7小时。这样Druid会在数据库断开连接之前主动回收并测试空闲连接避免应用拿到已失效的连接导致报错。5.3 数据库密码加密明文密码写在配置文件中是安全隐患。Druid支持对密码进行加密存储。生成加密密码 使用Druid Jar包中的工具类。在命令行中执行确保在项目根目录或能找到druid jar包java -cp druid-1.2.20.jar com.alibaba.druid.filter.config.ConfigTools your_plain_password输出会包含privateKey、publicKey和加密后的password。修改配置文件 在application.yml中使用加密后的密码和公钥。spring: datasource: password: {加密后的字符串} druid: connection-properties: config.decrypttrue;config.decrypt.key{上一步生成的publicKey} filter: config: enabled: true # 启用ConfigFilter同时移除或注释掉原始的明文password配置。这样Druid在启动时会自动使用ConfigFilter解密密码。这是一个提升安全性的好习惯特别是在配置需要提交到代码仓库时。6. 常见问题排查与解决方案实录在实际整合过程中你几乎一定会遇到下面这些问题。我把它们和解决方案整理出来你可以像查字典一样使用。6.1 监控页面无法访问404症状 配置了stat-view-servlet.enabledtrue但访问/druid返回404。可能原因与解决路径冲突 检查你的应用是否有全局的Servlet拦截如/*。Druid的StatViewServlet默认映射到/druid/*如果被拦截了就无法访问。确保web-stat-filter.exclusions包含了/druid/*。Spring Boot版本与Starter兼容性 极少数情况下Spring Boot版本与Druid Starter版本不兼容。尝试使用较新且稳定的版本组合。Spring Boot 2.7.x 配合 Druid Starter 1.2.x 一般是没问题的。自定义Filter/Servlet顺序问题 如果你在代码中手动注册了Filter或Servlet可能会影响Druid自动注册的组件。尝试调整顺序或检查是否有冲突。6.2 监控页面登录失败症状 能打开/druid/login.html但输入配置的用户名密码后无法登录。可能原因与解决配置未生效 检查application.yml中stat-view-servlet.login-username和login-password的缩进是否正确确保它们在druid节点下。密码特殊字符 如果密码包含、:、#等YAML特殊字符需要用引号括起来例如login-password: admin123。浏览器缓存 尝试使用浏览器的无痕模式访问。6.3 启动报错java.lang.ClassNotFoundException: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure症状 应用启动失败控制台抛出类找不到异常。可能原因与解决依赖未下载或冲突 运行mvn dependency:tree查看druid-spring-boot-starter依赖是否被正确引入是否有版本冲突。确保Maven仓库网络通畅。错误排除了自动配置 检查你是否在启动类或配置类上使用了SpringBootApplication(exclude {...})不小心排除了DruidDataSourceAutoConfigure类。确保没有排除它。6.4 SQL监控或Web统计中看不到数据症状 监控页面能打开但“SQL监控”或“Web应用”标签页下没有数据。可能原因与解决Filter未启用 确保filter.stat.enabled和web-stat-filter.enabled都设置为true。URL模式不匹配web-stat-filter.url-pattern默认是/*应该能覆盖所有请求。检查是否有其他全局Filter提前处理了请求并影响了统计。没有SQL执行 监控数据是在有实际数据库操作后才会产生。确保你的应用已经执行过JDBC操作。merge-sql影响 如果开启了merge-sql那么不同参数的相同SQL只会显示为一条记录但执行次数和耗时是累加的。这是正常现象。6.5 连接泄露监控与处理这是生产环境最令人头疼的问题之一应用从连接池借走了连接但没有归还比如忘了关闭Connection、Statement、ResultSet。Druid提供了强大的连接泄露检测功能。在配置中开启spring: datasource: druid: # 连接泄露检测 remove-abandoned: true # 是否移除泄露的连接 remove-abandoned-timeout: 300 # 泄露连接被移除的超时时间秒即连接被占用超过此时间视为泄露 log-abandoned: true # 是否记录泄露连接的堆栈信息配置后如果一个连接被占用时间超过remove-abandoned-timeout例如300秒Druid会认为它泄露了会强制将其回收并在日志中打印出该连接被打开时的堆栈跟踪信息如果log-abandoned为true。这是一个非常强大的调试工具能帮你快速定位到忘记关闭资源的代码位置。重要提醒remove-abandoned是一个“事后补救”机制它会带来一些性能开销。在开发测试环境强烈建议开启用于排查代码问题。在生产环境可以视情况开启但超时时间remove-abandoned-timeout要设置得比业务最长事务时间更长避免误杀。6.6 与MyBatis-Plus等ORM框架整合的注意事项如果你使用MyBatis-PlusMP整合Druid同样简单。MP本身不干涉数据源的选择你只需要确保Druid的依赖和配置正确即可。可能遇到的坑 MP自带的分页插件PaginationInterceptor或性能分析插件可能会和Druid的Filter链产生一些微妙的交互比如SQL统计可能会计入两次。通常这不是功能性问题只是监控数据会有些偏差。如果遇到奇怪的SQL监控现象可以尝试调整Filter的顺序或者在MP插件中关闭一些功能。一个更干净的做法是在配置Druid的filters时明确指定顺序并确保statfilter在最后执行spring: datasource: druid: filter: wall: enabled: true stat: enabled: true # 使用逗号分隔定义filter顺序 filters: wall,stat整合Druid到Spring Boot项目从“能用”到“用好”是一个逐步深入的过程。核心在于理解连接池的各项参数含义并熟练运用其监控和防护功能。开始可以先用默认配置跑起来随着项目上线、流量增长再根据监控数据特别是活跃连接数、等待线程数、慢SQL去动态调整参数。把Druid监控台的地址记下来养成定期查看的习惯它会是你在排查数据库相关性能问题时最得力的助手。最后密码加密、IP白名单这些安全配置千万别等到出事了才想起来补。