SpringBoot使用Druid连接池 + 配置监控页面(自定义版 + starter版)
作者:mmseoamin日期:2023-12-14

目录

  • 1. Druid连接池的功能
  • 2. 自定义版
    • 2.1 pom.xml添加依赖
    • 2.2 MyDataSourceConfig实现
    • 2.3 application.properties配置
    • 编写Controller进行测试
    • 2.4 druid监控页面查看
    • 3. starter版
      • 3.1 pom.xml添加依赖
      • 3.2 自动配置分析
      • 3.3 使用application.properties对druid进行配置
      • 3.4 druid配置参考

        1. Druid连接池的功能

        全方位监控、防SQL注入攻击等

        2. 自定义版

        2.1 pom.xml添加依赖

        添加druid连接池的依赖,如下所示:

                
                    com.alibaba
                    druid
                    1.2.15
                
        

        2.2 MyDataSourceConfig实现

        说明如下:

        • @ConfigurationProperties(prefix = “spring.datasource”)注解,将以spring.datasource开头的配置和DataSource类进行绑定,就可以在application.properties对DataSource的属性进行设置了
        • druidDataSource.setFilters(“stat,wall”):开启SQL监控、SQL防火墙功能
        • 向IOC容器添加ServletRegistrationBean组件,开启druid监控功能。设置了druid监控的访问页面是/druid/*;也设置了登录监控页面的账号和密码
        • 向IOC容器添加FilterRegistrationBean组件,开启Web应用菜单功能,让druid进行Web应用的统计。设置了统计的Web URL和排除的Web URL
          package com.hh.springboottest.config;
          import com.alibaba.druid.pool.DruidDataSource;
          import com.alibaba.druid.support.http.StatViewServlet;
          import com.alibaba.druid.support.http.WebStatFilter;
          import org.springframework.boot.context.properties.ConfigurationProperties;
          import org.springframework.boot.web.servlet.FilterRegistrationBean;
          import org.springframework.boot.web.servlet.ServletRegistrationBean;
          import org.springframework.context.annotation.Bean;
          import org.springframework.context.annotation.Configuration;
          import javax.sql.DataSource;
          import java.sql.SQLException;
          import java.util.Arrays;
          @Configuration
          public class MyDataSourceConfig {
              // 将application.properties中spring.datasource前缀对应的值赋值给DataSource类属性
              @ConfigurationProperties(prefix = "spring.datasource")
              @Bean
              public DataSource dataSource() {
                  DruidDataSource druidDataSource = new DruidDataSource();
                  try {
                      // 开启SQL监控菜单功能,让druid进行SQL的执行统计
                      // 开启SQL防火墙菜单功能
                      druidDataSource.setFilters("stat,wall");
                  } catch (SQLException e) {
                      e.printStackTrace();
                  }
                  return druidDataSource;
              }
              // 向IOC容器添加ServletRegistrationBean组件,开启druid监控功能
              @Bean
              public ServletRegistrationBean statViewServlet() {
                  StatViewServlet statViewServlet = new StatViewServlet();
                  ServletRegistrationBean servletRegistrationBean =
                          // druid监控的访问页面是/druid/*
                          new ServletRegistrationBean<>(statViewServlet, "/druid/*");
                  // 开启监控页面的访问登录账号和密码
                  servletRegistrationBean.addInitParameter("loginUsername", "druid");
                  servletRegistrationBean.addInitParameter("loginPassword", "123456");
                  return servletRegistrationBean;
              }
              // 开启Web应用菜单功能,让druid进行Web应用的统计
              @Bean
              public FilterRegistrationBean webStatFilter() {
                  WebStatFilter webStatFilter = new WebStatFilter();
                  FilterRegistrationBean filterRegistrationBean =
                          new FilterRegistrationBean<>(webStatFilter);
                  // 设置统计的Web URL
                  filterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
                  // 设置排除的Web URL
                  filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
                  return filterRegistrationBean;
              }
          }
          

          2.3 application.properties配置

          在代码中可以对DataSource进行各种配置参数的set,也可以在application.properties中对durid连接池进行配置,如下所示:

          # 最好注释HikariDataSource
          # spring.datasource.type=com.zaxxer.hikari.HikariDataSource
          spring.datasource.filters=stat,wall
          spring.datasource.max-active=12
          

          编写Controller进行测试

          package com.hh.springboottest.myController;
          import lombok.extern.slf4j.Slf4j;
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.jdbc.core.JdbcTemplate;
          import javax.sql.DataSource;
          @Slf4j
          @RestController
          public class HelloController {
              @Autowired
              private JdbcTemplate jdbcTemplate;
              @Autowired
              DataSource dataSource;
              @ResponseBody
              @GetMapping("/queryFromDb")
              public String queryFromDb() {
                  Long userCount = jdbcTemplate.queryForObject("select count(*) from user", Long.class);
                  // 返回的结果是:数据库连接池类型为class com.alibaba.druid.pool.DruidDataSource
                  log.info("数据库连接池类型为{}", dataSource.getClass());
                  return userCount.toString();
              }
          }
          

          2.4 druid监控页面查看

          访问http://localhost:8080/druid/index.html,页面效果如下:

          druid监控页面其中数据源菜单在RestController等进行了调用才有结果显示

          其中SQL监控页面如下。

          SQL监控页面SQL监控项上,执行时间、读取行数、更新行数都有区间分布,将耗时分布成8个区间:

          • 耗时0到1毫秒的次数
          • 耗时1到10毫秒的次数
          • 耗时10到100毫秒的次数
          • 耗时100到1000毫秒的次数
          • 耗时1到10秒的次数
          • 耗时10到100秒的次数
          • 耗时100到1000秒的次数
          • 耗时1000秒以上的次数

            耗时区间分布提供了“执行+RS时分布”,是将执行时间+ResultSet持有时间合并监控,这个能方便诊断返回行数过多的查询

            3. starter版

            首先注释上面MyDataSourceConfig的@Configuration注解,或者删除MyDataSourceConfig.java文件。开始进行starter版的开发

            3.1 pom.xml添加依赖

            添加druid-spring-boot-starter的依赖;和添加spring-boot-starter-aop,用于druid监控页的Spring监控菜单。如下所示:

                    
                        com.alibaba
                        druid-spring-boot-starter
                        1.2.15
                    
                    
                    
                        org.springframework.boot
                        spring-boot-starter-aop
                    
            

            可以看到自动添加了druid、spring-boot-autoconfiguration依赖

            druid-spring-boot-starter

            3.2 自动配置分析

            查看druid-spring-boot-starter-1.2.15.jar的DruidDataSourceAutoConfigure.class,可以看到:

            • DruidDataSourceAutoConfigure是在DataSourceAutoConfiguration之前添加到IOC容器的,这样就先使用了druid连接池
            • 同时对DruidStatProperties、DataSourceProperties两个配置类进行了绑定
            • 向IOC容器添加了DruidSpringAopConfiguration、DruidStatViewServletConfiguration、DruidWebStatFilterConfiguration.class、DruidFilterConfiguration四个组件
            • 向IOC容器添加了DataSource
              package com.alibaba.druid.spring.boot.autoconfigure;
              ......省略部分......
              @Configuration
              @ConditionalOnClass({DruidDataSource.class})
              @AutoConfigureBefore({DataSourceAutoConfiguration.class})
              @EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class})
              @Import({DruidSpringAopConfiguration.class, DruidStatViewServletConfiguration.class, DruidWebStatFilterConfiguration.class, DruidFilterConfiguration.class})
              public class DruidDataSourceAutoConfigure {
              ......省略部分......
              @Bean(
                      initMethod = "init"
                  )
                  @ConditionalOnMissingBean
                  public DataSource dataSource() {
                      LOGGER.info("Init DruidDataSource");
                      return new DruidDataSourceWrapper();
                  }
              }
              

              查看DruidStatProperties配置类,druid的配置是由spring.datasource.druid开头的参数进行配置的

              ......省略部分......
              @ConfigurationProperties("spring.datasource.druid")
              public class DruidStatProperties {
              ......省略部分......
              }
              

              查看DataSourceProperties配置类,datasource的配置是由spring.datasource开头的参数进行配置的

              ......省略部分......
              @ConfigurationProperties(
                  prefix = "spring.datasource"
              )
              public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
              ......省略部分......
              }
              

              查看DruidSpringAopConfiguration类,aop相关的是由spring.datasource.druid.aop-patterns参数进行配置的,主要用来监控SpringBean。对应druid监控页面的Spring监控菜单

              ......省略部分......
              @ConditionalOnProperty({"spring.datasource.druid.aop-patterns"})
              public class DruidSpringAopConfiguration {
              ......省略部分......
              }
              

              查看DruidStatViewServletConfiguration类,如下所示:

              • statViewServlet相关的是由spring.datasource.druid.stat-view-servlet.enabled参数进行配置的,默认关闭
              • 向IOC容器添加了ServletRegistrationBean组件
              • 该类主要做了允许哪些IP可以访问监控页面,不允许哪些页面访问监控页面
              • 和设置监控页面的登录账号和密码
              • 和设置重置按钮的开启和关闭
                ......省略部分......
                @ConditionalOnWebApplication
                @ConditionalOnProperty(
                    name = {"spring.datasource.druid.stat-view-servlet.enabled"},
                    havingValue = "true"
                )
                public class DruidStatViewServletConfiguration {
                    private static final String DEFAULT_ALLOW_IP = "127.0.0.1";
                    public DruidStatViewServletConfiguration() {
                    }
                    @Bean
                    public ServletRegistrationBean statViewServletRegistrationBean(DruidStatProperties properties) {
                        DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
                        ServletRegistrationBean registrationBean = new ServletRegistrationBean();
                        registrationBean.setServlet(new StatViewServlet());
                        registrationBean.addUrlMappings(new String[]{config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*"});
                        if (config.getAllow() != null) {
                            registrationBean.addInitParameter("allow", config.getAllow());
                        } else {
                            registrationBean.addInitParameter("allow", "127.0.0.1");
                        }
                        if (config.getDeny() != null) {
                            registrationBean.addInitParameter("deny", config.getDeny());
                        }
                        if (config.getLoginUsername() != null) {
                            registrationBean.addInitParameter("loginUsername", config.getLoginUsername());
                        }
                        if (config.getLoginPassword() != null) {
                            registrationBean.addInitParameter("loginPassword", config.getLoginPassword());
                        }
                        if (config.getResetEnable() != null) {
                            registrationBean.addInitParameter("resetEnable", config.getResetEnable());
                        }
                        return registrationBean;
                    }
                }
                

                查看DruidWebStatFilterConfiguration类,如下所示:

                • WebStatFilter相关的是由spring.datasource.druid.web-stat-filter.enabled参数进行配置的,默认关闭
                • 向IOC容器添加了FilterRegistrationBean组件
                • 该类设置了对哪些Web URL进行统计,哪些Web URL不进行统计(比如: “.js,.gif,.jpg,.png,.css,.ico,/druid/*”)
                  ......省略部分......
                  @ConditionalOnWebApplication
                  @ConditionalOnProperty(
                      name = {"spring.datasource.druid.web-stat-filter.enabled"},
                      havingValue = "true"
                  )
                  public class DruidWebStatFilterConfiguration {
                      public DruidWebStatFilterConfiguration() {
                      }
                      @Bean
                      public FilterRegistrationBean webStatFilterRegistrationBean(DruidStatProperties properties) {
                          DruidStatProperties.WebStatFilter config = properties.getWebStatFilter();
                          FilterRegistrationBean registrationBean = new FilterRegistrationBean();
                          WebStatFilter filter = new WebStatFilter();
                          registrationBean.setFilter(filter);
                          registrationBean.addUrlPatterns(new String[]{config.getUrlPattern() != null ? config.getUrlPattern() : "/*"});
                          registrationBean.addInitParameter("exclusions", config.getExclusions() != null ? config.getExclusions() : "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
                          ......省略部分......
                      }
                  ......省略部分......
                  }
                  

                  查看DruidFilterConfiguration类,是对所有Druid自己的Filter的配置,比如wall防火墙

                  ......省略部分......
                  public class DruidFilterConfiguration {
                      private static final String FILTER_STAT_PREFIX = "spring.datasource.druid.filter.stat";
                      private static final String FILTER_CONFIG_PREFIX = "spring.datasource.druid.filter.config";
                      private static final String FILTER_ENCODING_PREFIX = "spring.datasource.druid.filter.encoding";
                      private static final String FILTER_SLF4J_PREFIX = "spring.datasource.druid.filter.slf4j";
                      private static final String FILTER_LOG4J_PREFIX = "spring.datasource.druid.filter.log4j";
                      private static final String FILTER_LOG4J2_PREFIX = "spring.datasource.druid.filter.log4j2";
                      private static final String FILTER_COMMONS_LOG_PREFIX = "spring.datasource.druid.filter.commons-log";
                      private static final String FILTER_WALL_PREFIX = "spring.datasource.druid.filter.wall";
                      private static final String FILTER_WALL_CONFIG_PREFIX = "spring.datasource.druid.filter.wall.config";
                      ......省略部分......
                  }
                  

                  3.3 使用application.properties对druid进行配置

                  druid的配置如下所示:

                  # 配置druid监控功能
                  spring.datasource.druid.stat-view-servlet.enabled=true
                  spring.datasource.druid.stat-view-servlet.login-username=druid
                  spring.datasource.druid.stat-view-servlet.login-password=123456
                  spring.datasource.druid.stat-view-servlet.reset-enable=false
                  # 开启druid监控页面的sql监控菜单、防火墙菜单
                  spring.datasource.druid.filters=stat,wall,slf4j
                  # 对filters里面的stat的详细配置
                  spring.datasource.druid.filter.stat.enabled=true
                  spring.datasource.druid.filter.stat.log-slow-sql=true
                  # 1秒
                  spring.datasource.druid.filter.stat.slow-sql-millis=1000
                  # 对filters里面的wall的详细配置
                  spring.datasource.druid.filter.wall.enabled=true
                  spring.datasource.druid.filter.wall.config.update-allow=true
                  spring.datasource.druid.filter.wall.config.drop-table-allow=false
                  # 配置Web应用菜单功能
                  spring.datasource.druid.web-stat-filter.enabled=true
                  spring.datasource.druid.web-stat-filter.url-pattern=/*
                  spring.datasource.druid.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*
                  # 监控指定路径下的SpringBean。用于Spring监控菜单
                  spring.datasource.druid.aop-patterns=com.hh.springboottest.*
                  

                  3.4 druid配置参考

                  连接池配置

                  spring.datasource.druid.initial-size=
                  spring.datasource.druid.max-active=
                  spring.datasource.druid.min-idle=
                  spring.datasource.druid.max-wait=
                  spring.datasource.druid.pool-prepared-statements=
                  spring.datasource.druid.max-pool-prepared-statement-per-connection-size= 
                  # 和上面的等价
                  spring.datasource.druid.max-open-prepared-statements=
                  spring.datasource.druid.validation-query=
                  spring.datasource.druid.validation-query-timeout=
                  spring.datasource.druid.test-on-borrow=
                  spring.datasource.druid.test-on-return=
                  spring.datasource.druid.test-while-idle=
                  spring.datasource.druid.time-between-eviction-runs-millis=
                  spring.datasource.druid.min-evictable-idle-time-millis=
                  spring.datasource.druid.max-evictable-idle-time-millis=
                  # 配置多个英文逗号分隔
                  spring.datasource.druid.filters=
                  

                  监控配置

                   # WebStatFilter配置,说明请参考Druid Wiki,配置_配置WebStatFilter
                   # 是否启用StatFilter,默认值false
                  spring.datasource.druid.web-stat-filter.enabled=
                  spring.datasource.druid.web-stat-filter.url-pattern=
                  spring.datasource.druid.web-stat-filter.exclusions=
                  spring.datasource.druid.web-stat-filter.session-stat-enable=
                  spring.datasource.druid.web-stat-filter.session-stat-max-count=
                  spring.datasource.druid.web-stat-filter.principal-session-name=
                  spring.datasource.druid.web-stat-filter.principal-cookie-name=
                  spring.datasource.druid.web-stat-filter.profile-enable=
                   # StatViewServlet配置,说明请参考Druid Wiki,配置_StatViewServlet配置
                   # 是否启用StatViewServlet(监控页面),默认值为false(考虑到安全问题默认并未启动,如需启用建议设置密码或白名单以保障安全)
                  spring.datasource.druid.stat-view-servlet.enabled=
                  spring.datasource.druid.stat-view-servlet.url-pattern=
                  spring.datasource.druid.stat-view-servlet.reset-enable=
                  spring.datasource.druid.stat-view-servlet.login-username=
                  spring.datasource.druid.stat-view-servlet.login-password=
                  spring.datasource.druid.stat-view-servlet.allow=
                  spring.datasource.druid.stat-view-servlet.deny=
                   # Spring监控配置,说明请参考Druid Github Wiki,配置_Druid和Spring关联监控配置
                   # Spring监控AOP切入点,如x.y.z.service.*, 配置多个英文逗号分隔
                  spring.datasource.druid.aop-patterns=