文章目錄
-
- 一.前言
- 二.Durid 資料源概述
- 三.DruidDataSource基本配置
- 四.自定義資料源 Druid
-
- 1.引入 Druid 資料源依賴
- 2.切換 Druid 資料源
- 3.配置 Druid 資料源參數
- 五.Druid 資料源監控
-
- 1.配置 Druid 資料源監控
- 2.配置 Druid web 監控 filter
一.前言
本文介紹 Spring Boot 如何內建 Druid 資料源,如何實作資料庫監控
二.Durid 資料源概述
- Druid 是阿裡巴巴的一個開源的資料庫連接配接池實作,結合了 C3P0、DBCP、PROXOOL 等 DB 池的優點,同時加入了
日志監控
- Druid 可以很好的監控
,天生就是針對監控而生的 資料庫 連接配接池資料庫池連接配接和 SQL 的執行情況
-
以上Spring Boot 2.0
,可以說 Hikari 與 Driud 都是目前 Java Web 上最優秀的資料源預設使用 Hikari 資料源
三.DruidDataSource基本配置
配置 | 預設值 | 說明 |
---|---|---|
name | 配置這個屬性的意義在于,如果存在多個資料源,監控的時候可以通過名字來區分開來。 如果沒有配置,将會生成一個名字,格式是:“DataSource-” + System.identityHashCode(this) | |
jdbcUrl | 連接配接資料庫的url,不同資料庫不一樣。 例如: mysql : jdbc:mysql://10.20.153.104:3306/druid2 > oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto | |
username | 連接配接資料庫的使用者名 | |
password | 連接配接資料庫的密碼。如果你不希望密碼直接寫在配置檔案中,可以使用 。詳細看這裡 ConfigFilter作用: 1.從配置檔案中讀取配置 2.從遠端http檔案中讀取配置 3.為資料庫密碼提供加密功能 | |
driverClassName | 根據url自動識别 這一項可配可不配,如果不配置druid會根據url自動識别dbType,然後選擇相應的driverClassName(建議配置下) | |
initialSize | 初始化時建立實體連接配接的個數。初始化發生在顯示調用init方法,或者第一次getConnection時 | |
maxActive | 8 | 最大連接配接池數量 |
maxIdle | 8 | 已經不再使用,配置了也沒效果 |
minIdle | 最小連接配接池數量 | |
maxWait | 擷取連接配接時最大等待時間,機關毫秒。配置了maxWait之後,預設啟用公平鎖,并發效率會有所下降,如果需要可以通過配置useUnfairLock屬性為true使用非公平鎖。 | |
poolPreparedStatements | false | 是否緩存preparedStatement,也就是PSCache。PSCache對支援遊标的資料庫性能提升巨大,比如說oracle。在mysql下建議關閉。 |
maxOpenPreparedStatements | -1 | 要啟用PSCache,必須配置大于0,當大于0時,poolPreparedStatements自動觸發修改為true。在Druid中,不會存在Oracle下PSCache占用記憶體過多的問題,可以把這個數值配置大一些,比如說100 |
validationQuery | 用來檢測連接配接是否有效的sql,要求是一個查詢語句。如果validationQuery為null,testOnBorrow、testOnReturn、testWhileIdle都不會起作用。 | |
testOnBorrow | true | 申請連接配接時執行validationQuery檢測連接配接是否有效,,這裡建議配置為TRUE,防止取到的連接配接不可用 |
testOnReturn | false | 歸還連接配接時執行validationQuery檢測連接配接是否有效,做了這個配置會降低性能 |
testWhileIdle | false | 建議配置為true,不影響性能,并且保證安全性。申請連接配接的時候檢測,如果空閑時間大于timeBetweenEvictionRunsMillis,執行validationQuery檢測連接配接是否有效。 |
timeBetweenEvictionRunsMillis | 配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接配接,機關是毫秒 | |
numTestsPerEvictionRun | 不再使用,一個DruidDataSource隻支援一個EvictionRun | |
connectionInitSqls | 實體連接配接初始化的時候執行的sql | |
exceptionSorter | 根據dbType自動識别 | 當資料庫抛出一些不可恢複的異常時,抛棄連接配接 |
filters | 屬性類型是字元串,通過别名的方式配置擴充插件, 常用的插件有: 監控統計用的stat 日志用的 slf4j ,logback,log4j,log4j2 防禦sql注入的wall 配置多個時以英文逗号分隔 如: filters: stat,wall,slf4j | |
proxyFilters | 類型是List<com.alibaba.druid.filter.Filter>,如果同時配置了filters和proxyFilters,是組合關系,并非替換關系 |
四.自定義資料源 Druid
1.引入 Druid 資料源依賴
1、第一步需要在應用的 pom.xml 檔案中添加上 Druid 資料源依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>www.wmx.com.horse</groupId>
<artifactId>horse</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>horse</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/>
<!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- 引入Spring封裝的jdbc-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- 因為web項目啟動子產品-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 引入mysql資料庫連接配接驅動-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 引入 Druid 資料源依賴:https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
<!-- 引入Spring Boot 測試子產品-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins> </plugins>
<resources>
<!--src/main/resources下面所有檔案打包-->
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<!--src/main/java下面存在xml檔案也打包進去,解決 mapper與xml映射檔案處于同級目錄下卻無法找到檔案-->
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
</project>
2.切換 Druid 資料源
Spring Boot 2.0 以上預設使用
com.zaxxer.hikari.HikariDataSource
資料源,是以需要通過 配置
spring.datasource.type
指定資料源
spring:
datasource:
username: root
password: root
url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
高版本的 spring boot 搭配 mysql 驅動版本較高時,如 mysql-connector-java:8.0.16,
- 此時 driver-class-name 的值要帶 cj,如:driver-class-name: com.mysql.cj.jdbc.Driver
- url 的值要帶時區 serverTimezone,如:url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8&serverTimezone=UTC
測試: Spring擷取容器中的 DataSource ,然後輸出
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@RunWith(SpringRunner.class)
@SpringBootTest
public class HorseApplicationTests {
/**
* Spring Boot 預設已經配置好了資料源,程式員可以直接 DI 注入然後使用即可
*/
@Resource
DataSource dataSource;
@Test
public void contextLoads() throws SQLException {
System.out.println("資料源>>>>>>" + dataSource.getClass());
Connection connection = dataSource.getConnection();
System.out.println("連接配接>>>>>>>>>" + connection);
System.out.println("連接配接位址>>>>>" + connection.getMetaData().getURL());
connection.close();
}
}
3.配置 Druid 資料源參數
和 c3p0、dbcp 資料源 一樣,Druid也 也可以設定資料源連接配接初始化大小、最大連接配接數、等待時間、最小連接配接數等
- Druid 資料源參數配置在
中即可,如下所示:全局配置檔案application.yaml
spring:
datasource:
username: root
password: root
url: jdbc:mysql://192.168.58.129:3307/horse?characterEncoding=UTF-8
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
#上半區公共部分對應的是 org.springframework.boot.autoconfigure.jdbc.DataSourceProperties 中的屬性
#下半區屬性對應的是 com.alibaba.druid.pool.DruidDataSource 中的屬性,Spring Boot 預設是不注入不了這些屬性值的,需要自己綁定
#druid 資料源專有配置
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置監控統計攔截的filters,stat:監控統計、log4j:日志記錄、wall:防禦sql注入
#如果允許時報錯 java.lang.ClassNotFoundException: org.apache.log4j.Priority
#則導入 log4j 依賴即可,Maven 位址: https://mvnrepository.com/artifact/log4j/log4j
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
下半區 Druid 資料源的專有屬性對應的是
com.alibaba.druid.pool.DruidDataSource
中的屬性,雖然切換為 Druid 資料源之後**,Spring Boot 會自動生成 DruidDataSource 并放入容器中供程式員使用,但是它并不會自動綁定配置檔案的配置**
- 是以需要編寫一個配置類為
綁定全局配置檔案中的參數,再添加到容器中,而不再使用 Spring Boot 的自動生成了com.alibaba.druid.pool.DruidDataSource
Druid配置類
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class DruidConfig {
/**
* 将自定義的 Druid 資料源添加到容器中,不再讓 Spring Boot 自動建立
* 這樣做的目的是:綁定全局配置檔案中的 druid 資料源屬性到 com.alibaba.druid.pool.DruidDataSource
* 進而讓它們生效
* @ConfigurationProperties(prefix = "spring.datasource"):作用就是将 全局配置檔案中 字首為 spring.datasource
* 的屬性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名參數中
*
* @return
*/
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druidDataSource() {
return new DruidDataSource();
}
}
測試: Spring擷取容器中的 DataSource ,然後取值看配置檔案中的參數是否已經生效
import com.alibaba.druid.pool.DruidDataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@RunWith(SpringRunner.class)
@SpringBootTest
public class HorseApplicationTests {
/**
* Spring Boot 預設已經配置好了資料源,程式員可以直接 DI 注入然後使用即可
*/
@Resource
DataSource dataSource;
@Test
public void contextLoads() throws SQLException {
System.out.println("資料源>>>>>>" + dataSource.getClass());
Connection connection = dataSource.getConnection();
System.out.println("連接配接>>>>>>>>>" + connection);
System.out.println("連接配接位址>>>>>" + connection.getMetaData().getURL());
DruidDataSource druidDataSource = (DruidDataSource) dataSource;
System.out.println("druidDataSource 資料源最大連接配接數:" + druidDataSource.getMaxActive());
System.out.println("druidDataSource 資料源初始化連接配接數:" + druidDataSource.getInitialSize());
connection.close();
}
}
五.Druid 資料源監控
1.配置 Druid 資料源監控
- Druid 資料源具有監控的功能,并提供了一個 web 界面友善使用者檢視,類似安裝 路由器 時,人家也提供了一個預設的 web 頁面。
- 是以第一步需要設定 Druid 的背景管理頁面,比如 登入賬号、密碼 等
- 配置一個管理背景的 Servlet,因為使用的是内置 Servlet 容器
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import org.springframework.boot.context.properties.ConfigurationProperties;
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.util.HashMap;
import java.util.Map;
/**
* Created by Administrator on 2018/8/20 0020.
* Druid 資料源配置類
*/
@Configuration
public class DruidConfig {
/**
* 将自定義的 Druid 資料源添加到容器中,不再讓 Spring Boot 自動建立
* 這樣做的目的是:綁定全局配置檔案中的 druid 資料源屬性到 com.alibaba.druid.pool.DruidDataSource
* 進而讓它們生效
*
* @return
* @ConfigurationProperties(prefix = "spring.datasource"):作用就是将 全局配置檔案中 字首為 spring.datasource
* 的屬性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名參數中
*/
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druidDataSource() {
return new DruidDataSource();
}
/**
* 配置 Druid 監控 之 管理背景的 Servlet
* 内置 Servler 容器時沒有web.xml 檔案,是以使用 Spring Boot 的注冊 Servlet 方式
*/
@Bean
public ServletRegistrationBean statViewServlet() {
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(),
"/druid/*");
/**
* loginUsername:Druid 背景管理界面的登入賬号
* loginPassword:Druid 背景管理界面的登入密碼
* allow:Druid 背景允許誰可以通路
* initParams.put("allow", "localhost"):表示隻有本機可以通路
* initParams.put("allow", ""):為空或者為null時,表示允許所有通路
* deny:Druid 背景拒絕誰通路
* initParams.put("deny", "192.168.1.20");表示禁止此ip通路
*/
Map<String, String> initParams = new HashMap<>();
initParams.put("loginUsername", "admin");
initParams.put("loginPassword", "123456");
initParams.put("allow", "");
/*initParams.put("deny", "192.168.1.20");*/
/** 設定初始化參數*/
bean.setInitParameters(initParams);
return bean;
}
}
- 這些參數可以在
的父類com.alibaba.druid.support.http.StatViewServlet
中找到com.alibaba.druid.support.http.ResourceServlet
- 運作應用,測試結果
【SpringBoot】整合 Mybatis 實作 Druid資料源監控(Mysql)
2.配置 Druid web 監控 filter
- 這個過濾器的作用就是統計 web 應用請求中所有的資料庫資訊,比如 發出的 sql 語句,sql 執行的時間、請求次數、請求的 url 位址、以及seesion 監控、資料庫表的通路次數 等等。
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.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Administrator on 2018/8/20 0020.
* Druid 資料源配置類
*/
@Configuration
public class DruidConfig {
/**
* 将自定義的 Druid 資料源添加到容器中,不再讓 Spring Boot 自動建立
* 這樣做的目的是:綁定全局配置檔案中的 druid 資料源屬性到 com.alibaba.druid.pool.DruidDataSource
* 進而讓它們生效
*
* @return
* @ConfigurationProperties(prefix = "spring.datasource"):作用就是将 全局配置檔案中 字首為 spring.datasource
* 的屬性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名參數中
*/
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druidDataSource() {
return new DruidDataSource();
}
/**
* 配置 Druid 監控 之 管理背景的 Servlet
* 内置 Servler 容器時沒有web.xml 檔案,是以使用 Spring Boot 的注冊 Servlet 方式
*/
@Bean
public ServletRegistrationBean statViewServlet() {
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(),
"/druid/*");
/**
* loginUsername:Druid 背景管理界面的登入賬号
* loginPassword:Druid 背景管理界面的登入密碼
* allow:Druid 背景允許誰可以通路
* initParams.put("allow", "localhost"):表示隻有本機可以通路
* initParams.put("allow", ""):為空或者為null時,表示允許所有通路
* deny:Druid 背景拒絕誰通路
* initParams.put("deny", "192.168.1.20");表示禁止此ip通路
*/
Map<String, String> initParams = new HashMap<>();
initParams.put("loginUsername", "admin");
initParams.put("loginPassword", "123456");
initParams.put("allow", "");
/*initParams.put("deny", "192.168.1.20");*/
/** 設定初始化參數*/
bean.setInitParameters(initParams);
return bean;
}
/**
* 配置 Druid 監控 之 web 監控的 filter
* WebStatFilter:用于配置Web和Druid資料源之間的管理關聯監控統計
*/
@Bean
public FilterRegistrationBean webStatFilter() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
/** exclusions:設定哪些請求進行過濾排除掉,進而不進行統計*/
Map<String, String> initParams = new HashMap<>();
initParams.put("exclusions", "*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
/** "/*" 表示過濾所有請求*/
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}
2、運作應用,可以往背景發一些請求,同時進行一些 資料庫 sql 操作,測試結果效果如下:
注意: 資料連接配接池是在我們第一次請求資料庫的時候進行初始化的(懶加載)。