Spring Boot官方推薦的數(shù)據(jù)庫連接池是HikariCP,從一些第三方的評測結(jié)果看挠铲,HikariCP的性能比Druid要好寂诱,但是Druid自帶各種監(jiān)控工具,背后又有阿里一直在為它背書瓢棒,還是迎得了很多人的歡迎带迟,本文就講述Spring Boot如何集成Druid數(shù)據(jù)源。
由于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中新增數(shù)據(jù)庫連接池配置
#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
# 下面為連接池的補(bǔ)充設(shè)置,應(yīng)用到上面所有數(shù)據(jù)源中
# 初始化大小财边,最小点骑,最大
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
# 配置獲取連接等待超時的時間
spring.datasource.maxWait=60000
# 配置間隔多久才進(jìn)行一次檢測谍夭,檢測需要關(guān)閉的空閑連接紧索,單位是毫秒
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
# 配置監(jiān)控統(tǒng)計攔截的filters媳危,去掉后監(jiān)控界面sql無法統(tǒng)計冈敛,'wall'用于防火墻
spring.datasource.filters=stat,wall,log4j
# 通過connectProperties屬性來打開mergeSql功能;慢SQL記錄
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 合并多個DruidDataSource的監(jiān)控數(shù)據(jù)
spring.datasource.useGlobalDataSourceStat=true
#druid datasouce database settings end
定義Filter滋觉,忽略靜態(tài)資源的攔截
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優(yōu)先于allow)
@WebInitParam(name="loginUsername",value="admin"),// 用戶名
@WebInitParam(name="loginPassword",value="123456"),// 密碼
@WebInitParam(name="resetEnable",value="false")// 禁用HTML頁面上的“Reset All”功能
})
public class DruidStatViewServlet extends StatViewServlet {
}
主執(zhí)行類上注意要加上@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);
}
}
接下來就可以打開http://localhost:8080/druid/index.html看到效果了券犁,如下圖所示
Spring Boot 1.4.X配置
我一開始是在1.3.3.RELEASE版本上集成Druid粘衬,遷移到Spring Boot1.4.2版本時發(fā)現(xiàn)SQL控制臺無論如何都無法監(jiān)控到SQL操作咳促,不得已使用@Bean裝配方式來配置Druid數(shù)據(jù)源,終于發(fā)現(xiàn)可以正常工作了褂删。沒看過源碼冲茸,但猜想可能是由于Spring Boot升級版本的時候缅帘,與Druid有沖突难衰,下面講述@Bean裝配方式實現(xiàn)Druid數(shù)據(jù)源配置。
新增Druid數(shù)據(jù)源配置文件
刪除原有application.properties中druid的相關(guān)配置铃诬,新增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
# 下面為連接池的補(bǔ)充設(shè)置苍凛,應(yīng)用到上面所有數(shù)據(jù)源中
# 初始化大小,最小宣肚,最大
spring.druid.datasource.initialSize=5
spring.druid.datasource.minIdle=5
spring.druid.datasource.maxActive=20
# 配置獲取連接等待超時的時間
spring.druid.datasource.maxWait=60000
# 配置間隔多久才進(jìn)行一次檢測悠栓,檢測需要關(guān)閉的空閑連接,單位是毫秒
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
# 配置監(jiān)控統(tǒng)計攔截的filters,去掉后監(jiān)控界面sql無法統(tǒng)計错洁,'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的監(jiān)控數(shù)據(jù)
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方式讀取配置并實例化數(shù)據(jù)源
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());//這是最關(guān)鍵的,否則SQL監(jiān)控?zé)o法生效
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;
}
}