1. 程式人生 > >Spring Boot整合Druid資料來源

Spring Boot整合Druid資料來源

Spring Boot官方推薦的資料庫連線池是HikariCP,從一些第三方的評測結果看,HikariCP的效能比Druid要好,但是Druid自帶各種監控工具,背後又有阿里一直在為它背書,還是迎得了很多人的歡迎,本文就講述Spring Boot如何整合Druid資料來源。
由於Spring Boot的1.3.X和1.4.X版本對druid的配置方法略有不同,下面分開來描述。

Spring Boot 1.3.X 配置

引入Druid依賴

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

application.properties中新增資料庫連線池配置

#druid datasouce database settings begin
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/spring_boot?characterEncoding=utf-8 spring.datasource.username=root spring.datasource.password=123456 # 下面為連線池的補充設定,應用到上面所有資料來源中 # 初始化大小,最小,最大 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 # 合併多個DruidDataSource的監控資料 spring.datasource.useGlobalDataSourceStat=true #druid datasouce database settings end

定義Filter,忽略靜態資源的攔截

package com.bluecoffee.filter;

import com.alibaba.druid.support.http.WebStatFilter;

import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;

/**
 * Created by qianlong on 16/12/21.
 */
@WebFilter(filterName="druidStatFilter",urlPatterns="/*",
        initParams={
                @WebInitParam(name="exclusions",value="*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*")// 忽略資源
        })
public class DruidStatFilter extends WebStatFilter {

}

定義Servlet,用於Druid控制檯的檢視

package com.bluecoffee.servlet;

import com.alibaba.druid.support.http.StatViewServlet;

import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;

/**
 * Created by qianlong on 16/8/25.
 */
@SuppressWarnings("serial")
@WebServlet(urlPatterns = "/druid/*",
        initParams={
                @WebInitParam(name="allow",value="192.168.16.110,127.0.0.1"),// IP白名單 (沒有配置或者為空,則允許所有訪問)
                @WebInitParam(name="deny",value="192.168.16.111"),// IP黑名單 (存在共同時,deny優先於allow)
                @WebInitParam(name="loginUsername",value="admin"),// 使用者名稱
                @WebInitParam(name="loginPassword",value="123456"),// 密碼
                @WebInitParam(name="resetEnable",value="false")// 禁用HTML頁面上的“Reset All”功能
        })
public class DruidStatViewServlet extends StatViewServlet {

}

主執行類上注意要加上@ServletComponentScan註解,否則Servlet無法生效

@SpringBootApplication
@ServletComponentScan
@Configuration
@EnableAutoConfiguration
public class Application {

    public static void main(String[] args) throws Exception {
        System.out.println("------------Application is start---------------");
        SpringApplication.run(Application.class, args);
    }
}

Druid控制檯

Spring Boot 1.4.X配置

我一開始是在1.3.3.RELEASE版本上整合Druid,遷移到Spring Boot1.4.2版本時發現SQL控制檯無論如何都無法監控到SQL操作,不得已使用@Bean裝配方式來配置Druid資料來源,終於發現可以正常工作了。沒看過原始碼,但猜想可能是由於Spring Boot升級版本的時候,與Druid有衝突,下面講述@Bean裝配方式實現Druid資料來源配置。

新增Druid資料來源配置檔案

刪除原有application.properties中druid的相關配置,新增druid-config.properties配置檔案

#druid datasouce database settings begin
spring.druid.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.druid.datasource.driverClassName=com.mysql.jdbc.Driver
spring.druid.datasource.url=jdbc:mysql://localhost:3306/spring_boot?characterEncoding=utf-8
spring.druid.datasource.username=root
spring.druid.datasource.password=123456

# 下面為連線池的補充設定,應用到上面所有資料來源中
# 初始化大小,最小,最大
spring.druid.datasource.initialSize=5
spring.druid.datasource.minIdle=5
spring.druid.datasource.maxActive=20
# 配置獲取連線等待超時的時間
spring.druid.datasource.maxWait=60000
# 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒
spring.druid.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一個連線在池中最小生存的時間,單位是毫秒
spring.druid.datasource.minEvictableIdleTimeMillis=300000
spring.druid.datasource.validationQuery=SELECT 1 FROM DUAL
spring.druid.datasource.testWhileIdle=true
spring.druid.datasource.testOnBorrow=false
spring.druid.datasource.testOnReturn=false
# 開啟PSCache,並且指定每個連線上PSCache的大小
spring.druid.datasource.poolPreparedStatements=true
spring.druid.datasource.maxPoolPreparedStatementPerConnectionSize=20
# 配置監控統計攔截的filters,去掉後監控介面sql無法統計,'wall'用於防火牆
spring.druid.datasource.filters=stat,wall,log4j,config
# 通過connectProperties屬性來開啟mergeSql功能;慢SQL記錄
spring.druid.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 合併多個DruidDataSource的監控資料
spring.druid.datasource.useGlobalDataSourceStat=true
#druid datasouce database settings end

新增屬性讀取類DruidSettings.java

package com.bluecoffee.configuration;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * Created by qianlong on 2016/12/21.
 */
@ConfigurationProperties(prefix = "spring.druid.datasource",locations = "classpath:druid-config.properties")
public class DruidSettings {

    private String type;
    private String driverClassName;
    private String url;
    private String username;
    private String password;

    private Integer initialSize;
    private Integer minIdle;
    private Integer maxActive;
    private Long maxWait;
    private Long timeBetweenEvictionRunsMillis;
    private Long minEvictableIdleTimeMillis;
    private String validationQuery;
    private boolean testWhileIdle;
    private boolean testOnBorrow;
    private boolean testOnReturn;
    private boolean poolPreparedStatements;
    private Integer maxPoolPreparedStatementPerConnectionSize;
    private String filters;
    private String connectionProperties;
    private boolean useGlobalDataSourceStat;

    //省略getter/setter方法

}

用Bean方式讀取配置並例項化資料來源

package com.bluecoffee.configuration;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;

/**
 * Created by qianlong on 2016/12/21.
 */
@Configuration
@EnableConfigurationProperties(DruidSettings.class)
public class DruidDataSourceConfig {

    @Autowired
    private DruidSettings druidSettings;

    @Bean
    @ConfigurationProperties("spring.druid.datasource")
    public DruidDataSource dataSource(
            DataSourceProperties properties) throws Exception{
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(druidSettings.getDriverClassName());
        dataSource.setUrl(druidSettings.getUrl());
        dataSource.setUsername(druidSettings.getUsername());
        dataSource.setPassword(druidSettings.getPassword());
        dataSource.setInitialSize(druidSettings.getInitialSize());
        dataSource.setMinIdle(druidSettings.getMinIdle());
        dataSource.setMaxActive(druidSettings.getMaxActive());
        dataSource.setMaxWait(druidSettings.getMaxWait());
        dataSource.setTimeBetweenEvictionRunsMillis(druidSettings.getTimeBetweenEvictionRunsMillis());
        dataSource.setMinEvictableIdleTimeMillis(druidSettings.getMinEvictableIdleTimeMillis());
        String validationQuery = druidSettings.getValidationQuery();
        if (validationQuery != null && !"".equals(validationQuery)) {
            dataSource.setValidationQuery(validationQuery);
        }
        dataSource.setTestWhileIdle(druidSettings.isTestWhileIdle());
        dataSource.setTestOnBorrow(druidSettings.isTestOnBorrow());
        dataSource.setTestOnReturn(druidSettings.isTestOnReturn());
        if(druidSettings.isPoolPreparedStatements()){
            dataSource.setMaxPoolPreparedStatementPerConnectionSize(druidSettings.getMaxPoolPreparedStatementPerConnectionSize());
        }
        dataSource.setFilters(druidSettings.getFilters());//這是最關鍵的,否則SQL監控無法生效
        String connectionPropertiesStr = druidSettings.getConnectionProperties();
        if(connectionPropertiesStr != null && !"".equals(connectionPropertiesStr)){
            Properties connectProperties = new Properties();
            String[] propertiesList = connectionPropertiesStr.split(";");
            for(String propertiesTmp:propertiesList){
                String[] obj = propertiesTmp.split("=");
                String key = obj[0];
                String value = obj[1];
                connectProperties.put(key,value);
            }
            dataSource.setConnectProperties(connectProperties);
        }
        dataSource.setUseGlobalDataSourceStat(druidSettings.isUseGlobalDataSourceStat());

        return dataSource;
    }
}

此時再執行主執行類即可正常執行Druid控制檯