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

【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

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

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

相关文章:

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

&#x1f64b;大家好&#xff01;我是毛毛张! &#x1f308;个人首页&#xff1a; 神马都会亿点点的毛毛张 在前面一篇文章中毛毛张介绍了SpringBoot中数据源与数据库连接池相关概念&#xff0c;今天毛毛张要分享的是关于SpringBoot整合HicariCP连接池相关知识点以及底层源码…...

0.91英寸OLED显示屏一种具有小尺寸、高分辨率、低功耗特性的显示器件

0.91英寸OLED显示屏是一种具有小尺寸、高分辨率、低功耗特性的显示器件。以下是对0.91英寸OLED显示屏的详细介绍&#xff1a; 一、基本参数 尺寸&#xff1a;0.91英寸分辨率&#xff1a;通常为128x32像素&#xff0c;意味着显示屏上有128列和32行的像素点&#xff0c;总共409…...

【insert函数】

在 C 中&#xff0c;std::string::insert 是一个功能强大的成员函数&#xff0c;用于在字符串的指定位置插入内容。它有多个重载版本&#xff0c;支持插入 字符、字符串、子字符串 等。以下是 insert 所有相关函数的详细介绍&#xff1a; 1. 插入字符串 函数签名&#xff1a; …...

Python 如何进行文本匹配:difflib| python 小知识

Python 如何进行文本匹配&#xff1a;difflib| python 小知识 difflib是Python标准库中的一个工具&#xff0c;用于比较和处理文本差异。它提供了一组用于比较和处理文本差异的功能&#xff0c;可以用于比较字符串、文件等。本文将详细介绍difflib模块的用法和实现细节&#x…...

MySQL误删数据怎么办?

文章目录 1. 从备份恢复数据2. 通过二进制日志恢复数据3. 使用数据恢复工具4. 利用事务回滚恢复数据5. 预防误删数据的策略总结 在使用MySQL进行数据管理时&#xff0c;误删数据是一个常见且具有高风险的操作。无论是因为操作失误、系统故障&#xff0c;还是不小心执行了删除命…...

可以称之为“yyds”的物联网开源框架有哪几个?

有了物联网的发展&#xff0c;我们的生活似乎也变得更加“鲜活”、有趣、便捷&#xff0c;包具有科技感的。在物联网&#xff08;IoT&#xff09;领域中&#xff0c;也有许多优秀的开源框架支持设备连接、数据处理、云服务等&#xff0c;成为被用户们广泛认可的存在。以下给大家…...

为AI聊天工具添加一个知识系统 之74 详细设计之15 正则表达式 之2

本文要点 要点 本项目&#xff08;为AI聊天工具添加一个知识系统&#xff09;中的正则表达式。 正则表达式的三“比”。正则表达式被 一、排比为三种符号&#xff08;元符号-圈号&#xff0c;特殊符号-引号&#xff0c;普通符号-括号&#xff09; 引号<<a线性回归bo…...

Java 注解与元数据

Java学习资料 Java学习资料 Java学习资料 一、引言 在 Java 编程中&#xff0c;注解&#xff08;Annotation&#xff09;和元数据&#xff08;Metadata&#xff09;是两个重要的概念。注解为程序提供了一种在代码中嵌入额外信息的方式&#xff0c;这些额外信息就是元数据。元…...

【橘子Kibana】Kibana的分析能力Analytics简易分析

一、kibana是啥&#xff0c;能干嘛 我们经常会用es来实现一些关于检索&#xff0c;关于分析的业务。但是es本身并没有UI,我们只能通过调用api来完成一些能力。而kibana就是他的一个外置UI&#xff0c;你完全可以这么理解。 当我们进入kibana的主页的时候你可以看到这样的布局。…...

度小满前端面试题及参考答案

<form>标签使用过哪些 tag? <form>标签中常使用的标签有很多。 <input>:这是最常用的标签之一,用于创建各种类型的输入字段,如文本框、密码框、单选按钮、复选框、文件上传框等。通过设置type属性来指定输入类型,例如type="text"创建文本输入…...

Padas进行MongoDB数据库CRUD

在数据处理的领域,MongoDB作为一款NoSQL数据库,以其灵活的文档存储结构和高扩展性广泛应用于大规模数据处理场景。Pandas作为Python的核心数据处理库,能够高效处理结构化数据。在MongoDB中,数据以JSON格式存储,这与Pandas的DataFrame结构可以很方便地互相转换。通过这篇教…...

LQ1052 Fibonacci斐波那契数列

题目描述 Fibonacci斐波那契数列也称为兔子数列&#xff0c;它的递推公式为&#xff1a;FnFn-1Fn-2&#xff0c;其中F1F21。 当n比较大时&#xff0c;Fn也非常大&#xff0c;现在小蓝想知道&#xff0c;Fn除以10007的余数是多少&#xff0c;请你编程告诉她。 输入 输入包含一…...

华硕笔记本装win10哪个版本好用分析_华硕笔记本装win10专业版图文教程

华硕笔记本装win10哪个版本好用&#xff1f;华硕笔记本还是建议安装win10专业版。Win分为多个版本&#xff0c;其中家庭版&#xff08;Home&#xff09;和专业版&#xff08;Pro&#xff09;是用户选择最多的两个版本。win10专业版在功能以及安全性方面有着明显的优势&#xff…...

编译器gcc/g++ --【Linux基础开发工具】

文章目录 一、背景知识二、gcc编译选项1、预处理(进行宏替换)2、编译&#xff08;生成汇编&#xff09;3、汇编&#xff08;生成机器可识别代码&#xff09;4、链接&#xff08;生成可执行文件或库文件&#xff09; 三、动态链接和静态链接四、静态库和动态库1、动静态库2、编译…...

八股文 (一)

文章目录 项目地址一、前端1.1 大文件上传,预览1.2 首页性能优化1.2 流量染色,灰度发布1.3 Websock心跳机制,大数据实时数据优化1.4 Gpu 加速 fps优化1.5 echarts包大小优化和组件封装1.6 前端监控系统1.7 超大虚拟列表卡顿1. 实现2. 相关问题(1) 什么是虚拟化列表,为什么要…...

c语言无符号的变量不能和有符号的直接比较,或者使用移项解决符号问题

使用移项解决问题&#xff0c;简单来说就是无符号运行不要有减号&#xff0c;使用移项后的加号代替 if(uEventDirLimitSize > uEventAndNormalDirSize) {if((uEventDirLimitSize - uEventAndNormalDirSize) > pStConfig->stParam.stUserParam.uEventRemain){return O…...

安卓日常问题杂谈(一)

背景 关于安卓开发中&#xff0c;有很多奇奇怪怪的问题&#xff0c;有时候这个控件闪一下&#xff0c;有时候这个页面移动一下&#xff0c;这些对于快速开发中&#xff0c;去查询&#xff0c;都是很耗费时间的&#xff0c;因此&#xff0c;本系列文章&#xff0c;旨在记录安卓…...

电力晶体管(GTR)全控性器件

电力晶体管&#xff08;Giant Transistor&#xff0c;GTR&#xff09;是一种全控性器件&#xff0c;以下是关于它的详细介绍&#xff1a;&#xff08;模电普通晶体管三极管进行对比学习&#xff09; 基本概念 GTR是一种耐高电压、大电流的双极结型晶体管&#xff08;BJT&am…...

【美】Day 1 CPT申请步骤及信息获取指南(Day1 CPT)

参考文章&#xff1a;【美】境外申请Day 1 CPT完整流程&#xff08;境外Day 1 CPT&#xff09; 文章目录 **一、申请前准备&#xff1a;了解Day 1 CPT基本要求****二、选择Day 1 CPT学校****1. 搜索学校****2. 筛选标准** **三、申请流程****1. 提交学校申请****2. 转SEVIS记录…...

梯度下降优化算法-动量法

1. 动量法的数学原理 1.1 标准梯度下降回顾 在标准梯度下降中&#xff0c;参数的更新公式为&#xff1a; θ t 1 θ t − η ⋅ ∇ θ J ( θ t ) \theta_{t1} \theta_t - \eta \cdot \nabla_\theta J(\theta_t) θt1​θt​−η⋅∇θ​J(θt​) 其中&#xff1a; θ t …...

游戏引擎介绍:Game Engine

简介 定义&#xff1a;软件框架&#xff0c;一系列为开发游戏的工具的集合 可协作创意生产工具&#xff0c;复杂性艺术&#xff0c;注重realtime实时 目的 为艺术家&#xff0c;设计师&#xff0c;程序员设计工具链 游戏引擎开发参考书 推荐&#xff1a;Game Engine Archite…...

zookeeper-3.8.3-基于ACL的访问控制

ZooKeeper基于ACL的访问控制 ZooKeeper 用ACL控制对znode的访问&#xff0c;类似UNIX文件权限&#xff0c;但无znode所有者概念&#xff0c;ACL指定ID及对应权限&#xff0c;且仅作用于特定znode&#xff0c;不递归。 ZooKeeper支持可插拔认证方案&#xff0c;ID格式为scheme…...

ResNeSt: Split-Attention Networks 参考论文

参考文献 [1] Tensorflow Efficientnet. https://github.com/tensorflow/tpu/tree/master/models/official/efficientnet. Accessed: 2020-03-04. 中文翻译&#xff1a;[1] TensorFlow EfficientNet. https://github.com/tensorflow/tpu/tree/master/models/official/efficien…...

正反转电路梯形图

1、正转联锁控制。按下正转按钮SB1→梯形图程序中的正转触点X000闭合→线圈Y000得电→Y000自锁触点闭合&#xff0c;Y000联锁触点断开&#xff0c;Y0端子与COM端子间的内部硬触点闭合→Y000自锁触点闭合&#xff0c;使线圈Y000在X000触点断开后仍可得电。 Y000联锁触点断开&…...

【数据结构】空间复杂度

目录 一、引入空间复杂度的原因 二、空间复杂度的分析 ❥ 2.1 程序运行时内存大小 ~ 程序本身大小 ❥ 2.2 程序运行时内存大小 ~ 算法运行时内存大小 ❥ 2.3 算法运行时内存大小 ❥ 2.4 不考虑算法全部运行空间的原因 三、空间复杂度 ❥ 3.1空间复杂度的定义 ❥ 3.2 空…...

系统学英语 — 句法 — 复合句

目录 文章目录 目录复合句型主语从句宾语从句表语从句定语从句状语从句同位语从句 复合句型 复合句型&#xff0c;即&#xff1a;从句。在英语中&#xff0c;除了谓语之外的所有句子成分都可以使用从句来充当。 主语从句 充当主语的句子&#xff0c;通常位于谓语之前&#x…...

SQL server 数据库使用整理

标题&#xff1a;SQL server 数据库使用整理 1.字符串表名多次查询 2.读取SQL中Json字段中的值&#xff1a;JSON_VALUE&#xff08;最新版本支持&#xff0c;属性名大小写敏感&#xff09; 1.字符串表名多次查询 SELECT ROW_NUMBER() OVER (ORDER BY value ASC) rowid,value…...

*胡闹厨房*

前期准备 详细教程 一、创建项目 1、选择Universal 3D,创建项目 2、删除预制文件Readme:点击Remove Readme Assets,弹出框上点击Proceed 3、Edit-Project Setting-Quality,只保留High Fidelity 4、打开 Assets-Settings ,保留URP-HighFidelity-Renderer 和 URP-High…...

.NET 8 项目 Docker 方式部署到 Linux 系统详细操作步骤

本文将详细介绍如何将一个 .NET 8 项目通过 Docker 部署到 Linux 系统中。以下步骤包括从项目的创建、Dockerfile 的编写、镜像构建、到最后在 Linux 上的容器运行。 1. 环境准备 在开始之前&#xff0c;请确保你已经具备以下环境&#xff1a; Linux 系统&#xff08;如 Ubu…...

状态码对照表

别瞎自定义状态码了 1xx&#xff1a;信息性状态码 状态码名称使用场景100Continue客户端应继续请求&#xff0c;等待后续响应。101Switching Protocols服务器根据客户端的请求切换协议。102Processing服务器正在处理请求&#xff0c;但尚未完成。103Early Hints提供给客户端的…...

【愚公系列】《循序渐进Vue.js 3.x前端开发实践》027-组件的高级配置和嵌套

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

Autosar-Os是怎么运行的?(多核系统运行)

写在前面&#xff1a; 入行一段时间了&#xff0c;基于个人理解整理一些东西&#xff0c;如有错误&#xff0c;欢迎各位大佬评论区指正&#xff01;&#xff01;&#xff01; 目录 1.Autosar多核操作系统 1.1多核启动过程 1.2多核运行过程 1.2.1核间任务同步 1.2.2Counte…...

WPF3-在xaml中引用其他程序集的名称空间

1. 如何在XAML里引用类库中的名称空间和类2. 小结 1. 如何在XAML里引用类库中的名称空间和类 首先需要记住一点&#xff1a;把类库引用到项目中是引用其中名称空间的物理基础&#xff0c;无论是C#还是XAML都是这样。 一旦将一个类库引用进程序&#xff0c;就可以引用其中的名…...

无人机红外热成像:应急消防的“透视眼”

无人机红外热成像&#xff1a;应急消防的“透视眼” 亲爱的小伙伴们&#xff0c;每年一到夏天&#xff0c;应急消防的战士们就像上紧了发条的闹钟&#xff0c;时刻准备应对各种灾害。炎热天气让火灾隐患“蹭蹭”往上涨&#xff0c;南北各地还有防洪救灾、台风、泥石流等灾害轮…...

飞牛NAS安装过程中的docker源问题

采用CloudFlare进行飞牛NAS的远程访问 【安全免费】无需公网IP、端口号&#xff0c;NAS外网访问新方法_网络存储_什么值得买 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<EOF {"registry-mirrors": ["https://docker.1panel.dev&quo…...

python基础语法(4) ----- 学习笔记分享

目录 Python 使用库 以及 实战的一些案例 1. 标准库 1.1 认识标准库 1.2 使用import导入模块 1.3 代码示例:日期及结算 1.4 代码示例:字符串操作 1.5 代码示例 : 文件查找工具 2. 第三方库 2.1 认识第三方库 2.2 使用pip 2.3 代码示例:生成二维码 (1) 使用搜索引擎,…...

Linux 内核学习 3b - 和copilot 讨论pci设备的物理地址在内核空间和用户空间映射到虚拟地址的区别

前提知识&#xff1a; 可以把内核当作一个需要特殊权限运行的程序&#xff0c;那么不同的程序&#xff0c;相同的设备物理地址就会映射到不同的虚拟地址 &#xff08;见Linux 内核学习 3 - 虚拟内存和物理内存&#xff09;。 You said 同一个pcie 设备物理地址在linux 内核和用…...

算法【有依赖的背包】

有依赖的背包是指多个物品变成一个复合物品&#xff08;互斥&#xff09;&#xff0c;每件复合物品不要和怎么要多种可能性展开。时间复杂度O(物品个数 * 背包容量)&#xff0c;额外空间复杂度O(背包容量)。 下面通过题目加深理解。 题目一 测试链接&#xff1a;[NOIP2006 提…...

【Linux】 冯诺依曼体系与计算机系统架构全解

Linux相关知识点可以通过点击以下链接进行学习一起加油&#xff01;初识指令指令进阶权限管理yum包管理与vim编辑器GCC/G编译器make与Makefile自动化构建GDB调试器与Git版本控制工具Linux下进度条 冯诺依曼体系是现代计算机设计的基石&#xff0c;其统一存储和顺序执行理念推动…...

【深度学习】 UNet详解

UNet 是一种经典的卷积神经网络&#xff08;Convolutional Neural Network, CNN&#xff09;架构&#xff0c;专为生物医学图像分割任务设计。该模型于 2015 年由 Olaf Ronneberger 等人在论文《U-Net: Convolutional Networks for Biomedical Image Segmentation》中首次提出&…...

“深入浅出”系列之算法篇:(2)openCV、openMV、openGL

OpenCV是一个的跨平台计算机视觉库,可以运行在Linux囚、Windows 和Mac OS操作系统上。它轻量级而且高效,由一系列 C函数和少量C类构成&#xff0c;同时也提供了Python 接口&#xff0c;实现了图像处理和计算机视觉方面的很多通用算法。 OpenMV是一个开源&#xff0c;低成本&am…...

低代码系统-产品架构案例介绍、得帆云(八)

产品名称 得帆云DeCode低代码平台-私有化 得帆云DeMDM主数据管理平台 得帆云DeCode低代码平台-公有云 得帆云DePortal企业门户 得帆云DeFusion融合集成平台 得帆云DeHoop数据中台 名词 概念 云原生 指自己搭建的运维平台&#xff0c;区别于阿里云、腾讯云 Dehoop 指…...

web3py+flask+ganache的智能合约教育平台

最近在学习web3的接口文档&#xff0c;使用web3pyflaskganache写了一个简易的智能合约教育平台&#xff0c;语言用的是python&#xff0c;ganche直接使用的本地区块链网络&#xff0c;用web3py进行交互。 代码逻辑不难&#xff0c;可以私信或者到我的闲鱼号夏沫mds获取我的代码…...

(长期更新)《零基础入门 ArcGIS(ArcMap) 》实验六----流域综合处理(超超超详细!!!)

流域综合处理 流域综合治理是根据流域自然和社会经济状况及区域国民经济发展的要求,以流域水流失治理为中心,以提高生态经济效益和社会经济持续发展为目标,以基本农田优化结构和高效利用及植被建设为重点,建立具有水土保持兼高效生态经济功能的半山区流域综合治理模式。数字高程…...

基于 WPF 平台使用纯 C# 实现动态处理 json 字符串

一、引言 在当今的软件开发领域&#xff0c;数据的交换与存储变得愈发频繁&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;作为一种轻量级的数据交换格式&#xff0c;以其简洁、易读、便于解析和生成的特点&#xff0c;被广泛应用于各种应用程序中。在 W…...

DRF开发避坑指南01

在当今快速发展的Web开发领域&#xff0c;Django REST Framework&#xff08;DRF&#xff09;以其强大的功能和灵活性成为了众多开发者的首选。然而&#xff0c;错误的使用方法不仅会导致项目进度延误&#xff0c;还可能影响性能和安全性。本文将从我个人本身遇到的相关坑来给大…...

WordPress免费证书插件

为了在您的网站上启用HTTPS&#xff0c;您可以使用本插件快速获取Let’s Encrypt免费证书。 主要功能&#xff1a; 支持快速申请Let’s Encrypt免费证书支持通配符证书申请&#xff0c;每个证书最多可以绑定100个域名支持自动续期证书支持重颁发证书&#xff0c;证书过期或失…...

MongoDB平替数据库对比

背景 项目一直是与实时在线监测相关&#xff0c;特点数据量大&#xff0c;读写操作大&#xff0c;所以选用的是MongoDB。但按趋势来讲&#xff0c;需要有一款国产数据库可替代&#xff0c;实现信创要求。选型对比如下 1. IoTDB 这款是由清华大学主导的开源时序数据库&#x…...

ANSYS学习笔记(十)网格质量的诊断和提高

网格质量的好坏不能单纯只看meshing给出的网格质量结果&#xff0c;要根据实际的计算物理场景来判断&#xff0c;需要求解的地方物理量大梯度的位置网格越密越好。 网格质量&#xff1a;在有限网格数量限制下&#xff0c;离散误差小的网格是好网格&#xff0c;是高质量网格。网…...

能量提升法三:赞美

前情回顾&#xff1a; 《能量提升法二&#xff1a;感恩》 片段&#xff1a;“感恩&#xff0c;就像是在跟世界说&#xff1a;谢谢你&#xff0c;我收到了&#xff0c;我很喜欢&#xff0c;请多来点” 把它归还人海&#xff0c;就当作每一个人&#xff0c;都有可能是曾经帮助…...