SpringBoot08:整合Druid

Druid簡介

Java程序很大一部分要操作數據庫,爲了提高性能操作數據庫的時候,又不得不使用數據庫連接池。

Druid 是阿里巴巴開源平臺上一個數據庫連接池實現,結合了 C3P0、DBCP 等 DB 池的優點,同時加入了日誌監控。

Druid 可以很好的監控 DB 池連接和 SQL 的執行情況,天生就是針對監控而生的 DB 連接池。

Druid已經在阿里巴巴部署了超過600個應用,經過一年多生產環境大規模部署的嚴苛考驗。

Spring Boot 2.0 以上默認使用 Hikari 數據源,可以說 Hikari 與 Driud 都是當前 Java Web 上最優秀的數據源,我們來重點介紹 Spring Boot 如何集成 Druid 數據源,如何實現數據庫監控。

Github地址:https://github.com/alibaba/druid/

com.alibaba.druid.pool.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。詳細看這裏:https://github.com/alibaba/druid/wiki/%E4%BD%BF%E7%94%A8ConfigFilter
driverClassName 根據url自動識別 這一項可配可不配,如果不配置druid會根據url自動識別dbType,然後選擇相應的driverClassName(建議配置下)
initialSize 0 初始化時建立物理連接的個數。初始化發生在顯示調用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都不會其作用。
validationQueryTimeout 單位:秒,檢測連接是否有效的超時時間。底層調用jdbc
Statement對象的void setQueryTimeout(int seconds)方法
testOnBorrow true 申請連接時執行validationQuery檢測連接是否有效,做了這個配置會降低性能。
testOnReturn false 歸還連接時執行validationQuery檢測連接是否有效,做了這個配置會降低性能
testWhileIdle false 建議配置爲true,不影響性能,並且保證安全性。申請連接的時候檢測,如果空閒時間大於timeBetweenEvictionRunsMillis,執行validationQuery檢測連接是否有效。
timeBetweenEvictionRunsMillis 1分鐘
( 1.0.14 )
有兩個含義: 1) Destroy線程會檢測連接的間隔時間 2) testWhileIdle的判斷依據,詳細看testWhileIdle屬性的說明
numTestsPerEvictionRun 不再使用,一個DruidDataSource只支持一個EvictionRun
minEvictableIdleTimeMillis 30分鐘
( 1.0.14 )
連接保持空閒而不被驅逐的最長時間
connectionInitSqls 物理連接初始化的時候執行的sql
exceptionSorter 根據dbType自動識別 當數據庫拋出一些不可恢復的異常時,拋棄連接
filters 屬性類型是字符串,通過別名的方式配置擴展插件,常用的插件有: 監控統計用的filter:stat日誌用的filter:log4j防禦sql注入的filter:wall
proxyFilters 類型是List<com.alibaba.druid.filter.Filter>,如果同時配置了filters和proxyFilters,是組合關係,並非替換關係

配置數據源

  1. 新建模塊

  2. 添加上 Druid 數據源依賴

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.22</version>
</dependency>
  1. 切換數據源;之前已經說過 Spring Boot 2.0 以上默認使用 com.zaxxer.hikari.HikariDataSource 數據源,但可以 通過 spring.datasource.type 指定數據源。
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    username: root
    password: 123456
    type: com.alibaba.druid.pool.DruidDataSource # 自定義數據源
  1. 數據源切換之後,在測試類中注入 DataSource,然後獲取到它,輸出一看便知是否成功切換
@SpringBootTest
class SpringbootDataDruidApplicationTests {

    //DI注入數據源
    @Autowired
    DataSource dataSource;

    @Test
    void contextLoads() throws SQLException {
        //看一下默認數據源
        System.out.println(dataSource.getClass());
        //獲得連接
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
        //關閉連接
        connection.close();
    }

}

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-RtZbFuSM-1590650013448)(C:\Users\leomo\AppData\Roaming\Typora\typora-user-images\image-20200528145553375.png)]

  1. 既然切換成功,就可以設置數據源連接初始化大小、最大連接數、等待時間、最小連接數 等設置項;可以查看源碼
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    username: root
    password: 123456
    type: 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
  1. 導入Log4j 的依賴
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
  1. 現在需要程序員自己爲 DruidDataSource 綁定全局配置文件中的參數,再添加到容器中,而不再使用 Spring Boot 的自動生成的;我們需要 自己添加 DruidDataSource 組件到容器中,並綁定屬性;
package com.godfrey.config;

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;

/**
 * description : 添加 DruidDataSource 組件到容器
 *
 * @author godfrey
 * @since 2020-05-28
 */
@Configuration
public class DruidConfig {

    /**
       將自定義的 Druid數據源添加到容器中,不再讓 Spring Boot 自動創建
       綁定全局配置文件中的 druid 數據源屬性到 com.alibaba.druid.pool.DruidDataSource從而讓它們生效
       @ConfigurationProperties(prefix = "spring.datasource"):作用就是將 全局配置文件中
       前綴爲 spring.datasource的屬性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名參數中
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource druidDataSource() {
        return new DruidDataSource();
    }
}
  1. 去測試類中測試一下;看是否成功!
package com.godfrey;

import com.alibaba.druid.pool.DruidDataSource;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

@SpringBootTest
class SpringbootDataDruidApplicationTests {

    //DI注入數據源
    @Autowired
    DataSource dataSource;

    @Test
    void contextLoads() throws SQLException {
        //看一下默認數據源
        System.out.println(dataSource.getClass());
        //獲得連接
        Connection connection =   dataSource.getConnection();
        System.out.println(connection);

        DruidDataSource druidDataSource = (DruidDataSource) dataSource;
        System.out.println("druidDataSource 數據源最大連接數:" + druidDataSource.getMaxActive());
        System.out.println("druidDataSource 數據源初始化連接數:" + druidDataSource.getInitialSize());

        //關閉連接
        connection.close();
    }

}

輸出結果 :可見配置參數已經生效!

配置Druid數據源監控

Druid 數據源具有監控的功能,並提供了一個 web 界面方便用戶查看,類似安裝 路由器 時,人家也提供了一個默認的 web 頁面。

所以第一步需要設置 Druid 的後臺管理頁面,比如 登錄賬號、密碼 等;配置後臺管理;

//配置 Druid 監控管理後臺的Servlet;
//內置 Servlet 容器時沒有web.xml文件,所以使用 Spring Boot 的註冊 Servlet 方式
@Bean
public ServletRegistrationBean statViewServlet() {
    ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
                                                               
    // 這些參數可以在 com.alibaba.druid.support.http.StatViewServlet
    // 的父類 com.alibaba.druid.support.http.ResourceServlet 中找到                                                         
    Map<String, String> initParams = new HashMap<>();
    initParams.put("loginUsername", "admin"); //後臺管理界面的登錄賬號
    initParams.put("loginPassword", "123456"); //後臺管理界面的登錄密碼
                                                               
    //後臺允許誰可以訪問
    //initParams.put("allow", "localhost"):表示只有本機可以訪問
    //initParams.put("allow", ""):爲空或者爲null時,表示允許所有訪問
    initParams.put("allow", "");
    //deny:Druid 後臺拒絕誰訪問
    //initParams.put("godfrey", "192.168.1.1");表示禁止此ip訪問
                                                               
    //設置初始化參數
    bean.setInitParameters(initParams);
    return bean;
}

配置完畢後,我們可以選擇訪問 :http://localhost:8080/druid/login.html

進入之後:

配置 Druid web 監控 filter 過濾器

//配置 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/*,/jdbc/*");
    bean.setInitParameters(initParams);

    //"/*" 表示過濾所有請求
    bean.setUrlPatterns(Arrays.asList("/*"));
    return bean;
}

在平時中,按需求進行配置即可,主要用作監控!

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