天天看點

【SpringBoot】整合 Mybatis 實作 Druid資料源監控(Mysql)

文章目錄

    • 一.前言
    • 二.Durid 資料源概述
    • 三.DruidDataSource基本配置
    • 四.自定義資料源 Druid
      • 1.引入 Druid 資料源依賴
      • 2.切換 Druid 資料源
      • 3.配置 Druid 資料源參數
    • 五.Druid 資料源監控
      • 1.配置 Druid 資料源監控
      • 2.配置 Druid web 監控 filter

一.前言

本文介紹 Spring Boot 如何內建 Druid 資料源,如何實作資料庫監控

二.Durid 資料源概述

  1. Druid 是阿裡巴巴的一個開源的資料庫連接配接池實作,結合了 C3P0、DBCP、PROXOOL 等 DB 池的優點,同時加入了

    日志監控

  2. Druid 可以很好的監控

    資料庫池連接配接和 SQL 的執行情況

    ,天生就是針對監控而生的 資料庫 連接配接池
  3. Spring Boot 2.0

    以上

    預設使用 Hikari 資料源

    ,可以說 Hikari 與 Driud 都是目前 Java Web 上最優秀的資料源

三.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

。詳細看這裡

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 并放入容器中供程式員使用,但是它并不會自動綁定配置檔案的配置**

  • 是以需要編寫一個配置類為

    com.alibaba.druid.pool.DruidDataSource

    綁定全局配置檔案中的參數,再添加到容器中,而不再使用 Spring Boot 的自動生成了

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 資料源監控

  1. Druid 資料源具有監控的功能,并提供了一個 web 界面友善使用者檢視,類似安裝 路由器 時,人家也提供了一個預設的 web 頁面。
  2. 是以第一步需要設定 Druid 的背景管理頁面,比如 登入賬号、密碼 等
  3. 配置一個管理背景的 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;
    }
}
           
  1. 這些參數可以在

    com.alibaba.druid.support.http.StatViewServlet

    的父類

    com.alibaba.druid.support.http.ResourceServlet

    中找到
  2. 運作應用,測試結果
    【SpringBoot】整合 Mybatis 實作 Druid資料源監控(Mysql)

2.配置 Druid web 監控 filter

  1. 這個過濾器的作用就是統計 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 操作,測試結果效果如下:

【SpringBoot】整合 Mybatis 實作 Druid資料源監控(Mysql)

注意: 資料連接配接池是在我們第一次請求資料庫的時候進行初始化的(懶加載)。

【SpringBoot】整合 Mybatis 實作 Druid資料源監控(Mysql)

繼續閱讀