【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.pswp.cn/web/67037.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/67037.shtml
英文地址,請注明出處:http://en.pswp.cn/web/67037.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java進階(一)

目錄 一.Java注解 什么是注解&#xff1f; 內置注解 元注解 二.對象克隆 什么是對象克隆? 為什么用到對象克隆 三.淺克隆深克隆 一.Java注解 什么是注解&#xff1f; java中注解(Annotation)又稱java標注&#xff0c;是一種特殊的注釋。 可以添加在包&#xff0c;類&…

【PyCharm】將包含多個參數的 shell 腳本配置到執行文件來調試 Python 程序

要配置 PyCharm 以使用包含多個參數的 shell 腳本&#xff08;如 run.sh&#xff09;來調試 Python 程序&#xff0c;您可以按照以下步驟操作&#xff1a; 創建一個新的運行/調試配置&#xff1a; 在 PyCharm 中&#xff0c;點擊“運行”菜單旁邊的齒輪圖標&#xff0c;選擇“…

即夢(Dreamina)技術淺析(二):后端AI服務

1. 文本處理(Text Processing) 1.1 功能概述 文本處理模塊的主要任務是將用戶輸入的文字提示詞轉換為機器可以理解的向量表示。這一過程包括分詞、詞嵌入和語義編碼,旨在捕捉文本的語義信息,為后續的圖像和視頻生成提供準確的指導。 1.2 關鍵技術 1.分詞(Tokenization…

藍橋杯之c++入門(一)【第一個c++程序】

目錄 前言一、第?個C程序1.1 基礎程序1.2 main函數1.3 字符串1.4 頭文件1.5 cin 和 cout 初識1.6 名字空間1.7 注釋 二、四道簡單習題&#xff08;點擊跳轉鏈接&#xff09;練習1&#xff1a;Hello,World!練習2&#xff1a;打印飛機練習3&#xff1a;第?個整數練習4&#xff…

【C++初階】第11課—vector

文章目錄 1. 認識vector2. vector的遍歷3. vector的構造4. vector常用的接口5. vector的容量6. vector的元素訪問7. vector的修改8. vector<vector\<int\>>的使用9. vector的使用10. 模擬實現vector11. 迭代器失效11.1 insert插入數據內部迭代器失效11.2 insert插入…

【AIGC學習筆記】扣子平臺——精選有趣應用,探索無限可能

背景介紹&#xff1a; 由于近期業務發展的需求&#xff0c;我開始接觸并深入了解了扣子平臺的相關知識&#xff0c;并且通過官方教程自學了簡易PE工作流搭建的技巧。恰逢周會需要準備與工作相關的分享主題&#xff0c;而我作為一個扣子平臺的初學者&#xff0c;也想探索一下這…

mysql 學習6 DML語句,對數據庫中的表進行 增 刪 改 操作

添加數據 我們對 testdatabase 數據中 的 qqemp 這張表進行 增加數據&#xff0c;在這張表 下 打開 命令行 query console 在 軟件中就是打開命令行的意思 可以先執行 desc qqemp; 查看一下當前表的結構。 插入一條數據 到qqemp 表&#xff0c;插入時要每個字段都有值 insert…

Java Web-Request與Response

在 Java Web 開發中&#xff0c;Request 和 Response 是兩個非常重要的對象&#xff0c;用于在客戶端和服務器之間進行請求和響應的處理&#xff0c;以下是詳細介紹&#xff1a; Request&#xff08;請求對象&#xff09; Request繼承體系 在 Java Web 開發中&#xff0c;通…

李沐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 創…

論文閱讀(十六):利用線性鏈條件隨機場模型檢測陣列比較基因組雜交數據的拷貝數變異

1.論文鏈接&#xff1a;Detection of Copy Number Variations from Array Comparative Genomic Hybridization Data Using Linear-chain Conditional Random Field Models 摘要&#xff1a; 拷貝數變異&#xff08;CNV&#xff09;約占人類基因組的12%。除了CNVs在癌癥發展中的…

Alibaba Spring Cloud 十三 Nacos,Gateway,Nginx 部署架構與負載均衡方案

在微服務體系中&#xff0c;Nacos 主要承擔“服務注冊與發現、配置中心”的職能&#xff0c;Gateway&#xff08;如 Spring Cloud Gateway&#xff09;通常負責“路由轉發、過濾、安全鑒權、灰度流量控制”等功能&#xff0c;而 Nginx 則常被用作“邊緣反向代理”或“統一流量入…

Next.js 實戰 (十):中間件的魅力,打造更快更安全的應用

什么是中間件&#xff1f; 在 Next.js 中&#xff0c;中間件&#xff08;Middleware&#xff09;是一種用于處理每個傳入請求的功能。它允許你在請求到達頁面之前對其進行修改或響應。 通過中間件&#xff0c;你可以實現諸如日志記錄、身份驗證、重定向、CORS配置、壓縮等任務…

ElasticSearch-文檔元數據樂觀并發控制

文章目錄 什么是文檔&#xff1f;文檔元數據文檔的部分更新Update 樂觀并發控制 最近日常工作開發過程中使用到了 ES&#xff0c;最近在檢索資料的時候翻閱到了 ES 的官方文檔&#xff0c;里面對 ES 的基礎與案例進行了通俗易懂的解釋&#xff0c;讀下來也有不少收獲&#xff0…

實驗二 數據庫的附加/分離、導入/導出與備份/還原

實驗二 數據庫的附加/分離、導入/導出與備份/還原 一、實驗目的 1、理解備份的基本概念&#xff0c;掌握各種備份數據庫的方法。 2、掌握如何從備份中還原數據庫。 3、掌握數據庫中各種數據的導入/導出。 4、掌握數據庫的附加與分離&#xff0c;理解數據庫的附加與分離的作用。…

技術中臺與終搜——2

文章目錄 5、語言處理與自動補全技術探測5.1 自定義語料庫5.1.1 語料庫映射OpenAPI5.1.2 語料庫文檔OpenAPI 5.2 產品搜索與自動補全5.2.1 漢字補全OpenAPI5.2.2 拼音補全OpenAPI 5.3 產品搜索與語言處理5.3.1 什么是語言處理&#xff08;拼寫糾錯&#xff09;5.3.2 語言處理Op…

15_業務系統基類

創建腳本 SystemRoot.cs 因為 業務系統基類的子類 會涉及資源加載服務層ResSvc.cs 和 音樂播放服務層AudioSvc.cs 所以在業務系統基類 提取引用資源加載服務層ResSvc.cs 和 音樂播放服務層AudioSvc.cs 并調用單例初始化 using UnityEngine; // 功能 : 業務系統基類 public c…

k8s優雅重啟

理論上處于terminating狀態的pod&#xff0c;k8s 就會把它從service中移除了&#xff0c;只用配置一個優雅停機時長就行了。kubectl get endpoints 驗證 因此&#xff0c;優雅重新的核心問題&#xff0c;是怎么讓空閑長連接關閉&#xff0c;再等待處理中的請求執行完。 一些底…

【Linux】華為服務器使用U盤安裝統信操作系統

目錄 一、準備工作 1.1 下載UOS官方系統 &#xff11;.&#xff12;制作啟動U盤 1.3 服務器智能管理系統iBMC 二、iBMC設置U盤啟動 一、準備工作 1.1 下載UOS官方系統 服務器CPU的架構是x86-64還是aarch64&#xff09;,地址&#xff1a;統信UOS生態社區 - 打造操作系統創…

27. 【.NET 8 實戰--孢子記賬--從單體到微服務】--簡易報表--報表服務

報表是每個記賬應用所具備的功能&#xff0c;要實現報表功能就需要把賬本的核心功能&#xff08;記賬&#xff09;完成&#xff0c;因此報表服務作為本專欄第一部分單體應用開發中最后一個要實現的功能&#xff0c;這一篇文章很簡單&#xff0c;我們一起來實現一個簡單的報表服…

基于 Node.js 的天氣查詢系統實現(附源碼)

項目概述 這是一個基于 Node.js 的全棧應用,前端使用原生 JavaScript 和 CSS,后端使用 Express 框架,通過調用第三方天氣 API 實現天氣數據的獲取和展示。 主要功能 默認顯示多個主要城市的天氣信息 支持城市天氣搜索 響應式布局設計 深色主題界面 優雅的加載動畫 技術棧 …