当前位置: 首页 > news >正文

【SpringBoot教程】Spring Boot + MySQL + Druid连接池整合教程

🙋大家好!我是毛毛张!
🌈个人首页: 神马都会亿点点的毛毛张

前面毛毛张介绍过HikariCP连接池,今天毛毛张来介绍一下Druid连接池,SpringBoot 2.0以上默认使用HikariCP数据源,但是也要学会使用Druid连接池,可以说HikariCPDriud都是当前JavaWeb上最优秀的数据源

文章目录

  • 1 Druid连接池简介
  • 2 入门使用教程
    • 2.1 后端代码
      • 2.1.1 创建项目
      • 2.1.2 导入依赖
      • 2.1.3 编写配置文件
      • 2.1.4 初始化数据库并创建对应实体类
      • 2.1.5 编写响应封装与前端展示VO
      • 2.1.6 编写业务逻辑
      • 2.1.7 跨域资源共享
      • 2.1.8 启动类
      • 2.1.9 测试
      • 2.1.10 Druid后台监控查看
    • 2.2 前端代码
    • 2.3 可能会遇到的问题
      • 2.3.1 MySQL 连接器版本问题
      • 2.3.2 javax.annotation.Resource找不到包的问题
      • 2.3.3 监控页面报`404`
      • 2.3.4 之前SpringBoot3不兼容Druid - 可忽略
    • 2.4 总结
  • 3 配置详解
    • 3.1 导入依赖
      • 3.1.1 Druid三种依赖
      • 3.1.2 SpringBoot 2.x 依赖
      • 3.1.3 SpringBoot 3.x 依赖
    • 3.2 常见配置
    • 3.3 数据源配置解析
    • 3.4 连接池配置详解
    • 3.5 Druid监控配置
    • 3.6 总结
  • 4 总结
  • 参考文献

1 Druid连接池简介

  • Druid 是阿里巴巴开源的一款高性能数据库连接池,集成了 C3P0、DBCP 等传统连接池的优点,并针对高并发和大规模生产环境进行了优化。它提供了高效的数据库连接管理,具备强大的监控和统计功能,能够实时监控 SQL 执行、连接池状态,并提供慢查询分析,帮助开发者优化数据库性能。Druid 具有灵活的配置选项,支持连接泄露检测、SQL 防火墙、黑白名单过滤等安全特性,确保数据库的稳定性与安全性。相比于 Spring Boot 默认使用的 HikariCP,Druid 在可视化监控、扩展性和 SQL 分析方面更具优势,适用于对性能和安全要求较高的 Java 应用。
  • 特性和功能:
    • 高性能:Druid连接池通过一些优化策略实现高性能的数据库连接获取和释放。其中包括使用预创建连接来减少连接获取的开销,以及通过连接池扩展机制来快速处理并发请求。此外,Druid还提供了连接的闲置检测和定时回收机制,以避免连接长时间占用资源。
    • 监控统计:Druid连接池内置了强大的监控统计功能,可以实时监控连接池的状态、活跃连接数、请求频率、SQL执行情况等。它提供了一个内置的Web界面,可以方便地查看连接池的监控数据,并进行性能分析和故障排查。
    • 防止泄露:Druid连接池可以检测和关闭泄露的连接,防止长时间占用数据库连接资源。它提供了一套完善的连接泄露检测和回收机制,以保证连接资源的有效利用。
    • 数据库访问优化:Druid连接池支持连接的预处理、批量更新等优化操作,可以提高数据库的访问效率。它还提供了SQL执行的慢查询日志功能,可以帮助开发人员找出慢查询语句,并进行性能优化。
    • 安全防护:Druid连接池提供了一些安全防护机制,如SQL防火墙、黑白名单过滤等。这些机制可以保护数据库免受恶意SQL注入等攻击。
    • 配置灵活:Druid连接池的配置选项非常灵活,可以根据应用程序的需求进行定制。您可以设置连接池大小、最大连接数、连接超时时间、验证方式等参数,以满足不同场景的需求。
  • 更多的介绍可以参见官网:https://github.com/alibaba/druid/

2 入门使用教程

  • 案例内容:基于SpringBoot3.x,使用MyBatis框架,结合Druid连接池,查询并展示数据库中的全部用户信息
  • 项目版本依赖:
    • 后端:
      • SpringBoot:3.1.0
      • JDK:17
      • Mybatis:3.0.1
      • druid-spring-boot-3-starter:1.2.24
    • 前端
      • vite:6.0.5
      • vue:3.5.13
      • vue-router:4.5.0
      • pinia:2.3.0
      • axios:1.7.9

2.1 后端代码

2.1.1 创建项目

  • 如何快速创建一个SpringBoot新项目可以参见毛毛张的这篇博客:【SpringBoot教程】IDEA快速搭建正确的SpringBoot版本和Java版本的项目
  • 下面是毛毛张的完整后端代码文件结构如下图:
    image-20250127001559008

2.1.2 导入依赖

  • 更多的关于依赖的介绍可以看第三节,毛毛张在这里只介绍关于这个入门项目的依赖的内容
  • 毛毛张针对SpringBoot3.1.0选择的Druid适配的依赖:druid-spring-boot-3-starter:1.2.24
  • 需要注意的是,在使用Druid作为连接池的同时,还需要单独导入 MySQL 数据库驱动,通常通过引入 mysql-connector-java 依赖来实现
  • 毛毛张在这个任务中为了方便,使用了Mybatis框架,整个项目的pom.xml文件为:
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.zzx</groupId><artifactId>springboot3-druid-demo</artifactId><version>0.0.1-SNAPSHOT</version><name>springboot3-druid-demo</name><description>springboot3-druid-demo</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-parent</artifactId><version>3.1.4</version></parent><properties><java.version>17</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>3.1.4</spring-boot.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.0.33</version><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- druid启动器的依赖  --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-3-starter</artifactId><version>1.2.24</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.1</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>17</source><target>17</target><encoding>UTF-8</encoding></configuration></plugin><!--    SpringBoot应用打包插件--><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring-boot.version}</version><configuration><mainClass>com.zzx.Springboot3DruidDemoApplication</mainClass><skip>true</skip></configuration><executions><execution><id>repackage</id><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build></project>
    

2.1.3 编写配置文件

  • 下面是整个项目的配置文件application.yaml,关键部分已被注释出来了,更多详细的解释可以参见第三节的内容
    server:port: 8080  # 服务端口号spring:datasource:url: jdbc:mysql://localhost:3306/springboot?useSSL=false&autoReconnect=true&characterEncoding=utf8&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8&allowMultiQueries=true  # 数据库地址driver-class-name: com.mysql.cj.jdbc.Driver  # MySQL 8.0 及以上需要 cj,5.7 以下可去掉 cjusername: root  # 数据库用户名password: abc123  # 数据库密码type: com.alibaba.druid.pool.DruidDataSource  # 使用 Druid 数据源druid:# 连接池基本配置initial-size: 5  # 初始化连接数min-idle: 10  # 最小空闲连接数max-active: 20  # 最大连接数max-wait: 60000  # 最大等待时间(毫秒)time-between-eviction-runs-millis: 60000  # 多少毫秒执行一次空闲连接回收min-evictable-idle-time-millis: 600000  # 连接最小生存时间(毫秒)max-evictable-idle-time-millis: 1800000  # 连接最大生存时间(毫秒)# 连接校验配置validation-query: SELECT 1  # 用于测试连接是否可用的 SQL 语句validation-query-timeout: 2000  # SQL 校验超时时间(毫秒)test-on-borrow: false  # 获取连接时是否检测(影响性能,建议关闭)test-on-return: false  # 归还连接时是否检测(影响性能,建议关闭)test-while-idle: true  # 空闲时是否检测(推荐开启)# 连接池优化配置phy-max-use-count: 1000  # 每个连接的最大使用次数pool-prepared-statements: false  # 是否开启 PSCachemax-open-prepared-statements: 50  # PSCache 允许的最大预编译 SQL 数# Druid 监控配置filters: stat,wall,slf4j  # 启用监控统计拦截的过滤器(SQL监控、防火墙、日志)# 监控页面配置stat-view-servlet:enabled: true  # 启用内置监控页面url-pattern: /druid/*  # 监控页面路径login-username: admin  # 访问监控页面的用户名login-password: admin  # 访问监控页面的密码reset-enable: false  # 是否允许重置统计数据allow: 127.0.0.1  # 允许访问的 IP 白名单deny: 192.168.0.1  # 禁止访问的 IP 黑名单# Web 监控配置web-stat-filter:enabled: true  # 开启 Web-JDBC 关联监控url-pattern: /*  # 监控所有请求exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"  # 排除静态资源和监控路径session-stat-enable: true  # 启用 Session 统计session-stat-max-count: 1000  # Session 最大数量# SQL 慢查询日志配置filter:stat:# 是否开启 FilterStat,默认trueenabled: true# 是否开启 慢SQL 记录,默认falselog-slow-sql: true# 慢 SQL 的标准,默认 3000,单位:毫秒slow-sql-millis: 5000# 合并多个连接池的监控数据,默认falsemerge-sql: false# 日志配置,采用 SLF4Jslf4j:enabled: true  # 启用日志statement-log-error-enabled: true  # 开启 SQL 语句错误日志statement-create-after-log-enabled: falsestatement-close-after-log-enabled: falseresult-set-open-after-log-enabled: falseresult-set-close-after-log-enabled: falselogging:level:org.springframework.jdbc.core.JdbcTemplate: DEBUG  # 开启 SQL 执行日志mybatis:# Mapper 文件的位置mapper-locations: classpath:mapper/*Mapper.xml# 实体类的包路径type-aliases-package: com.zzx.entityconfiguration:# 自动下划线转驼峰map-underscore-to-camel-case: true
    

2.1.4 初始化数据库并创建对应实体类

  • 创建名为springboot的数据库,并创建user_info表:
    -- 创建数据库
    CREATE DATABASE IF NOT EXISTS springboot CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
    USE springboot;-- 删除已存在的 user_info 表(如果存在)
    DROP TABLE IF EXISTS `user_info`;-- 创建 user_info 表
    CREATE TABLE `user_info`  (`id` INT NOT NULL AUTO_INCREMENT,`user_name` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,`pass_word` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,`age` INT NULL DEFAULT NULL,`gender` VARCHAR(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 3 DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;-- 插入示例数据
    INSERT INTO `user_info` (`id`, `user_name`, `pass_word`, `age`, `gender`) VALUES 
    (1, 'sam', 'password123', 32, 'M'),
    (2, 'hah', 'password456', 10, 'F');-- 确保外键检查被重新启用
    SET FOREIGN_KEY_CHECKS = 1;
    
  • 对应实体类User
    package com.zzx.entity;import lombok.Data;@Data
    public class User {private Integer id;        // 对应数据库中的 `u_id`private String userName;   // 对应数据库中的 `u_username`private String passWord;   // 对应数据库中的 `u_password`private Integer age;       // 对应数据库中的 `u_age`private String gender;     // 对应数据库中的 `u_gender`
    }
    

2.1.5 编写响应封装与前端展示VO

  • 定义统一的响应封装类 ResVo:

    package com.zzx.reponse;public class ResVo<T> {private Integer code;      // 状态码private String message;    // 消息内容private T content;         // 内容,可以是任何类型的数据// 构造方法public ResVo(Integer code, String message, T content) {this.code = code;this.message = message;this.content = content;}// 成功的返回,通常是常用的,内容可以为空public static <T> ResVo<T> success(T content) {return new ResVo<>(200, "成功", content);}// 失败的返回,通常返回错误信息public static <T> ResVo<T> error(Integer code, String message) {return new ResVo<>(code, message, null);}// Getters and Setterspublic Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public T getContent() {return content;}public void setContent(T content) {this.content = content;}
    }
  • 前端展示对象UserInfoVo,在查询用户信息时通过是把查询到的结果封装在一个实体类中,但是返回给前端的信息不一定是用户的全部信息,例如用户的密码就不能直接返回给前端,或者不要返回,所以毛毛张设计了一个这个类:

    package com.zzx.model.vo;import lombok.Data;@Data
    public class UserInfoVo {//返回给前端展示的数据,密码不能展示,性别转化成数字private Integer id;private String username;private Integer age;private Integer gender;
    }
  • 为了节省传输的字符,毛毛张将用户的信息对应的内容转化成数字再返回给前端,因此设计了一个枚举类型UserSexEnum

    package com.zzx.enums;public enum UserSexEnum {M(1, "男"), // M对应男,值为 1F(0, "女"); // F对应女,值为 0private int code;         // 对应的数字值(1 或 0)private String description; // 性别描述(男 或 女)// 构造方法,用于设置枚举常量的描述和对应的代码UserSexEnum(int code, String description) {this.code = code;this.description = description;}// 获取性别描述public String getDescription() {return description;}// 获取对应的数字代码public int getCode() {return code;}// 根据传入的字符串 'M' 或 'F' 获取对应的性别枚举public static UserSexEnum fromString(String sexStr) {for (UserSexEnum sex : UserSexEnum.values()) {if (sex.name().equalsIgnoreCase(sexStr)) {return sex;}}throw new IllegalArgumentException("无效的性别字符串: " + sexStr);}// 根据 'M' 或 'F' 获取对应的数字代码public static int getCodeByString(String sexStr) {UserSexEnum sex = fromString(sexStr);return sex.getCode();}
    }
    
  • 由于User类和UserInfoVo不是完全一一对应的,所以为了数据转换的方便,毛毛张再这里专门写了一个转换类UserConverter

    package com.zzx.converter;import com.zzx.entity.User;
    import com.zzx.enums.UserSexEnum;
    import com.zzx.model.vo.UserInfoVo;import java.util.List;
    import java.util.stream.Collectors;public class UserConverter{// 单个转换public static UserInfoVo toUserInfoDTO(User user) {UserInfoVo userInfoVo = new UserInfoVo();userInfoVo.setId(user.getId());userInfoVo.setUsername(user.getUserName());userInfoVo.setAge(user.getAge());userInfoVo.setGender(UserSexEnum.getCodeByString(user.getGender()));return userInfoVo;}// 批量转换public static List<UserInfoVo> toUserInfoDTOList(List<User> users) {// 使用 Java 8 的 stream API 进行批量转换return users.stream().map(UserConverter::toUserInfoDTO)  // 对每个 User 对象进行转换.collect(Collectors.toList());     // 收集成 List<UserInfoDTO>}
    }
    

2.1.6 编写业务逻辑

  • controller层UserController
    package com.zzx.controller;import com.zzx.converter.UserConverter;
    import com.zzx.entity.User;
    import com.zzx.model.vo.UserInfoVo;
    import com.zzx.reponse.ResVo;
    import com.zzx.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
    @RequestMapping("user")
    public class UserController {@Autowiredprivate UserService userService;@GetMapping("queryAllUserInfo")  // 使用 GET 请求public ResVo<List<UserInfoVo>> queryAllUserInfo() {List<User> userInfoList = userService.queryAllUserInfo();return ResVo.success(UserConverter.toUserInfoDTOList(userInfoList));}
    }
    
  • service层接口UserService
    package com.zzx.service;import com.zzx.entity.User;import java.util.List;public interface UserService {List<User> queryAllUserInfo();
    }
    
  • 服务层实现类UserServiceImpl
    package com.zzx.service.impl;import com.zzx.entity.User;
    import com.zzx.mapper.UserMapper;
    import com.zzx.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;import java.util.List;@Service
    public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;@Overridepublic List<User> queryAllUserInfo() {return userMapper.queryAllUserInfo();}
    }
    
  • mapper层UserMapper
    package com.zzx.mapper;import org.apache.ibatis.annotations.Mapper;
    import com.zzx.entity.User;import java.util.List;@Mapper
    public interface UserMapper {List<User> queryAllUserInfo();
    }
    
  • Mapper 层 SQL 映射配置文件UserMapper.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.zzx.mapper.UserMapper"><!-- 声明标签写sql语句  crud  select  insert update  delete每个标签对应接口的一个方法!  方法的一个实现!注意:mapper接口不能重载!!! 因为mapper.xml无法识别! 根据方法名识别!--><!-- 查询所有用户 --><select id="queryAllUserInfo" resultType="com.zzx.entity.User">SELECT id, user_name, pass_word, age, gender FROM user_info</select></mapper>
    

2.1.7 跨域资源共享

  • 由于毛毛张这个代码还有前端代码,涉及到和前端交互,还需要做一个跨域资源共享的配置,毛毛张没有使用@CrossOrigin,而是通过拦截器的方式实现的:
    package com.zzx.interceptor;import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;public class CorsInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {response.setHeader("Access-Control-Allow-Origin", "*");  // 允许所有来源response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");response.setHeader("Access-Control-Allow-Headers", "Origin, Content-Type, Accept, Authorization");response.setHeader("Access-Control-Allow-Credentials", "true");// 处理OPTIONS请求if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {response.setStatus(HttpServletResponse.SC_OK);return false;  // 返回false,表示不再执行后续的Controller方法}return true;  // 继续执行其他拦截器或Controller方法}
    }
  • 配置类:
    package com.zzx.config;import com.zzx.interceptor.CorsInterceptor;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
    public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册 CORS 拦截器registry.addInterceptor(new CorsInterceptor()).addPathPatterns("/**")  // 拦截所有路径.excludePathPatterns("/login", "/error");  // 排除登录和错误页面}
    }
    

2.1.8 启动类

  • 启动类SpringbootHicariCpDemoApplication
    package com.zzx;import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
    @MapperScan("com.zzx.mapper")
    public class SpringbootHicariCpDemoApplication {public static void main(String[] args) {SpringApplication.run(SpringbootHicariCpDemoApplication.class, args);}}
    

2.1.9 测试

  • 启动后端程序,可以在浏览器中输入http://localhost:8080/user/queryAllUserInfo,返回结果如下则表示后端代码正确无误:
    image-20250125120253993
  • 同时也能看见控制台输出使用的连接池为Druid连接池:

image-20250126180009473

  • 完整的后端代码已上传至毛毛张Github仓库:hhttps://github.com/zzxrepository/SpringBootTutorial/tree/master/springboot-mysql/springboot3-druid-demo

2.1.10 Druid后台监控查看

  • 上一个步骤执行完了http://localhost:8080/user/queryAllUserInfo请求,我们可以通过http://127.0.01:8080/druid/login.html来查看DruidSQL监控页面,查看做了哪些SQL语句。访问该页面首先需要登陆,如下图所示。
    image-20250127000826837
  • 登陆密码可以查看配置文件,毛毛张在上面的配置文件中用户名和密码全是admin
    image-20250127000929459
  • 登陆成功之后即可查看SQL监控:
    image-20250127001054572

2.2 前端代码

  • 前端代码和之前毛毛张介绍的Mybatis教程的代码是一样的,毛毛张在这里不做过多的介绍了,感兴趣的可以查看毛毛张的相关博客:【SpringBoot教程】SpringBoot整合Mybatis - 前后端分离项目 - vue3
  • 完整前端代码已上传至毛毛张Github仓库:https://github.com/zzxrepository/SpringBootTutorial/tree/master/springboot-mysql/springboot-mysql-demo-vue

2.3 可能会遇到的问题

  • 毛毛张在之前的项目使用的是SpringBoot2.x版本,本项目使用的是3.x版本的,遇到了一些问题,在这里也记录一下

2.3.1 MySQL 连接器版本问题

  • 在 Spring Boot 2.7.6 版本中,MySQL 连接器的版本可以自动推断,但在 Spring Boot 3.x 中,MySQL 连接器的版本需要显式指定,否则会导致构建失败。解决办法是在 pom.xml 中显式指定 mysql-connector-java 的版本,例如:
    <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version>  <!-- 替换为你需要的版本 --><scope>runtime</scope>
    </dependency>
    

2.3.2 javax.annotation.Resource找不到包的问题

  • 在``SpringBoot2.x中毛毛张使用的是@Resource`注解,但是报错: javax.annotation.Resource找不到包
  • 原因:Spring Boot 3.x 版本基于 Spring 6,而 javax.annotation 包已不再包含在 Spring 中。此时编译时会出现 程序包javax.annotation不存在 的错误。解决办法有两个选择:
    • 方案 1:显式添加javax.annotation-api依赖:
      <dependency><groupId>javax.annotation</groupId><artifactId>javax.annotation-api</artifactId><version>1.3.2</version>
      </dependency>
      
    • 方案 2:直接使用 Spring 推荐的@Autowired注解替代@Resource,因为@AutowiredSpring的默认注解,且具有更好的兼容性

2.3.3 监控页面报404

  • 启动服务后,打开Druid监控地址http://127.0.0.1:8080/druid/,出现如下图所示错误
    image-20250126214150008
  • 错误原因:主要是因为Springboot3.x使用Jakarta EE 10,从 Java EE 变更为 Jakarta EE,包名以 javax开头的需要相应地变更为jakarta,如javax.servlet.*,修改为jakarta.servlet.,目前Druid提供的druid-spring-boot-3-starter1.2.23之前的依赖仍使用javax的旧包,直到1.2.24才解决,因此毛毛张在上面项目中使用的就是1.2.24版本的依赖

2.3.4 之前SpringBoot3不兼容Druid - 可忽略

  • Spring Boot 3 发布之前,Druid 数据源与 Spring Boot 3 的兼容性较差,特别是在自动配置方面。druid-spring-boot-starter 版本(如 1.2.20)在与 Spring Boot 3 集成时,缺少自动装配配置类,导致无法正常启动,通常会出现 ClassNotFoundException 错误。
    Caused by: java.lang.ClassNotFoundException: com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure
    
  • 解决方案:开发者需要手动在 resources 目录下创建 META-INF/spring/ 文件夹,并添加一个名为 org.springframework.boot.autoconfigure.AutoConfiguration.imports 的文件,内容为 com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure,这样 Spring Boot 就能加载并配置 Druid 数据源。
    image
com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure
  • 当前,使用兼容 Spring Boot 3 的 druid-spring-boot-3-starter 版本(如 1.2.24)已经解决了这个问题,不再需要手动配置自动装配类,因此这个问题不会再出现

2.4 总结

  • 毛毛张关于这个入门案例编写的了两个版本的后端代码,已经上传至Github
    • SpringBoot2.x:https://github.com/zzxrepository/SpringBootTutorial/tree/master/springboot-mysql/springboot-druid-demo
    • SpringBoot3.x:https://github.com/zzxrepository/SpringBootTutorial/tree/master/springboot-mysql/springboot3-druid-demo
  • 前端代码:https://github.com/zzxrepository/SpringBootTutorial/tree/master/springboot-mysql/springboot-mysql-demo-vue

3 配置详解

3.1 导入依赖

  • 不同于HikariCP连接池,Druid连接池需要显示的导入相关依赖

3.1.1 Druid三种依赖

  • 当我们使用Maven Search插件搜索Druid连接池的时候发现阿里巴巴提供了三种依赖,如下图
    image-20250126205641714
  • 这三种依赖毛毛张简单介绍一下:
    • druid:Druid 是一个高效、稳定、功能丰富的数据库连接池,广泛应用于 Java 项目中。它具备出色的性能和监控功能,支持 SQL 执行日志、连接池监控、SQL 防火墙等高级功能,尤其在处理大规模高并发数据库请求时表现优异。在 Spring Boot 项目中使用 Druid 时,通常需要手动配置连接池属性,手动注入 DruidDataSource,并且需要开发者自己编写相关的配置类。这种方式适用于不使用 Spring Boot 或对连接池有高度自定义需求的项目。
    • druid-spring-boot-starterdruid-spring-boot-starter 是为 Spring Boot 2.x 项目提供的一款自动化配置的启动器,它简化了 Druid 集成过程,减少了手动配置的步骤。通过该 Starter,开发者只需在 application.propertiesapplication.yml 中配置数据源的相关信息,Spring Boot 会自动为你配置并初始化 Druid 连接池。它不仅支持 Druid 数据源的连接池功能,还提供了 Druid 的监控、日志、慢查询等功能的自动配置,非常适合大多数 Spring Boot 2.x 项目,推荐使用此依赖来整合 Druid,避免手动配置的繁琐。
    • druid-spring-boot-3-starter:是专门为 Spring Boot 3.x 版本设计的自动化配置依赖。由于 Spring Boot 3.x 引入了一些不兼容的 API 变更,因此 druid-spring-boot-3-starter 对 Druid 的集成进行了适配,以确保其能够与 Spring Boot 3.x 的特性兼容。与 druid-spring-boot-starter 类似,开发者只需要在配置文件中提供数据库连接信息,Spring Boot 3.x 会自动配置 Druid 数据源以及其他相关功能,如监控、SQL 日志等。这款依赖是 Spring Boot 3.x 项目中使用 Druid 的推荐选择,简化了集成步骤,适合希望快速配置和使用 Druid 数据源的开发者。
  • 总结:因此作为SpringBoot项目
    • Spring Boot 2.x 项目使用 druid-spring-boot-starter
    • Spring Boot 3.x 项目使用 druid-spring-boot-3-starter
  • 说在前面:毛毛张为什么这么强调版本的原因是因为,如果使用的版本不正确,不匹配,就不能使用Druid 提供的 SQL 监控、连接池监控、慢查询日志以及 Web 和 SQL 的监控页面等功能,如下图所示。因此版本的选择非常重要!
    image-20250126211129303

3.1.2 SpringBoot 2.x 依赖

  • 下面是毛毛张针对SpringBoot2.7.6选择的四个适配的依赖:
    • druid-spring-boot-starter
      • 1.1.10
      • 1.1.21
      • 1.2.15
      • 1.2.18
  • 依赖文件如下图所示:
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">........<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-parent</artifactId><version>2.7.6</version></parent><dependencies>......<!-- 以下四个版本任选一个 --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.10</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.21</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.15</version></dependency></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.18</version></dependency>......</dependencies>......
    </project>
    

3.1.3 SpringBoot 3.x 依赖

  • 下面是毛毛张针对SpringBoot3.1.0选择的依赖:
    • druid-spring-boot-3-starter:1.2.24
  • 完整的项目依赖为:
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">......<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-parent</artifactId><version>3.1.0</version></parent>......<dependencies>......<!-- druid启动器的依赖  --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-3-starter</artifactId><version>1.2.24</version></dependency>......</dependencies>......</project>
    

3.2 常见配置

  • 下面是HicariCP连接池常见的配置:
    spring:datasource:url: jdbc:mysql://localhost:3306/springboot?useSSL=false&autoReconnect=true&characterEncoding=utf8&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8&allowMultiQueries=true  # 数据库地址driver-class-name: com.mysql.cj.jdbc.Driver  # MySQL 8.0 及以上需要 cj,5.7 以下可去掉 cjusername: root  # 数据库用户名password: abc123  # 数据库密码type: com.alibaba.druid.pool.DruidDataSource  # 使用 Druid 数据源druid:# 连接池基本配置initial-size: 5  # 初始化连接数min-idle: 10  # 最小空闲连接数max-active: 20  # 最大连接数max-wait: 60000  # 最大等待时间(毫秒)time-between-eviction-runs-millis: 60000  # 多少毫秒执行一次空闲连接回收min-evictable-idle-time-millis: 600000  # 连接最小生存时间(毫秒)max-evictable-idle-time-millis: 1800000  # 连接最大生存时间(毫秒)# 连接校验配置validation-query: SELECT 1  # 用于测试连接是否可用的 SQL 语句validation-query-timeout: 2000  # SQL 校验超时时间(毫秒)test-on-borrow: false  # 获取连接时是否检测(影响性能,建议关闭)test-on-return: false  # 归还连接时是否检测(影响性能,建议关闭)test-while-idle: true  # 空闲时是否检测(推荐开启)# 连接池优化配置phy-max-use-count: 1000  # 每个连接的最大使用次数pool-prepared-statements: false  # 是否开启 PSCachemax-open-prepared-statements: 50  # PSCache 允许的最大预编译 SQL 数# Druid 监控配置filters: stat,wall,log4j2  # 启用监控统计拦截的过滤器(SQL监控、防火墙、日志)# 监控页面配置stat-view-servlet:enabled: true  # 启用内置监控页面url-pattern: /druid/*  # 监控页面路径login-username: admin  # 访问监控页面的用户名login-password: admin  # 访问监控页面的密码reset-enable: false  # 是否允许重置统计数据allow: 127.0.0.1  # 允许访问的 IP 白名单deny: 192.168.0.1  # 禁止访问的 IP 黑名单# Web 监控配置web-stat-filter:enabled: true  # 开启 Web-JDBC 关联监控url-pattern: /*  # 监控所有请求exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"  # 排除静态资源和监控路径session-stat-enable: true  # 启用 Session 统计session-stat-max-count: 1000  # Session 最大数量# SQL 慢查询日志配置filter:stat:# 是否开启 FilterStat,默认trueenabled: true# 是否开启 慢SQL 记录,默认falselog-slow-sql: true# 慢 SQL 的标准,默认 3000,单位:毫秒slow-sql-millis: 5000# 合并多个连接池的监控数据,默认falsemerge-sql: false# 日志配置,采用 SLF4Jslf4j:enabled: true  # 启用日志statement-log-error-enabled: true  # 开启 SQL 语句错误日志statement-create-after-log-enabled: falsestatement-close-after-log-enabled: falseresult-set-open-after-log-enabled: falseresult-set-close-after-log-enabled: false
    
  • 上面配置主要分为三部分:数据源配置、数据库连接池配置和Druid监控配置

3.3 数据源配置解析

  • 下面部分属于数据源配置:
    spring:datasource:url: jdbc:mysql://localhost:3306/springboot?useSSL=false&autoReconnect=true&characterEncoding=utf8&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8&allowMultiQueries=true  # 数据库地址driver-class-name: com.mysql.cj.jdbc.Driver  # MySQL 8.0 及以上需要 cj,5.7 以下可去掉 cjusername: root  # 数据库用户名password: abc123  # 数据库密码type: com.alibaba.druid.pool.DruidDataSource  # 使用 Druid 数据源
    
  • 配置解析:
    • url:定义数据库连接的详细信息,包括:
      • localhost:3306(服务器地址和端口)
      • springboot(数据库名称)
      • 连接参数
    • driver-class-name:指定数据库连接的驱动,MySQL 8.x使用 com.mysql.cj.jdbc.Driver
    • usernamepassword:提供访问数据库的身份凭证
    • type:指定数据库连接池的实现,配置为 com.alibaba.druid.pool.DruidDataSource
  • url连接参数详解:
    • useUnicode=true&characterEncoding=UTF-8
      • 确保数据库与应用之间的字符编码一致,防止乱码问题
      • 推荐使用 utf8mb4 以支持更多字符(如表情符号)
    • serverTimezone=UTC
      • 指定数据库服务器的时区,避免时间处理错误
      • 可选值:
        • UTC:世界标准时间,比北京时间(CST)早 8 小时
        • Asia/Shanghai:中国标准时间(推荐)
      • 说明:MySQL 6.0 及以上的 com.mysql.cj.jdbc.Driver 需要显式指定时区,否则可能导致时区不匹配的异常
    • useSSL=false
      • 指定是否启用 SSL 连接
      • 在生产环境(如 Linux 服务器部署)通常关闭 SSL 连接,以减少额外的安全配置
      • 建议:在公共网络或云数据库环境中建议开启 SSL
    • autoReconnect=true&failOverReadOnly=false
      • autoReconnect=true:允许 JDBC 驱动在连接意外断开时自动重连(已弃用,推荐使用连接池)
      • failOverReadOnly=false:防止发生故障转移时连接错误地设置为只读模式
    • allowPublicKeyRetrieval=true
      • 允许客户端从 MySQL 服务器检索公钥,以进行密码验证
      • 安全建议:生产环境下尽量避免使用该参数,建议启用 SSL 进行安全通信
    • zeroDateTimeBehavior=convertToNull
      • 当数据库中的日期时间值为 0000-00-00 00:00:00 时,转换为 null,避免 Java 应用程序在处理无效日期值时出错
    • rewriteBatchedStatements=true
      • 启用批量执行优化,提高批量 INSERTUPDATE 的执行效率
      • 适用于大数据量操作,不适用于 SELECT 查询

3.4 连接池配置详解

  • 下面是Druid连接池的配置:

    druid:# 连接池基本配置initial-size: 5  # 初始化连接数min-idle: 10  # 最小空闲连接数max-active: 20  # 最大连接数max-wait: 60000  # 最大等待时间(毫秒)time-between-eviction-runs-millis: 60000  # 多少毫秒执行一次空闲连接回收min-evictable-idle-time-millis: 600000  # 连接最小生存时间(毫秒)max-evictable-idle-time-millis: 1800000  # 连接最大生存时间(毫秒)# 连接校验配置validation-query: SELECT 1  # 用于测试连接是否可用的 SQL 语句validation-query-timeout: 2000  # SQL 校验超时时间(毫秒)test-on-borrow: false  # 获取连接时是否检测(影响性能,建议关闭)test-on-return: false  # 归还连接时是否检测(影响性能,建议关闭)test-while-idle: true  # 空闲时是否检测(推荐开启)# 连接池优化配置phy-max-use-count: 1000  # 每个连接的最大使用次数pool-prepared-statements: false  # 是否开启 PSCachemax-open-prepared-statements: 50  # PSCache 允许的最大预编译 SQL 数
    
  • 配置属性列表介绍:

配置项名称缺省值说明
connectProperties{}map方式放入自定义的key和value,在Filter等地方可以获取该信息进行相应逻辑控制
connectionPropertiesnull字符串方式放入自定义的key和value,键值对用分号隔开,比如“a=b;c=d”,传入空白字符串表示清空属性,实际拆分字符串后赋值给connectProperties,在Filter等地方可以获取该信息进行相应逻辑控制
connectTimeout0新增的控制创建连接时的socket连接最大等待超时,单位是毫秒,默认0表示永远等待,工作原理是在创建连接时将该值设置到对应数据库驱动的属性信息中由其JDBC驱动进行控制
connectionInitSqls[]数组方式定义物理连接初始化的时候执行的1到多条sql语句,比如连接MySQL数据库使用低版本驱动的情况下,想使用utf8mb4,则可以配置sql为: set NAMES ‘utf8mb4’
createSchedulernull可以使用定时线程池方式异步创建连接,比起默认的单线程创建连接方式,经实际验证这种更可靠
dbTypenull对于不是Druid自动适配支持的db类型,可以强制指定db类型,字符串值来自com.alibaba.druid.DbType的枚举名
destroySchedulernull可以使用定时线程池方式异步创建连接,比起默认的单线程创建连接方式,经实际验证这种更可靠
driverClassName根据url自动识别这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName
exceptionSorternull当数据库抛出一些不可恢复的异常时,抛弃连接
failFastfalsenull
filters属性类型是逗号隔开的字符串,通过别名的方式配置扩展插件,插件别名列表请参考druid jar包中的 /META-INF/druid-filter.properties,常用的插件有: 监控统计用的filter:stat 日志用的filter:log4j 防御sql注入的filter:wall 防御sql注入的filter:wall
initialSize0初始化数据源时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
keepAlivefalse连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis,则会执行keepAlive操作。实际项目中建议配置成true
keepAliveBetweenTimeMillis120000null
logAbandonedfalse在开启removeAbandoned为true的情况,可以开启该设置,druid在销毁未及时关闭的连接时,则会输出日志信息,便于定位连接泄露问题
loginTimeout单位是秒,底层调用DriverManager全局静态方法
maxActive8连接池最大活跃连接数量,当连接数量达到该值时,再获取新连接时,将处于等待状态,直到有连接被释放,才能借用成功
maxEvictableIdleTimeMillis25200000null
maxIdle8已经彻底废弃,配置了也没效果,以maxActive为准
maxOpenPreparedStatements10null
maxPoolPreparedStatementPerConnectionSize10要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
maxWait-1获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
minEvictableIdleTimeMillis1800000连接保持空闲而不被驱逐的最小时间
minIdle0连接池最小空闲数量
nameDataSource-****配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。如果没有配置,将会生成一个名字,格式是:“DataSource-” + System.identityHashCode(this). 另外配置此属性至少在1.0.5版本中是不起作用的,强行设置name会出错。详情-点此处。
numTestsPerEvictionRun3不再使用,已经彻底废弃,一个DruidDataSource只支持一个EvictionRun
passwordnull连接数据库的密码。如果你不希望密码直接写在配置文件中,可以使用passwordCallback进行配置,或者使用ConfigFilter。详细看这里
passwordCallbacknull可以自定义实现定制的PasswordCallback,然后实现定制的密码解密效果
phyTimeoutMillis-1强制回收物理连接的最大超时时长,大于0的情况下才生效,当物理创建之后存活的时长超过该值时,该连接会强制销毁,便于重新创建新连接,建议可以配置成7小时的毫秒值,比如25200000,这样可以规避MySQL的8小时连接断开问题
poolPreparedStatementsfalse是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
proxyFilters类型是List<com.alibaba.druid.filter.Filter>,如果同时配置了filters和proxyFilters,是组合关系,并非替换关系
queryTimeout0控制查询结果的最大超时,单位是秒,大于0才生效,最终底层调用是java.sql.Statement.setQueryTimeout(int)
removeAbandonedfalse是否回收泄露的连接,默认不开启,建议只在测试环境设置未开启,利用测试环境发现业务代码中未正常关闭连接的情况
removeAbandonedTimeoutMillis300000开启回收泄露连接的最大超时,默认300秒表示连接被借出超过5分钟后,且removeAbandoned开启的情况下,强制关闭该泄露连接
socketTimeout0新增的控制创建连接时的socket最大读超时,单位是毫秒,默认0表示永远等待,配置成10000则表示db操作如果在10秒内未返回应答,将抛出异常,工作原理是在创建连接时将该值设置到对应数据库驱动的属性信息中由其JDBC驱动进行控制
testOnBorrowfalse申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能,其实一般情况下都可以开启,只有性能要求极其高且连接使用很频繁的情况下才有必要禁用。
testOnReturnfalse归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能,这个一般不需要开启。
testWhileIdletrue建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
timeBetweenEvictionRunsMillis60000有两个含义: 1) Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。 2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明
transactionQueryTimeout0控制查询结果的最大超时,单位是秒,大于0才生效,最终是在开启事务的情况下底层调用java.sql.Statement.setQueryTimeout(int)
url连接数据库的url,不同数据库不一样。例如: mysql : jdbc:mysql://10.20.153.104:3306/druid2 oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto
usernamenull连接数据库的用户名
validationQuerynull用来检测连接是否有效的sql,要求是一个查询语句,常用select ‘x’。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。
validationQueryTimeout-1单位:秒,检测连接是否有效的超时时间,大于0才生效。底层调用jdbc Statement对象的void setQueryTimeout(int seconds)方法

3.5 Druid监控配置

  • 下面是Druid监控配置:
      # Druid 监控配置filters: stat,wall,slf4j  # 启用监控统计拦截的过滤器(SQL监控、防火墙、日志)# 监控页面配置stat-view-servlet:enabled: true  # 启用内置监控页面url-pattern: /druid/*  # 监控页面路径login-username: admin  # 访问监控页面的用户名login-password: admin  # 访问监控页面的密码reset-enable: false  # 是否允许重置统计数据allow: 127.0.0.1  # 允许访问的 IP 白名单deny: 192.168.0.1  # 禁止访问的 IP 黑名单# Web 监控配置web-stat-filter:enabled: true  # 开启 Web-JDBC 关联监控url-pattern: /*  # 监控所有请求exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"  # 排除静态资源和监控路径session-stat-enable: true  # 启用 Session 统计session-stat-max-count: 1000  # Session 最大数量# SQL 慢查询日志配置filter:stat:enabled: true  # 是否开启 FilterStat,默认truelog-slow-sql: true  # 是否开启 慢SQL 记录,默认falseslow-sql-millis: 5000  # 慢 SQL 的标准,默认 3000,单位:毫秒merge-sql: false  # 合并多个连接池的监控数据,默认false# 日志配置,采用 SLF4Jslf4j:enabled: true  # 启用日志statement-log-error-enabled: true  # 开启 SQL 语句错误日志statement-create-after-log-enabled: falsestatement-close-after-log-enabled: falseresult-set-open-after-log-enabled: falseresult-set-close-after-log-enabled: false
    
  • 配置详解:
    • filters: 启用 Druid 的过滤器,stat 用于SQL监控,wall 用于防火墙,log4j2 用于日志记录。
    • stat-view-servlet: 启用 Druid 内置监控页面,配置路径、用户名、密码等。可以通过 url-pattern 指定访问路径。
    • web-stat-filter: 配置 Web-JDBC 关联监控,可以监控 HTTP 请求的详细数据,如 Session 信息。
    • filter.stat: 配置 Druid 的 SQL 慢查询日志功能,记录执行时间超过设定阈值的 SQL 查询。
    • slf4j: 配置 Druid 使用 SLF4J 进行日志输出,开启 SQL 语句错误日志、创建语句日志等。

3.6 总结

  • 使用 Druid 连接池的核心关键点在于选择与项目所使用的 Spring Boot 版本兼容的 Druid 依赖版本。
    • 如果版本选择不当,虽然 Druid 连接池仍然可以正常使用,但后台的 SQL 监控功能可能无法正常工作。
    • 毛毛张在其文章中详细介绍了不同版本的兼容性问题,通常,如果遇到 SQL 后台监控无法显示的情况,可以尝试升级到 Druid 的最新版本,以解决此类问题。

4 总结

  • 更多关于Druid连接池的介绍可以查看官网连接:https://github.com/alibaba/druid/tree/master
  • 更多关于Druid配置文件的介绍可以查看官网的配置文件的介绍:https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter#如何配置-filter

参考文献

  • https://juejin.cn/post/7329033419328307226
  • https://zhuanlan.zhihu.com/p/686960884
  • https://blog.csdn.net/hansome_hong/article/details/124320410
  • https://juejin.cn/post/7224499191962714171#heading-2
  • https://blog.csdn.net/hansome_hong/article/details/124320410
  • https://pdai.tech/md/spring/springboot/springboot-x-mysql-HikariCP.html
  • https://blog.csdn.net/doubiy/article/details/131578389
  • https://www.cnblogs.com/lyluoye/p/16627840.html
  • https://github.com/brettwooldridge/HikariCP
  • https://www.cnblogs.com/zhaojinhui/p/17579010.html
  • https://javabetter.cn/springboot/mysql-druid.html
  • https://juejin.cn/post/7374356945702322214
  • https://blog.csdn.net/munangs/article/details/124724091
  • https://zhuanlan.zhihu.com/p/636184214
  • https://github.com/alibaba/druid/wiki/DruidDataSource配置属性列表

都看到这了,不妨一键三连再走吧!

🌈欢迎和毛毛张一起探讨和交流!
联系方式点击下方个人名片

相关文章:

【SpringBoot教程】Spring Boot + MySQL + Druid连接池整合教程

&#x1f64b;大家好&#xff01;我是毛毛张! &#x1f308;个人首页&#xff1a; 神马都会亿点点的毛毛张 前面毛毛张介绍过HikariCP连接池&#xff0c;今天毛毛张来介绍一下Druid连接池&#xff0c;SpringBoot 2.0以上默认使用HikariCP数据源&#xff0c;但是也要学会使用…...

基于SpringBoot实现的宠物领养系统平台功能一

一、前言介绍&#xff1a; 1.1 项目摘要 宠物领养需求增加&#xff1a;随着人们生活水平的提高和对宠物养护意识的增强&#xff0c;越来越多的人选择领养宠物作为家庭的一员。这导致了宠物领养需求的显著增加。 传统领养方式存在问题&#xff1a;传统的宠物领养方式&#xf…...

【DeepSeek 学C++】std::atomic 用于线程控制,和内存强顺序一致性

std::atomic<bool> workerTerminate_{}; std::atomic<bool> workerTerminate_{}; 是一个原子布尔变量的声明&#xff0c;变量名为 workerTerminate_。这种变量通常用于多线程编程中&#xff0c;用来控制或通知工作线程的终止。使用 std::atomic 可以确保对该变量的…...

计算存储一幅大小为 1024×10241024×1024、256 灰度级的图像所需的字节数

1. 图像的基本信息 图像分辨率&#xff1a;1024102410241024&#xff0c;表示图像有 1024 行和 1024 列&#xff0c;总像素数为&#xff1a; 102410241,048,576 像素102410241,048,576 像素 灰度级&#xff1a;256 灰度级&#xff0c;表示每个像素的灰度值可以用 256 个不同的值…...

Flutter 网络请求与数据处理:从基础到单例封装

Flutter 网络请求与数据处理&#xff1a;从基础到单例封装 在 Flutter 开发中&#xff0c;网络请求是一个非常常见的需求&#xff0c;比如获取 API 数据、上传文件、处理分页加载等。为了高效地处理网络请求和数据管理&#xff0c;我们需要选择合适的工具并进行合理的封装。 …...

从开发到部署:EasyRTC嵌入式视频通话SDK如何简化实时音视频通信的集成与应用

嵌入式设备和视频综合管理平台均支持B/S架构。在B/S架构下&#xff0c;传统的视频观看方式依赖于微软的OCX控件&#xff0c;然而OCX控件的使用正面临越来越多的挑战&#xff1a; 首先&#xff0c;用户需要安装浏览器插件、调整浏览器安全级别&#xff0c;并允许ActiveX控件弹出…...

Jeesite5:Star24k,Spring Boot 3.3+Vue3实战开源项目,架构深度拆解!让企业级项目开发效率提升300的秘密武器

嗨&#xff0c;大家好&#xff0c;我是小华同学&#xff0c;关注我们获得“最新、最全、最优质”开源项目和高效工作学习方法 企业级应用开发的需求日益增长。今天&#xff0c;我们要介绍的是一个在GitHub上广受好评的开源项目——Jeesite5。这不仅是一个技术框架&#xff0c;更…...

C++(23):lambda可以省略()

C越来越多的使用了lambda&#xff0c;C23也进一步的放宽了对lambda的限制&#xff0c;这一次&#xff0c;如果lambda没有参数列表&#xff0c;那么可以直接省略掉()&#xff1a; #include <iostream> using namespace std;void func() {auto f []{cout<<"in…...

vue3之echarts柱状图-圆锥加自动轮播

vue3之echarts柱状图-圆锥加自动轮播 效果&#xff1a; 版本 "echarts": "5.4.2" 核心代码&#xff1a; <template><div ref"echartRef" class"chart"></div><svg><linearGradient v-for"(item, i…...

Qt中利用httplib调用https接口

httplib中如果要调用https接口&#xff0c;需要开启OPENSSL支持&#xff0c;经过半天坑爹得摸索&#xff0c;总结下经验。 1&#xff0c;下载 并安装Win64OpenSSL 地址如下&#xff0c;我Qt版本是5.15.2 &#xff0c;openssl选择的是 64位&#xff08;Win64OpenSSL-3_3_3.msi…...

深度学习04 数据增强、调整学习率

目录 数据增强 常用的数据增强方法 调整学习率 学习率 调整学习率 ​调整学习率的方法 有序调整 等间隔调整 多间隔调整 指数衰减 余弦退火 ​自适应调整 自定义调整 数据增强 数据增强是通过对训练数据进行各种变换&#xff08;如旋转、翻转、裁剪等&#xff09;&am…...

卷积神经网络之AlexNet经典神经网络,实现手写数字0~9识别

深度学习中较为常见的神经网络模型AlexNet&#xff0c;AlexNet 是一个采用 GPU 训练的深层 CNN&#xff0c;本质是种 LeNet 变体。由特征提取层的5个卷积层两个下采样层和分类器中的三个全连接层构成。 先看原理&#xff1a; AlexNet网络特点 采用 ReLU 激活函数&#xff0c;…...

建筑兔零基础自学python记录22|实战人脸识别项目——视频人脸识别(下)11

这次我们继续解读代码&#xff0c;我们主要来看下面两个部分&#xff1b; 至于人脸识别成功的要点我们在最后总结~ 具体代码学习&#xff1a; #定义人脸名称 def name():#预学习照片存放位置path M:/python/workspace/PythonProject/face/imagePaths[os.path.join(path,f) f…...

全球化趋势下中资企业出海投资及合规运营实战分享

企业全球化布局需构建“战略-架构-合规-运营”四位一体体系&#xff0c;通过灵活的投资架构、精准的税务规划、本土化运营和ESG融合&#xff0c;实现风险可控的海外扩张。核心策略包括&#xff1a; 供应链多节点布局&#xff08;至少3个国家备份产能&#xff09;&#xff1b;融…...

2025-2-19 leetcode刷题情况(二叉树)

一、226.翻转二叉树 1.题目描述 给你一棵二叉树的根节点root&#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点 2.代码 3.思路 递归遍历&#xff08;DFS&#xff09;交换每个节点的左 / 右子节点&#xff0c;即可生成二叉树的镜像。 递归解析&#xff1a; 终止条件&a…...

Linux常见命令

文件和目录操作命令 cd&#xff1a;用于切换目录。例如&#xff0c;cd /home/user 可进入 /home/user 目录&#xff1b;cd.. 可返回上一级目录。ls&#xff1a;用于列出目录内容。ls 直接列出当前目录下的文件和文件夹&#xff1b;ls -l 以详细列表形式显示&#xff1b;ls -a 显…...

C++ 一篇读懂“值传递”和“地址传递”

让我们通过一个简单的、形象的比喻来帮助你理解“值传递”和“地址传递”是如何影响实参的。 1. 值传递 想象你有一个 **信封**&#xff08;代表变量&#xff09;&#xff0c;里面放着一张纸条&#xff08;代表数据&#xff09;。你决定把这个信封寄给一个朋友&#xff0c;让他…...

我用AI做数据分析之数据清洗

我用AI做数据分析之数据清洗 AI与数据分析的融合效果怎样&#xff1f; 这里描述自己在使用AI进行数据分析&#xff08;数据清洗&#xff09;过程中的几个小故事&#xff1a; 1. 变量名的翻译 有一个项目是某医生自己收集的数据&#xff0c;变量名使用的是中文&#xff0c;分…...

韩国哈希散列算法DHA-256

韩国哈希散列算法DHA-256 DHA-256是在2005年11月由NIST举行的Hash研讨会(Cryptographic Hash Workshop)上提出的。DHA-256压缩函数将长度为512比特的分组&#xff0c;压缩成长度为256比特的串&#xff0c;总共迭代64步&#xff0c;扩展的消息字在步函数中使用了两次。 DHA-25…...

【愚公系列】《Python网络爬虫从入门到精通》022-Splash的爬虫应用

标题详情作者简介愚公搬代码头衔华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,亚马逊技领云博主,51CTO博客专家等。近期荣誉2022年度…...

Golang深度学习

前言 在2009年&#xff0c;Google公司发布了一种新的编程语言&#xff0c;名为Go&#xff08;或称为Golang&#xff09;&#xff0c;旨在提高编程效率、简化并发编程&#xff0c;并提供强大的标准库支持。Go语言的设计者们希望通过Go语言能够解决软件开发中的一些长期存在的问…...

React(8)

封装评论列表的Item组件 实现父传子以及子组件调用父组件方法 import { useEffect, useState } from "react"; import "./index.css"; import _ from "lodash"; import classNames from "classnames"; import axios from "axio…...

自制AirTag,支持安卓/鸿蒙/PC/Home Assistant,无需拥有iPhone

苹果的AirTag很贵&#xff0c;虽然某强北有平价代替品&#xff0c;但是仍需要苹果设备才能绑定&#xff0c;才能查看位置。不支持安卓/鸿蒙/PC&#xff0c;也不支持集成到Home Assistant中。 AirTag 的原理 每个AirTag都会发送一个蓝牙信号&#xff0c;其可以被临近的苹果设备…...

docker修改镜像默认存储路径(基于页面迁移)

文章目录 1、停止服务2、拷贝镜像3、docker界面设置路径4、重新启动服务5、重启电脑 1、停止服务 桌面底部右键打开任务管理器 停止docker服务 2、拷贝镜像 从原目录拷贝到新的目录下&#xff0c;新的目录自己定&#xff0c;如果没有权限&#xff0c;需要先对原文件添加权限…...

10. 软件设计架构-经典架构问题

文章目录 前言一、高并发场景下的系统崩溃1. 问题描述2. 解决方案&#xff1a;3. 案例分析&#xff1a;电商秒杀系统 二、单体架构到微服务的拆分陷阱1. 问题描述2. 解决方案&#xff1a;3. 案例分析&#xff1a;在线教育平台拆分 三、分布式系统中的数据一致性难题1. 问题描述…...

Qt学习(五)自定义对话框,多窗口开发---添加设计师类, MDI多窗口开发

一 对话框 实现功能&#xff1a;打开文件&#xff0c;选择目录&#xff0c;保存文件&#xff0c;选择颜色&#xff0c;选择字体&#xff0c;输入信息&#xff0c; 消息提示框 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE na…...

【部署优化篇三】《DeepSeek边缘计算实战:把目标检测模型塞进树莓派,让AI在巴掌大的设备上“开天眼“》

“谁说只有超级计算机才能跑AI?今天咱们就要在树莓派上玩转DeepSeek目标检测,让这个巴掌大的小盒子变成会‘看’世界的智能终端!” 本文手把手教你从零开始,把最潮的目标检测模型塞进树莓派。全程高能预警,建议准备好你的树莓派4B/5和散热风扇,咱们这就开启边缘计算的魔法…...

深入浅出CSS复合选择器:掌控元素关系与层级选择

目录 前言 一、子代选择器&#xff08;Descendant Selector&#xff09; 1. 什么是子代选择器&#xff1f; 2. 基本语法 3. 示例 4. 注意事项 二、直接子元素选择器&#xff08;Child Selector&#xff09; 1. 什么是直接子元素选择器&#xff1f; 2. 基本语法 3. 示例…...

LLM 推理中推理-时间计算技巧

25年2月来自香港科技大学广州分校的论文“Bag of Tricks for Inference-time Computation of LLM Reasoning”。 随着大语言模型 (LLM) 的进步&#xff0c;解决复杂的推理任务越来越受到关注。推理-时间计算方法&#xff08;例如 Best-of-N、波束搜索等&#xff09;特别有价值…...

【模板】图论 最短路 (Floyd+SPFA+Dijkstra)

FloydSPFADijkstra 温故而知新&#xff0c;这三种算法都是求最短路问题常用的算法&#xff08;特别是Dijkstra) 1.Floyd &#xff08;多源最短路&#xff09; 基于动态规划思想&#xff0c;时间复杂度为 O ( N 3 ) O(N^3) O(N3) 较高。 注意点&#xff1a; 初始化距离为INF…...

vite-vue-ts使用arco-design-vue定制主题的后动态变更主题思路

定制主题的后动态变更主题思路 安装依赖与主题定制动态变更主题过程尝试修改主题色&#xff08;结果失败&#xff09;尝试修改主题色&#xff08;结果成功&#xff0c;但是hover的主题色没有变&#xff0c;未覆盖10个梯度的色值&#xff09;根据主题色实现10个梯度颜色实现10个…...

递归爬取网页测试

我们正在做基于大模型的数据分析平台。 当前需要测试ezdata的递归爬取功能&#xff0c;爬取到第几层 测试网址 https://blog.csdn.net/m0_68177611/article/details/144936089...

【论文学习】RVS-FDSC:一种基于四方向条带卷积的视网膜血管分割方法以增强特征提取

写在前面&#xff1a;本博客仅作记录学习之用&#xff0c;部分图片来自网络&#xff0c;如需引用请注明出处&#xff0c;同时如有侵犯您的权益&#xff0c;请联系删除&#xff01; 文章目录 前言论文论文内容RSC模块MSPF2 模块RPDA模块 实验效果 总结互动致谢参考往期回顾 前言…...

交友项目-交友软件简介

一、 项目背景 在线社交是互联网时代的产物&#xff0c;已成为互联网用户的基础需求之一。移动互联网自2003年起快速发展&#xff0c;促使在线社交逐渐从PC端转移至移动端。移动社交最初以熟人社交为主&#xff0c;以维系熟人关系、共享资源信息的形式存在。随着人们交友需求的…...

新手向:SpringBoot后端查询到数据,前端404?(附联调时各传参方式注解总结-带你一文搞定联调参数)

前言&#xff1a; 在 Spring Boot 项目开发中&#xff0c;后端小伙伴可能经常遇到这样诡异的场景&#xff1a; 后台日志显示查询到了数据&#xff0c;但前端却一脸懵逼地告诉你 404 Not Found&#xff1f;接口明明写好了&#xff0c;Postman 直接访问却提示找不到&#xff1f…...

Elasticsearch7.6.2 安装过程

一. 安装JDK1.8 &#xff08;1&#xff09;创建安装目录 mkdir /usr/local/java/ &#xff08;2&#xff09;解压至安装目录 tar -zxvf jdk-8u251-linux-x64.tar.gz -C /usr/local/java/ &#xff08;3&#xff09;设置环境变量 vim /etc/profile 在末尾添加 export JA…...

汇能感知的光谱相机/模块产品有哪些?

CM020A 分辨率&#xff1a;1600H1200V 光谱范围&#xff1a;350~950nm 光谱分辨率&#xff1a;1nm 接口&#xff1a;USB2.0 帧率&#xff1a;16001200 (6帧) 输出格式&#xff1a;Raw 8bit FOV&#xff1a;D73.5H58.8V44.1 相机尺寸&#xff1a;505055mm VM02S10 分辨率…...

【机器学习】K折交叉验证(K-Fold Cross-Validation)

文章目录 K折交叉验证步骤详解一. 核心目标二. 具体步骤与操作三. 关键变体与场景适配3.1 分层K折交叉验证3.2 时间序列K折交叉验证3.3 留一法&#xff08;LOO&#xff09;3.4 重复K折交叉验证 四. 实践注意事项五. Python代码示例六. 总结 K折交叉验证步骤详解 一. 核心目标 …...

【核心算法篇十九】《 DeepSeek因果推断:双重差分模型如何破解政策评估的「时空难题」》

一、当AB实验不可行时,我们该相信什么?(因果推断困局解析) 假设某城市推出「夜间地铁免费」政策,市长想知道这个政策是否真的提升了夜间经济。这时候你会发现: 1️⃣ 无法克隆城市:不能同时存在一个「实施政策」和「不实施政策」的平行宇宙 2️⃣ 数据混杂严重:疫情反…...

使用vue3框架vue-next-admin导出列表数据

在 Vue3 中实现 Excel 导出功能可以通过以下步骤完成&#xff0c;这里使用 xlsx 库来实现前端 Excel 导出&#xff1a; 1. 安装依赖 npm install xlsx file-saver # 或 yarn add xlsx file-saver2. 实现代码示例 需要在当前页引入 import * as XLSX from "xlsx";注…...

机器学习(1)安装Pytorch

1.安装命令 pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 2.安装过程Log&#xff1a; Looking in indexes: https://download.pytorch.org/whl/cu118 Co…...

讯方·智汇云校华为官方授权培训机构

1.官方授权 讯方智汇云校是华为领先级授权培训机构&#xff08;华为授权培训合作伙伴&#xff08;HALP&#xff09;体系&#xff0c;分为认证、优选、领先三个等级&#xff0c;领先级是HALP最高级&#xff09;&#xff0c;代表着华为对培训合作伙伴在专业能力、师资队伍、合作…...

彻底理解零拷贝技术,zero-copy

计算机处理的任务大体可以分为两类&#xff1a;CPU密集型与IO密集型。当前流行的互联网应用更多的属于IO密集型&#xff0c;传统的IO标准接口都是基于数据拷贝的&#xff0c;这篇文章我们主要关注该怎样从数据拷贝的角度来优化IO性能&#xff0c;让你的程序在IO性能方面赶超P8。…...

使用 MySQL 从 JSON 字符串提取数据

使用 MySQL 从 JSON 字符串提取数据 在现代数据库管理中&#xff0c;JSON 格式因其灵活性而广泛使用。然而&#xff0c;当数据存储在 JSON 中时&#xff0c;我们经常需要将其转换为更易于处理的格式。本篇文章将通过一个具体的 SQL 查询示例&#xff0c;展示如何从存储在 MySQ…...

矛盾(WEB)

##解题思路 打开靶场就是一段自相矛盾的代码&#xff0c;既要num是数字类型&#xff0c;又要判断为1 这种情况我们会想到弱类型的编程语言&#xff0c;插件查看过后&#xff0c;php就是弱类型的语言&#xff0c;此处并非是严格相等&#xff0c;只是 因此可以根据弱类型编程语言…...

优先队列(典型算法思想)—— OJ例题算法解析思路

目录 一、1046. 最后一块石头的重量 - 力扣&#xff08;LeetCode&#xff09; 算法代码&#xff1a; 代码思路 使用优先队列&#xff08;大根堆&#xff09; 将所有石头放入堆中 模拟碰撞过程 返回最后的重量 代码解析 时间复杂度 示例 输入 输出 二、703. 数据流…...

IGBT的损耗性分析

铝合金外壳设计器地址:嘉立创铝合金外壳/壳体/盒型-让您的产品更出彩 IGBT和MOS的损耗谁大: 电子元器件常见失效模式: 电子元器件的失效模式多种多样,以下是一些常见的失效模式及其原因: 开路: 原因:内部连接断开、焊点断裂、导线断裂等。 影响:电流无法通过,电路中断。…...

TypeScript跟js,es6这些的区别

TypeScript 一、TypeScript 是什么 想象 JavaScript 是一个自由奔放的艺术家&#xff0c;它在创作&#xff08;编写代码&#xff09;时不受太多约束&#xff0c;非常灵活&#xff0c;但有时也容易犯错且难以调试。而 TypeScript 就像是给这位艺术家配备了一套精确的工具和规范…...

单例模式代码示例

饿汉式&#xff1a;在类加载时就创建单例实例&#xff0c;线程安全。代码如下&#xff1a; public class Singleton {// 私有静态实例private static final Singleton instance new Singleton();// 私有构造函数private Singleton() {}// 公共访问方法public static Singleto…...

掌握 ElasticSearch的 _source 过滤

掌握 ElasticSearch的 _source 过滤 1. 引言2. _source 元数据基础2.1 什么是 _source 字段&#xff1f;2.2 _source 的基本用法 3. 禁用 _source3.1 如何禁用 _source 字段3.2 禁用 _source 的利弊3.3 最佳实践建议 4. _source 数据源过滤4.1 为什么需要数据源过滤&#xff1f…...