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

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

在前面一篇文章中毛毛张介绍了SpringBoot中数据源与数据库连接池相关概念,今天毛毛张要分享的是关于SpringBoot整合HicariCP连接池相关知识点以及底层源码分析

文章目录

  • 1 HicariCP连接池概述
    • 1.1 HicariCP连接池简介
  • 2 快速入门案例
    • 2.1 后端代码
      • 2.1.1 创建项目
      • 2.1.2 导入依赖
        • 方式1:手动导入 `HikariCP` 依赖
        • 方式 2:自动引入依赖 - 推荐
        • 本项目完整依赖
      • 2.1.3 编写配置文件
      • 2.1.4 初始化数据库并创建对应实体类
      • 2.1.5 编写响应封装与前端展示VO
      • 2.1.6 编写业务逻辑
      • 2.1.7 跨域资源共享
      • 2.1.8 启动类
      • 2.1.9 测试
    • 2.2 前端代码
  • 3 配置详解
    • 3.1 常见配置
    • 3.2 数据源配置解析
    • 3.3 连接池配置详解
  • 4 底层源码解析
    • 4.1 SpringBoot自动初始化配置
    • 4.2 默认的数据源
  • 参考文献

1 HicariCP连接池概述

  • 在上面介绍过HicariCPSpringBoot2.0之后默认的数据库连接池,特点就是:简单,高效,史称最快的数据库连接池,毛毛张将从以下几个方面展开对HicariCP连接池的介绍:
    • 首先简单介绍以下HicariCP连接池
    • 然后通过一个案例来帮助大家能够快速使用HicariCP连接池
    • 接着通过分析SpringBoot的底层代码来解释SringBoot默认的数据库连接池为HicariCP

1.1 HicariCP连接池简介

  • HikariCP 是一个高性能的JDBC数据库连接池,基于BoneCP做了多项优化,旨在提供更高的并发性能和更低的延迟。自SpringBoot 2.x版本后(自然也包括SpringBoot 3.x),HikariCP成为默认的数据库连接池,只需导入HikariCPJAR包并配置相关参数,即可无缝集成并优化数据库连接池管理。
  • HikariCP 的高性能优化主要体现在以下两个方面:
    • FastList 替代 ArrayList
      • 传统的数据库连接池大多使用ArrayList存储Statement,HikariCP 自定义了FastList来优化这一操作。FastList的优化主要体现在两个方面:
        • 取消 ArrayListget() 方法中的范围检查(range check)。由于数据库连接池管理的 List 中的索引合法性有保证,因此不需要每次访问都进行索引合法性检查。
        • 改变 ArrayListremove() 操作的遍历方式,采用从尾部开始遍历,而不是从头开始。由于连接池中的连接通常是逆序释放的(后获取的连接先释放),这样优化后,每次关闭连接时可以更高效地找到需要释放的资源,提升了效率。
    • ConcurrentBag 替代阻塞队列
      • 大多数传统数据库连接池使用两个阻塞队列(idlebusy)来管理空闲连接和忙碌连接,使用 Lock 机制来处理线程竞争,但这种方式在高并发场景下可能会导致性能瓶颈。HikariCP通过使用 ConcurrentBag 替代了传统的阻塞队列,极大地减少了锁的竞争,提高了并发性能。
      • ConcurrentBag的核心工作原理:
        • sharedList:存储所有数据库连接的共享队列,使用 CopyOnWriteArrayList 类型,支持并发操作。
        • threadList:线程本地存储,避免了线程竞争,每个线程会缓存自己获取的连接。
        • waiters:等待连接的线程数,使用 AtomicInteger 类型。
        • handoffQueue:分配数据库连接的核心队列,使用 SynchronousQueue 类型,负责将空闲连接分配给请求的线程。
      • 这种设计通过减少线程竞争和优化连接分配,提高了连接池的效率,特别适合高并发的环境。
  • 其他优化
    • 字节码精简:HikariCP 在字节码上进行了优化,编译后的字节码量极少,这样可以使得更多的代码被 CPU 缓存,从而提高程序的执行效率。减少字节码的大小是提高性能的基础,HikariCP 在这方面做得非常好。
    • 优化代理和拦截器:HikariCP 对代理和拦截器的实现进行了精简。例如,它的 Statement 代理类仅有 100 行代码,是 BoneCP 的十分之一。这减少了性能开销,确保数据库连接池在执行 SQL 时更加高效。
    • 自定义集合类型(FastStatementList):为了提高对 Statement 的管理效率,HikariCP 使用了自定义的集合类型 FastStatementList 来替代传统的 ArrayList。这样避免了每次获取元素时的范围检查,并且采用逆序遍历的方式来优化 remove() 操作,使得关闭连接时更加高效。
    • 自定义集合类型(ConcurrentBag):HikariCP 为了优化并发读写效率,采用了 ConcurrentBag 代替传统的阻塞队列。这不仅提高了数据库连接分配的效率,而且减少了锁的竞争,显著提升了高并发场景下的性能。
    • 针对 BoneCP 缺陷的优化:HikariCP 在设计时,针对 BoneCP 中的一些缺陷进行了优化,特别是在处理 CPU 时间片内的耗时方法调用时,进一步提高了性能。

接下来毛毛张将结合一个完整的项目案例来介绍SpringBoot整合MySQL和HikariCP 连接池的过程,并提供了完整的代码

2 快速入门案例

  • 案例内容:基于Spring Boot,使用MyBatis-Plus框架,结合HikariCP连接池,查询并展示数据库中的全部用户信息

2.1 后端代码

2.1.1 创建项目

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

2.1.2 导入依赖

  • 在 Spring Boot 项目中,默认使用 HikariCP 作为数据库连接池,因此在大多数情况下无需手动引入该依赖。若项目中使用了以下某些 starter 依赖,HikariCP 会自动作为连接池配置:
    • spring-boot-starter-jdbc
    • spring-boot-starter-data-jpa
    • mybatis-spring-boot-starter
    • mybatis-plus-boot-starter
  • 需要特别注意的是,mybatismybatis-plus 已经间接依赖了 spring-boot-starter-jdbc,因此这两个 starter 会自动引入 HikariCP,从而避免重复配置。
方式1:手动导入 HikariCP 依赖
  • 如果没有导入HikariCP,我们可以通过下面的方式手动导入HikariCP依赖
    <dependency><groupId>com.zaxxer</groupId><artifactId>HikariCP</artifactId><version>6.2.1</version>
    </dependency>
    
方式 2:自动引入依赖 - 推荐
  • 在使用SpringBoot默认配置时,不需要手动添加 HikariCP 依赖,可以通过导入下面依赖的方式来自动引入HikariCP依赖:

    <!-- 引入 Spring Boot JDBC 模块 -->
    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency><!-- 引入 Spring Boot JPA 模块 -->
    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency><!-- 引入 MyBatis Plus 模块 -->
    <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version>
    </dependency>
    
本项目完整依赖
  • 需要注意的是,在使用 HikariCP 作为连接池的同时,还需要单独导入 MySQL 数据库驱动,通常通过引入 mysql-connector-java 依赖来实现
  • 毛毛张在这个任务中为了方便,使用了Mybatis-plus框架,整个项目的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>springboot-HicariCP-demo</artifactId><version>0.0.1-SNAPSHOT</version><name>springboot-HicariCP-demo</name><description>springboot-HicariCP-demo</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-parent</artifactId><version>2.7.6</version></parent><properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.7.6</spring-boot.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- MySQL 数据库驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope> <!-- 运行时依赖 --></dependency><!-- MybatisPlus 核心库 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version></dependency><!-- 热部署 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></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>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring-boot.version}</version><configuration><mainClass>com.zzx.SpringbootHicariCpDemoApplication</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:# HikariCP 连接池配置datasource:url: jdbc:mysql://localhost:3306/springboot?useSSL=false&autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&allowPublicKeyRetrieval=true&serverTimezone=UTCdriver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: abc123# 指定数据源类型为 HikariDataSourcetype: com.zaxxer.hikari.HikariDataSource# Hikari 连接池的详细配置hikari:# 连接池名称pool-name: HikariCP# 最小空闲连接数minimum-idle: 5# 空闲连接超时时间(毫秒)idle-timeout: 600000# 连接池的最大大小maximum-pool-size: 10# 是否自动提交事务auto-commit: true# 连接的最大生命周期(毫秒)max-lifetime: 1800000# 连接超时时间(毫秒)connection-timeout: 30000# 测试连接的 SQL 语句connection-test-query: SELECT 1logging:level:org.springframework.jdbc.core.JdbcTemplate: DEBUGmybatis-plus:# xml扫描,多个目录用逗号或者分号分隔(告诉 Mapper 所对应的 XML 文件位置)mapper-locations: classpath:mapper/*.xmlconfiguration:auto-mapping-behavior: full# 开启驼峰映射map-underscore-to-camel-case: true# 如果查询结果中包含空值的列,则 MyBatis 在映射的时候,不会映射这个字段call-setters-on-nulls: true# 这个配置会将执行的sql打印出来,在开发或测试的时候可以用log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    

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 com.baomidou.mybatisplus.annotation.TableName;
    import lombok.Data;@Data
    @TableName("user_info")
    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.model.vo.UserInfoVo;
    import com.zzx.reponse.ResVo;
    import com.zzx.entity.User;
    import com.zzx.service.UserService;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
    import java.util.List;@RestController
    @RequestMapping("user")
    public class UserController {@Resourceprivate 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.stereotype.Service;import javax.annotation.Resource;
    import java.util.List;@Service
    public class UserServiceImpl implements UserService {@Resourceprivate UserMapper userMapper;@Overridepublic List<User> queryAllUserInfo() {return userMapper.queryAllUserInfo();}
    }
    
  • mapper层UserMapper
    package com.zzx.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.zzx.entity.User;import java.util.List;public interface UserMapper extends BaseMapper<User> {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

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

2.2 前端代码

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

3 配置详解

3.1 常见配置

  • 下面是HicariCP连接池常见的配置:

    spring:datasource:url: jdbc:mysql://localhost:3306/springboot?useSSL=false&autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&allowPublicKeyRetrieval=true&serverTimezone=UTCdriver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: abc123type: com.zaxxer.hikari.HikariDataSource # 指定数据源类型为 HikariDataSourcehikari: # Hikari 连接池的详细配置pool-name: HikariCP       # 连接池名称minimum-idle: 5 # 最小空闲连接数idle-timeout: 600000  # 空闲连接超时时间(毫秒)maximum-pool-size: 10 # 连接池的最大大小auto-commit: true # 是否自动提交事务max-lifetime: 1800000 # 连接的最大生命周期(毫秒)connection-timeout: 30000 # 连接超时时间(毫秒)connection-test-query: SELECT 1 # 测试连接的 SQL 语句
    
  • 上面配置主要分为两部分:一部分是数据源配置,一部分是数据库连接池配置

3.2 数据源配置解析

  • 下面部分属于数据源配置:
    spring:datasource:# 数据库连接URL,指定数据库地址、端口、库名以及连接参数url: jdbc:mysql://localhost:3306/springboot?useSSL=false&autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&allowPublicKeyRetrieval=true&serverTimezone=UTC# MySQL 8.0 及以上需要 cj,5.7 以下可去掉 cjdriver-class-name: com.mysql.cj.jdbc.Driver # 数据库的用户名和密码username: rootpassword: abc123# 指定使用的数据库连接池实现type: com.zaxxer.hikari.HikariDataSource
    
  • 配置解析:
    • url:定义数据库连接的详细信息,包括:
      • localhost:3306(服务器地址和端口)
      • springboot(数据库名称)
      • 连接参数
    • driver-class-name:指定数据库连接的驱动,MySQL 8.x使用 com.mysql.cj.jdbc.Driver
    • usernamepassword:提供访问数据库的身份凭证。
    • type:指定数据库连接池的实现,配置为 com.zaxxer.hikari.HikariDataSource,表示使用 HikariCP 作为数据库连接池。如果需要使用 Druid,应将其替换为 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.3 连接池配置详解

  • 下面是关于连接池的配置部分:

    spring:datasource:hikari:# 连接池名称pool-name: HikariCP# 最小空闲连接数minimum-idle: 5# 空闲连接超时时间(毫秒)idle-timeout: 600000# 连接池的最大大小maximum-pool-size: 10# 是否自动提交事务auto-commit: true# 连接的最大生命周期(毫秒)max-lifetime: 1800000# 连接超时时间(毫秒)connection-timeout: 30000# 测试连接的 SQL 语句connection-test-query: SELECT 1
    
  • 关于HikariCP连接池的详细配置解析如下:

属性描述构造器默认值默认配置 validate 之后的值validate 重置
autoCommit自动提交从池中返回的连接truetrue
connectionTimeout等待来自池的连接的最大毫秒数30000 (30秒)30000如果小于 250 毫秒,则重置为 30 秒
idleTimeout连接允许在池中闲置的最长时间600000 (10分钟)maxLifetime 影响,条件不符可能重置为 0如果设置小于 10 秒则重置为 10 秒
maxLifetime池中连接最长生命周期1800000 (30分钟)1800000如果小于 30 秒则重置为 30 分钟
connectionTestQuery如果支持 JDBC4,建议不设置此属性nullnull
minimumIdle池中维护的最小空闲连接数1010小于 0 或大于 maxPoolSize 则重置为 maxPoolSize
maximumPoolSize池中最大连接数,包括闲置和使用中的连接1010如果小于 1,则重置为默认 10 或 minIdle 的值
metricRegistry指定 Codahale/Dropwizard MetricRegistry 的实例nullnull
healthCheckRegistry指定 Dropwizard HealthCheckRegistry 的实例nullnull
poolName连接池的用户定义名称,主要用于日志和 JMX 管理nullHikariPool-1
initializationFailTimeout控制池是否在初始化连接失败时快速失败11
isolateInternalQueries是否在独立事务中隔离内部池查询falsefalse
allowPoolSuspension是否允许通过 JMX 暂停和恢复池falsefalse
readOnly从池中获取的连接是否默认处于只读模式falsefalse
registerMbeans是否注册 JMX 管理 Bean(MBeans)falsefalse
catalog设置默认 catalogdefaultnull
connectionInitSql在新连接创建后执行的 SQL 语句nullnull
driverClassNameJDBC URL 解析失败时指定驱动程序类名称nullnull
transactionIsolation连接的默认事务隔离级别nullnull
validationTimeout连接测试活动的最大时间5000 (5秒)5000如果小于 250 毫秒,则重置为 5 秒
leakDetectionThreshold检测潜在的连接泄漏的时间阈值00必须 > 0 且 ≥ 2 秒,且不能大于 maxLifetime
dataSource设置要包装的数据源实例nullnull
schema设置默认 schemadefaultnull
threadFactory设置用于创建池线程的 ThreadFactory 实例nullnull
scheduledExecutor设置用于池内部任务的 ScheduledExecutorService 实例nullnull
  • 更具体的可以看官方配置文档

4 底层源码解析

  • 前面毛毛张介绍了HikariCP连接池的配置,下面毛毛张通过分析源码的方式来介绍以下为什么说SoringBoot2.x之后默认使用的连接池是HikariCP,从SpringBoot自动初始化配置 和 默认的数据源 两个角度理解。

4.1 SpringBoot自动初始化配置

  • 找到spring-boot-autocinfigure-2.7.6.jar依赖下面的org.springframework.boot.autoconfigure.jdbc
    image-20250125140727917
  • 关键代码如下:
    image-20250125140535976
  • 找到HikariCP数据源的配置:你可以发现,为了支持动态更新配置(基于MXBean),这里还设计了一层HikariConfigMXBean接口
    image-20250125141106379

4.2 默认的数据源

  • 首先,springboot-starter-jdbc中默认加载了HikariCP
    image-20250125143209056
    image-20250125143333154
  • 其次,在配置初始化或者加载时都是第一个被加载的
    image-20250125144401033

参考文献

  • 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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/8667.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SCRM在企业私域流量与客户管理中的变革之路探索

内容概要 在当今数字化高速发展的时代&#xff0c;SCRM&#xff08;社交客户关系管理&#xff09;作为一种新的管理工具&#xff0c;正逐渐成为企业私域流量管理和客户关系维护的重要基石。它不仅仅是一种软件工具&#xff0c;更是一种整合客户数据和关系管理的全新思维方式。…

实战 | 域环境下通过anydesk进入生产网

视频教程在我主页简介或专栏里 目录&#xff1a; 前言 外网突破 资产扫描与常规漏洞 经典的MS17010漏洞利用&#xff1a; 网络通信设备弱口令&#xff1a; 安全防护设备集群&#xff1a; 域环境渗透 核心生产网渗透 总结 教程下载链接&#xff1a;zkanzz 话不多说&#x…

卡特兰数学习

1&#xff0c;概念 卡特兰数&#xff08;英语&#xff1a;Catalan number&#xff09;&#xff0c;又称卡塔兰数&#xff0c;明安图数。是组合数学中一种常出现于各种计数问题中的数列。它在不同的计数问题中频繁出现。 2&#xff0c;公式 卡特兰数的递推公式为&#xff1a;f(…

算法刷题Day28:BM66 最长公共子串

题目链接&#xff0c;点击跳转 题目描述&#xff1a; 解题思路&#xff1a; 方法一&#xff1a;暴力枚举 遍历str1的每个字符x&#xff0c;并在str2中寻找以相同元素x为起始的最长字符串。记录最长的公共子串及其长度。 代码实现&#xff1a; def LCS(self, str1: str, st…

Open FPV VTX开源之ardupilot双OSD配置摄像头

Open FPV VTX开源之ardupilot双OSD配置 1 源由2. 分析3. 配置4. 解决办法5. 参考资料 1 源由 鉴于笔者这台Mark4 Copter已经具备一定的历史&#xff0c;目前机载了两个FPV摄像头&#xff1a; 模拟摄像头数字摄像头(OpenIPC) 测试场景&#xff1a; 从稳定性的角度&#xff1…

【Super Tilemap Editor使用详解】(十六):高级主题:深入理解 Super Tilemap Editor

在本节中,我们将深入探讨 Super Tilemap Editor 的工作原理,特别是图块地图(Tilemap)的渲染机制以及如何优化性能。这些知识将帮助你更好地理解工具的内部机制,并在开发中做出更明智的决策。 一、图块地图与图块渲染 图块地图是 Super Tilemap Editor 的核心组件之一。它由…

01学习预热篇(D6_正式踏入JVM深入学习前的铺垫)

目录 学习前言 一、虚拟机的结构 1. Java虚拟机参数设置 2. java 堆 3. 出入栈 4. 局部变量表 1> 局部变量的剖析 2> 局部变量的回收 5. 操作数栈 1> 常量入栈指令 2> 局部变量值转载到栈中指令 3> 将栈顶值保存到局部变量中指令 6. 帧数据区 7. 栈…

Node.js下载安装及环境配置教程 (详细版)

Node.js&#xff1a;是一个基于 Chrome V8 引擎的 JavaScript 运行时&#xff0c;用于构建可扩展的网络应用程序。Node.js 使用事件驱动、非阻塞 I/O 模型&#xff0c;使其非常适合构建实时应用程序。 Node.js 提供了一种轻量、高效、可扩展的方式来构建网络应用程序&#xff0…

SimpleFOC STM32教程10|基于STM32F103+CubeMX,速度闭环控制(有电流环)

导言 SimpleFOC STM32教程09&#xff5c;基于STM32F103CubeMX&#xff0c;ADC采样相电流 如上图所示, 增加了电流环. 效果如下&#xff1a; 20250123-200906 RTT 如上图所示&#xff0c;三相占空比依然是马鞍波。当我用手去给电机施加阻力时&#xff0c;PID要维持目标转速&am…

【超详细】ELK实现日志采集(日志文件、springboot服务项目)进行实时日志采集上报

本文章介绍&#xff0c;Logstash进行自动采集服务器日志文件&#xff0c;并手把手教你如何在springboot项目中配置logstash进行日志自动上报与日志自定义格式输出给logstash。kibana如何进行配置索引模式&#xff0c;可以在kibana中看到采集到的日志 日志流程 logfile-> l…

DeepSeek-R1:强化学习驱动的推理模型

1月20日晚&#xff0c;DeepSeek正式发布了全新的推理模型DeepSeek-R1&#xff0c;引起了人工智能领域的广泛关注。该模型在数学、代码生成等高复杂度任务上表现出色&#xff0c;性能对标OpenAI的o1正式版。同时&#xff0c;DeepSeek宣布将DeepSeek-R1以及相关技术报告全面开源。…

李沐vscode配置+github管理+FFmpeg视频搬运+百度API添加翻译字幕

终端输入nvidia-smi查看cuda版本 我的是12.5&#xff0c;在网上没有找到12.5的torch&#xff0c;就安装12.1的。torch&#xff0c;torchvision&#xff0c;torchaudio版本以及python版本要对应 参考&#xff1a;https://blog.csdn.net/FengHanI/article/details/135116114 创…

炫酷JavaScript文本时钟

今天分享一段简单的 JS 代码&#xff0c;创意来自aem1k.com/qlock &#xff0c;可以将整段 JS 代码字符本身变成时钟&#xff0c;每秒以 HH:MM:SS 的格式显示当前的时间。 JS逻辑实现代码本身也是时钟展示的载体&#xff0c;通过给字符设置不同的高亮颜色来显示当前的时间&…

前端jquery 实现文本框输入出现自动补全提示功能

git仓库&#xff1a;web_study/some-demos/inputAutoFit at main Cong0925/web_study (github.com) 压缩包&#xff1a;已绑定到指定资源 示例图&#xff1a; 实现说明: 1.首先&#xff0c;html部分设置好相关的定位标签如图&#xff1a; 2.主要函数 3.默认数据

Python3 OS模块中的文件/目录方法说明十二

一. 简介 前面文章简单学习了 Python3 中 OS模块中的文件/目录的部分函数。 本文继续来学习 OS 模块中文件、目录的操作方法&#xff1a;rename() 方法与 renames()方法。 二. Python3 OS模块中的文件/目录方法 1. rename() 方法 rename() 方法用于重命名文件或目录。它还可…

【Uniapp-Vue3】StorageSync数据缓存API

一、存储本地数据 uni.setStorageSync("键名", 键值); 二、获取本地数据 uni.getStorageSync("键名"); 也可以同时获取所有存储的数据的键名&#xff1a; uin.getStorageInfoSync(); 三、删除本地数据 uni.removeStorageSync("键名"); 如果想要…

2. Java-MarkDown文件解析-工具类

2. Java-MarkDown文件解析-工具类 1. 思路 读取markdown文件的内容&#xff0c;根据markdown的语法进行各个类型语法的解析。引入工具类 commonmark 和 commonmark-ext-gfm-tables进行markdown语法解析。 2. 工具类 pom.xml <!-- commonmark 解析markdown --> <d…

【Pytest】生成html报告中,中文乱码问题解决方案

import pytestif __name__ "__main__":# 只运行 tests 目录下的测试用例&#xff0c;并生成 HTML 报告pytest.main([-v, -s, --htmlreport.html, tests])可以以上方式生成&#xff0c;也可以在pytest.ini中设置 [pytest] addopts --htmlreport.html --self-contai…

Couchbase UI: Views

Couchbase 的 Views 页面是用于创建和管理视图的部分&#xff0c;视图是一种用于从 Couchbase 中提取和聚合数据的机制。视图通常用于实现简单的查询和数据汇总&#xff0c;特别是在处理大数据集时。以下是关于 Couchbase Views 页面的详细说明。 Views 页面功能概述 视图创建…

SpringBoot+Electron教务管理系统 附带详细运行指导视频

文章目录 一、项目演示二、项目介绍三、运行截图四、主要代码1.查询课程表代码2.保存学生信息代码3.用户登录代码 一、项目演示 项目演示地址&#xff1a; 视频地址 二、项目介绍 项目描述&#xff1a;这是一个基于SpringBootElectron框架开发的教务管理系统。首先&#xff…