Druid:簡述對數據庫連接池Druid的認識和使用

一、Druid介紹

Druid是一個數據庫連接池,可以說是目前最好的!因其優秀的功能、性能和擴展性方面,深受開發人員的青睞。

阿里巴巴已經部署了超過600個使用Druid的應用,經過一年多生產環境大規模部署的嚴苛考驗。Druid是阿里巴巴開發的號稱爲監控而生的數據庫連接池!

Druid的主要功能如下:

  • 一個高效、功能強大、可擴展性好的數據庫連接池。
  • 可以監控數據庫訪問性能。
  • 進行數據庫密碼加密 。
  • 獲得SQL執行日誌 。
  • 擴展JDBCDruid。

Druid的核心主要包括三部分:

  • 基於Filter-Chain模式的插件體系。
  • DruidDataSource 高效可管理的數據庫連接池。
  • SQLParser。

二、Druid的Maven依賴及配置

2.1 Druid的Maven依賴

<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>druid</artifactId>
	<version>1.1.8</version>
</dependency>

2.2 Druid在SpringBoot中的配置文件

只需要在application.properties或application.yml添加如下配置:

# 默認的數據源
master.datasource.url=jdbc:mysql://localhost:3306/springBoot?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
master.datasource.username=root
master.datasource.password=123456
master.datasource.driverClassName=com.mysql.jdbc.Driver


# 另一個的數據源
cluster.datasource.url=jdbc:mysql://localhost:3306/springBoot_test?useUnicode=true&characterEncoding=utf8
cluster.datasource.username=root
cluster.datasource.password=123456
cluster.datasource.driverClassName=com.mysql.jdbc.Driver

# 連接池的配置信息
# 初始化大小,最小,最大
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
# 配置獲取連接等待超時的時間
spring.datasource.maxWait=60000
# 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連接,單位是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一個連接在池中最小生存的時間,單位是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
# 打開PSCache,並且指定每個連接上PSCache的大小
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
# 配置監控統計攔截的filters,去掉後監控界面sql無法統計,'wall'用於防火牆
spring.datasource.filters=stat,wall,log4j
# 通過connectProperties屬性來打開mergeSql功能;慢SQL記錄
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

2.3 Druid在項目中的多數據源配置類

  1. 默認(master)數據源配置類

有兩個註解需要說明下:

  • @Primary :標誌這個 Bean 如果在多個同類 Bean 候選時,該 Bean
    優先被考慮。多數據源配置的時候注意,必須要有一個主數據源,用 @Primary 標誌該 Bean。
  • @MapperScan:掃描 Mapper 接口並容器管理。

需要注意的是sqlSessionFactoryRef 表示定義一個唯一 SqlSessionFactory 實例。進行下述的配置完之後,就可以將Druid作爲連接池使用了。

@Configuration
@MapperScan(basePackages = MasterDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterDataSourceConfig {

    static final String PACKAGE = "com.pancm.dao.master";
    static final String MAPPER_LOCATION = "classpath:mapper/master/*.xml";

    @Value("${master.datasource.url}")
    private String url;
    @Value("${master.datasource.username}")
    private String username;
    @Value("${master.datasource.password}")
    private String password;

    @Value("${master.datasource.driverClassName}")
    private String driverClassName;

    @Value("${spring.datasource.initialSize}")
    private int initialSize;
    @Value("${spring.datasource.minIdle}")
    private int minIdle;
    @Value("${spring.datasource.maxActive}")
    private int maxActive;
    @Value("${spring.datasource.maxWait}")
    private int maxWait;

    @Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
    private int timeBetweenEvictionRunsMillis;
    @Value("${spring.datasource.minEvictableIdleTimeMillis}")
    private int minEvictableIdleTimeMillis;

    @Value("${spring.datasource.validationQuery}")
    private String validationQuery;

    @Value("${spring.datasource.testWhileIdle}")
    private boolean testWhileIdle;
    @Value("${spring.datasource.testOnBorrow}")
    private boolean testOnBorrow;

    @Value("${spring.datasource.testOnReturn}")
    private boolean testOnReturn;

    @Value("${spring.datasource.poolPreparedStatements}")
    private boolean poolPreparedStatements;
    @Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")
    private int maxPoolPreparedStatementPerConnectionSize;

    @Value("${spring.datasource.filters}")
    private String filters;

    @Value("{spring.datasource.connectionProperties}")
    private String connectionProperties;


    @Bean(name = "masterDataSource")
    @Primary
    public DataSource masterDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setDriverClassName(driverClassName);

        //具體配置
        dataSource.setInitialSize(initialSize);
        dataSource.setMinIdle(minIdle);
        dataSource.setMaxActive(maxActive);
        dataSource.setMaxWait(maxWait);
        dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        dataSource.setValidationQuery(validationQuery);
        dataSource.setTestWhileIdle(testWhileIdle);
        dataSource.setTestOnBorrow(testOnBorrow);
        dataSource.setTestOnReturn(testOnReturn);
        dataSource.setPoolPreparedStatements(poolPreparedStatements);
        dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
        try {
            dataSource.setFilters(filters);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        dataSource.setConnectionProperties(connectionProperties);
        return dataSource;
    }

    @Bean(name = "masterTransactionManager")
    @Primary
    public DataSourceTransactionManager masterTransactionManager() {
        return new DataSourceTransactionManager(masterDataSource());
    }

    @Bean(name = "masterSqlSessionFactory")
    @Primary
    public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource masterDataSource)
            throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(masterDataSource);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources(MasterDataSourceConfig.MAPPER_LOCATION));
        return sessionFactory.getObject();
    }
}
  1. 集羣備選(cluster)數據源配置類

第二個集羣備選數據源的配置和上面的MasterDataSourceConfig.java差不多,區別在與沒有使用@Primary 註解和名稱不同而已。需要注意的是MasterDataSourceConfig.java對package和mapper的掃描是精確到目錄的,這裏的第二個數據源也是如此。

@Configuration
@MapperScan(basePackages = ClusterDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "clusterSqlSessionFactory")
public class ClusterDataSourceConfig {

 static final String PACKAGE = "com.pancm.dao.cluster";
 static final String MAPPER_LOCATION = "classpath:mapper/cluster/*.xml";

 @Value("${cluster.datasource.url}")
 private String url;

 @Value("${cluster.datasource.username}")
 private String username;

 @Value("${cluster.datasource.password}")
 private String password;

 @Value("${cluster.datasource.driverClassName}")
 private String driverClass;

 // 和MasterDataSourceConfig一樣,這裏略

 @Bean(name = "clusterDataSource")
 public DataSource clusterDataSource() {
     DruidDataSource dataSource = new DruidDataSource();
     dataSource.setUrl(url);
     dataSource.setUsername(username);
     dataSource.setPassword(password);
     dataSource.setDriverClassName(driverClass);

     // 和MasterDataSourceConfig一樣,這裏略 ...
     return dataSource;
 }

 @Bean(name = "clusterTransactionManager")
 public DataSourceTransactionManager clusterTransactionManager() {
     return new DataSourceTransactionManager(clusterDataSource());
 }

 @Bean(name = "clusterSqlSessionFactory")
 public SqlSessionFactory clusterSqlSessionFactory(@Qualifier("clusterDataSource") DataSource clusterDataSource)
         throws Exception {
     final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
     sessionFactory.setDataSource(clusterDataSource);
     sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(ClusterDataSourceConfig.MAPPER_LOCATION));
     return sessionFactory.getObject();
 }
}

2.4 Druid的監控功能

Druid不僅是一個連接池,它也可以說是一個監控應用,它自帶了web監控界面,可以很清晰的看到SQL相關信息。

在SpringBoot中運用Druid的監控作用,只需要編寫StatViewServlet和WebStatFilter類,實現註冊服務和過濾規則。這裏我們可以將這兩個寫在一起,使用@Configuration和@Bean。代碼如下:

@Configuration
public class DruidConfiguration {

    @Bean
    public ServletRegistrationBean druidStatViewServle() {
        //註冊服務
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(
                new StatViewServlet(), "/druid/*");
        // 白名單(爲空表示,所有的都可以訪問,多個IP的時候用逗號隔開)
        servletRegistrationBean.addInitParameter("allow", "127.0.0.1");
        // IP黑名單 (存在共同時,deny優先於allow)
        servletRegistrationBean.addInitParameter("deny", "127.0.0.2");
        // 設置登錄的用戶名和密碼
        servletRegistrationBean.addInitParameter("admin", "admin");
        servletRegistrationBean.addInitParameter("root", "root");
        // 是否能夠重置數據.
        servletRegistrationBean.addInitParameter("resetEnable", "false");
        return servletRegistrationBean;
    }

    @Bean
    public FilterRegistrationBean druidStatFilter() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
        // 添加過濾規則
        filterRegistrationBean.addUrlPatterns("/*");
        // 添加不需要忽略的格式信息
        filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
        System.out.println("druid初始化成功!");
        return filterRegistrationBean;

    }
}

編寫完之後,啓動程序,在瀏覽器輸入:http://127.0.0.1:8084/druid/index.html ,然後輸入設置的用戶名和密碼,便可以訪問Web界面了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章