Spring boot 数据库连接池

Posted xiaodujava

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring boot 数据库连接池相关的知识,希望对你有一定的参考价值。

Spring boot 数据库连接池

上一节 Spring boot jdbcTemplate

Spring boot jdbcTemplate

源码

[源码地址]:(https://gitee.com/mayun_xiaodu/spring-boot-all)


Spring boot 数据库连接池

上一章节我们使用了jdbcTemplate 进行数据库的简单操作,这章我们给数据库连接添加上数据连接池。

springboot 默认数据库 Hikari

springboot 内置式默认支持HiKari 数据库连接池的;在 DataSourceConfiguration 配置类 中我可以看到
默认引入创建了HikariDatasource ; hikari 号称是 最快的数据库连接池,不过国内一般使用druid

	/**
	 * Hikari DataSource configuration.
	 */
	@Configuration
	@ConditionalOnClass(HikariDataSource.class)
	@ConditionalOnMissingBean(DataSource.class)
	@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource",
			matchIfMissing = true)
	static class Hikari {

		@Bean
		@ConfigurationProperties(prefix = "spring.datasource.hikari")
		public HikariDataSource dataSource(DataSourceProperties properties) {
			HikariDataSource dataSource = createDataSource(properties, HikariDataSource.class);
			if (StringUtils.hasText(properties.getName())) {
				dataSource.setPoolName(properties.getName());
			}
			return dataSource;
		}

	}

springboot 已经自动装配了 HikarDataSource 数据源所以我们只需要在配置文件中配置下连接池信息即可;
配置文件中使用 spring.hikari 前缀进行数据库连接配置

spring:
  application:
    name: test-jdbcPool
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/mytest?useSSL=false&charsetEncoding=utf8
    driver-class-name: com.mysql.jdbc.Driver
    hikari:
      maximum-pool-size: 10  # 最大连接数
      minimum-idle: 5 # 最小空闲数
      connection-timeout: 2000 # 获取连接超时时间; 默认30s
      pool-name: my-test-hikari # 连接池名称
      idle-timeout: 600000 # 空闲超时时间;默认是十分钟;空闲时间超过设定时间则会被回收
      auto-commit: true # 是否自动提交
      max-lifetime: 1800000 # 最大存活时间,默认30分钟
     # connection-test-query: SELECT 1  # 连接数据库后测试语句
      validation-timeout: 1000 #
      # schema: 设置模式,例如 postgresql 有模式这个概念

配置完以上后我们使用 jdbcTemplate 或者mybatis 等进行数据库操作的时候就会默认使用上HikarDataSource 进行数据库连接操作。

alibaba Druid 数据库连接池

简述
Druid是Java语言中综合最好的数据库连接池。Druid能够提供强大的监控和扩展功能;我们把springboot 默认的 数据库连接池 hikar 缓存Druid 。
使用 druid 数据库连接池的好处:

  • 开源,国内活跃度高
  • 性能好,国内号称是java里最好的数据库连接池
  • 功能多,提供了 sql统计,sql过滤,数据库密码加密等功能

druid github 地址


使用:

添加pom 依赖

我们这里选用druid 提供的springboot starter

 <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.18</version>
        </dependency>
配置连接池信息

配置文件中配置连接池信息

spring:
  # 数据源配置
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/mytest?useSSL=false&charsetEncoding=utf8
    driver-class-name: com.mysql.jdbc.Driver
    # 连接池配置
    druid:
      max-active: 10 # 最大活跃数量 默认8
      min-idle:  2 # 最小空闲数 默认0
      initial-size: 5 # 初始连接数
      max-wait: 2000 # 获取连接最大等待时间 默认 -1
      validation-query: select 1
      validation-query-timeout: 5000
      time-between-eviction-runs-millis: 2000 # 间隔多久进行检测需要关闭的空闲连接
      min-evictable-idle-time-millis: 600000 # 配置连接在池中最小生存的时间
      max-wait-thread-count: 20 # 最大等待线程数

集成依赖springboot durid starter 后springboot 就会自动装配了DruidDatasource,改变了jdbc操作数据使用的DataSource.
druid 自动装配类:
这里面创建了 DruidDataSourceWrapper() 其本身就是 DruidDatasource, 通过 注解@AutoConfigureBefore(DataSourceAutoConfiguration.class) 可知此配置类是在 DataSourceAutoConfiguration 之前生效,所以
优于springboot 默认创建的 hikarDatasource;

@Configuration
@ConditionalOnClass(DruidDataSource.class)
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class})
@Import({DruidSpringAopConfiguration.class,
    DruidStatViewServletConfiguration.class,
    DruidWebStatFilterConfiguration.class,
    DruidFilterConfiguration.class})
public class DruidDataSourceAutoConfigure {

    private static final Logger LOGGER = LoggerFactory.getLogger(DruidDataSourceAutoConfigure.class);

    @Bean(initMethod = "init")
    @ConditionalOnMissingBean
    public DataSource dataSource() {
        LOGGER.info("Init DruidDataSource");
        return new DruidDataSourceWrapper();
    }
}

所以加入了 Druid 的依赖后 就会自动选择使用 druidDatasource 作为数据源的操作,即可直接使用。

druid 监控功能

durid 的监控统计也是非常好用的;durid 内置了比较多的 Filter ;对sql的执行,和过滤监控,url 的方法都进行了比较好的统计。

配置Filters 开启哪些filter

在 spring.datasource.druid.filters 中配置, 多个使用逗号隔开; druid 在springboot 配置文件中前缀都是 spring.datasource.druid 所以有些截图就不添加

   # 配置filters ;
      #内置了日志类型: log4j ,slf4j, log4j2; 用于日志打印
      #监控统计: stat ;
      #解密和配置远程配置文件: config
      #防火墙: wall
      filters: stat,slf4j,wall
开启监控UI页面 StatViewServlet
     stat-view-servlet:
        enabled: true
        login-username: root  # 监控页面登录名
        login-password: 123456 # 监控页面密码

开启 监控页面后, 就可以登录监控页面

监控页面

访问路径: localhost:8181/druid 就可以观察到相关的
在这里插入图片描述

数据源 记录了我们的数据库连接信息
sql监控 监控执行过的sql 数量,执行时间, 并发数等
Sql防火墙 监控我们配置的wallFilter 信息;

配置慢sql 扫描
spring:
  datasource:
    druid: 
	  filter:
	    stat: # 监控配置
          enabled: true
          db-type: mysql
         # 慢sql配置
          log-slow-sql: true
          # sql 执行超过多少ms算慢sql
          slow-sql-millis: 1000

慢sql会在日志中打印 ,以及监控页面中sql监控中显示

配置 sql日志打印

使用slf4j; 配置文件中filters中添加slf4j

filters: stat,slf4j,wall

编写logback日志配置文件, 配置druid.sql.Statement 的日志输出配置 进行日志的打印和输出到日志文件; 我这里只配置了输出到控制台
logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!--获取spirng配置信息-->
    <springProperty name="APP" source="spring.application.name"/>
    <!--   日志颜色转换器 -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>

    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <Target>System.out</Target>
        <encoder>
            <pattern>%clr(${APP}){magenta} -- %d{yyyy-MM-dd HH:mm:ss.SSS} %clr([%5level]) %blue([%10t]) %cyan(%40logger{39}) : %clr(%m) %n
            </pattern>
        </encoder>
    </appender>
    <logger name="com.xiaodu" additivity="false">
        <level value="warn"/>
    </logger>
    <!--配置sql打印-->
    <logger name="druid.sql.Statement" level="debug" additivity="false">
        <appender-ref ref="console"/>
    </logger>
    <root>
        <level value="info"/>
        <appender-ref ref="console"/>
    </root>
</configuration>

日志打印信息

test-jdbcPool -- 2021-04-13 10:49:36.940 [DEBUG] [http-nio-8181-exec-1]                      druid.sql.Statement : {conn-10005, pstmt-20005} created. insert into t_user(u_id,u_name,password,money,create_time) values(?,?,?,?,?) 
test-jdbcPool -- 2021-04-13 10:49:36.940 [DEBUG] [http-nio-8181-exec-1]                      druid.sql.Statement : {conn-10005, pstmt-20005} Parameters : [e0b2ae8bfd23497f9d0d5fa59d450add, xiaodu, xiaodu, 123456, 2021-04-13 10:49:36.939] 
test-jdbcPool -- 2021-04-13 10:49:36.940 [DEBUG] [http-nio-8181-exec-1]                      druid.sql.Statement : {conn-10005, pstmt-20005} Types : [VARCHAR, VARCHAR, VARCHAR, BIGINT, TIMESTAMP] 
test-jdbcPool -- 2021-04-13 10:49:36.993 [DEBUG] [http-nio-8181-exec-1]                      druid.sql.Statement : {conn-10005, pstmt-20005} update executed. effort 1. 52.4484 millis. insert into t_user(u_id,u_name,password,money,create_time) values(?,?,?,?,?) 
test-jdbcPool -- 2021-04-13 10:49:36.993 [DEBUG] [http-nio-8181-exec-1]                      druid.sql.Statement : {conn-10005, pstmt-20005} closed 
配置sql防火墙 WallFilter

配置sql语句的检测,是否能进行一些危险的sql操作

spring:
  datasource:
    druid:
      filter:
        wall:  # sql防火墙配置
          enabled: true
          db-type: mysql
          config:
            select-all-column-allow: false # 是否允许select *
            delete-allow: false # 是否允许delete 语句
            drop-table-allow: false # 是否允许 drop table 语句
            alter-table-allow: false # 是否允许 alter table 语句
            truncate-allow: false
            update-where-alay-true-check: true # 检测update 语句是否条件永远为真
            update-where-none-check: true # 检测update 语句是否没有 where 条件
            delete-where-none-check: true # 检测delete 语句是否没有 where 条件
            delete-where-alway-true-check: true # 检测delete 语句是否条件永远为真
配置web应用和URL监控 WebStatFilter
spring:
  datasource:
    druid:
     # web应用 和URL 监控
      web-stat-filter:
        enabled: true
        exclusions: /static/*,*.js,*.gif,*.jpg,*.css,*.ico,/druid/* # 排除url
配置ConfigFilter

configFilter 可以进行数据库信息配置文件的位置,通过file 或者http 进行获取;和数据库密码加密操作;
重点说下数据库密码加密; 数据库密码在配置文件中明文显示是很敏感的。
数据库密码加密

  1. 使用durid 提供的 工具类生成加密后的密码
public class TestConfigFilter {

    public static void main(String[] args) throws Exception {
        String[] arg = new String[]{"123456"};  // 你的密码
        ConfigTools.main(arg);
    }
}

控制台输出加密后的密码信息
在这里插入图片描述
   2. 配置configFilter

  • filters 中加上config
 filters: stat,slf4j,wall,config
  • 添加工具类生成的公钥
db:
 publickey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAI9GVgduCJuY7K0Do7fSyrR0AyF+9leXaE4NlDnyEm/ZBixDPZCTgZLsaGkXFhiJ/14m7J+Ai1sC7q2RWbIoZSMCAwEAAQ==

  • 添加connection-properties 开启解密
spring:
  datasource:
    druid:
      connection-properties: config.decrypt=true;config.decrypt.key=${db.publickey}
  • 修改密码为加密后的密码
spring:
 # 数据源配置
 datasource:
   username: root
   password: XGsrLVwuuZJNCxZBJ5Q398P32SKDYYqL/MsqbAFAnIyd0X+SBcTQztWfZNm9D/GmRh4M95yP4ABd3WuA9EMUFA==

以上就是 configFIlter 对数据库密码加密的操作。

配置spring 监控

配置spring监控中 就会拦截指定的springbean ;在 监控页面的spring监控模块中显示 那些方法执行了那些sql, 耗时等信息。
这里简单以按照spring bean类型拦截监控为例。 其他例如通过正则, springbean id 请参考官网。

    @Bean
        public DruidStatInterceptor druidStatInterceptor() throws Exception {
            DruidStatInterceptor druidStatInterceptor = new DruidStatInterceptor();
            druidStatInterceptor.afterPropertiesSet();
            return druidStatInterceptor;
        }

        @Bean
        public BeanTypeAutoProxyCreator beanTypeAutoProxyCreator() {
            BeanTypeAutoProxyCreator beanTypeAutoProxyCreator = new BeanTypeAutoProxyCreator();
            beanTypeAutoProxyCreator.setTargetBeanType(UserController.class);  // 拦截的目标
            beanTypeAutoProxyCreator.setInterceptorNames("druidStatInterceptor"); // bean拦截器名称
            return beanTypeAutoProxyCreator;
        }

配置完后; 我们访问Usercontroller 类中的方法; 然后看ui页面 spring监控
在这里插入图片描述
其他方式参考官网wiki

扩展-通过spring 注解配置druid

也可以在配置类中配置相关的druid信息, 例如 datasource, druid提供的监控功能filter功能等。

          /*-------------使用配置类配置druid相关信息-----------------*/

        @Bean
        public DruidDataSource dataSource(DataSourceProperties dataSourceProperties) throws SQLException {
            DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
            dataSource.setFilters("slf4j,wall,stat");
            dataSource.setMaxActive(5);
            return dataSource;
        }

        @Bean
        public WallFilter wallFilter() {
            WallFilter wallFilter = new WallFilter();
            wallFilter.setConfig(wallConfig());
            wallFilter.setThrowException(true); // 对被认为是攻击的sql进行抛异常
            wallFilter.setLogViolation(true); // 对被认为是攻击的sql进行error 输出
            return wallFilter;
        }

        @Bean
        public WallConfig wallConfig() {
            WallConfig wallConfig = new WallConfig();
            wallConfig.setDeleteWhereAlwayTrueCheck(true);
            wallConfig.setUpdateWhereAlayTrueCheck(true);
            wallConfig.setDeleteWhereNoneCheck(true);
            wallConfig.setUpdateWhereNoneCheck(true);
            return wallConfig;
        }

        @Bean
        public StatFilter statFilter() {
            StatFilter statFilter = new StatFilter();
            statFilter.setDbType("mysql");
            statFilter.setLogSlowSql(true);
            statFilter.setSlowSqlMillis(2000);
            return statFilter;
        }

下一节 Spring boot restTemplate

Spring boot restTemplate

以上是关于Spring boot 数据库连接池的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot 数据库连接池

spring-boot中tomcat的默认连接池?

spring boot 集成Druid

Spring-Boot:如何设置 JDBC 池属性,例如最大连接数?

spring boot整合Druid连接池

spring boot默认使用的是啥数据库连接池