1. 程式人生 > 其它 >log4j2+springboot+Druid的使用

log4j2+springboot+Druid的使用

1 基本概念

雖然 HikariCP 的速度稍快,但是,Druid能夠提供強大的監控和擴充套件功能,也是阿里巴巴的開源專案。

Druid是阿里巴巴開發的號稱為監控而生的資料庫連線池,在功能、效能、擴充套件性方面,都超過其他資料庫連線池,包括DBCPC3P0BoneCPProxoolJBoss DataSource等等等,秒殺一切。

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

Spring Boot 預設資料來源 HikariDataSource JdbcTemplate中已經介紹 Spring Boot 2.x 預設使用 Hikari

資料來源,可以說 Hikari Driud 都是當前 Java Web 上最優秀的資料來源。

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

statDruid內建提供一個StatFilter,用於統計監控資訊。

wallDruid防禦SQL注入攻擊的WallFilter就是通過DruidSQL Parser分析。Druid提供的SQL Parser可以在JDBC層攔截SQL做相應處理,比如說分庫分表、審計等。

log4j2:這個就是 日誌記錄的功能,可以把sql語句列印到log4j2 供排查問題。

2 新增依賴

推薦一個 Spring Boot

基礎教程及實戰示例:

https://github.com/javastacks/spring-boot-best-practice

pom.xml

<!-- 阿里巴巴的druid資料來源 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.23</version>
</dependency>
<!-- mysql8 驅動-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<!--使用 log4j2 記錄日誌-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!--springbootweb的依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- mybatis,引入了 SpringBoot的 JDBC 模組, 所以,預設是使用 hikari 作為資料來源 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
<exclusions>
<!-- 排除預設的 HikariCP 資料來源 -->
<exclusion>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</exclusion> </exclusions>
</dependency>

 

3 配置相關屬性

配置Druid資料來源(連線池): 如同以前 c3p0dbcp 資料來源可以設定資料來源連線初始化大小、最大連線數、等待時間、最小連線數 等一樣,Druid 資料來源同理可以進行設定;

配置 Druid web 監控 filterWebStatFilter): 這個過濾器的作用就是統計 web 應用請求中所有的資料庫資訊,比如 發出的 sql 語句,sql 執行的時間、請求次數、請求的 url 地址、以及seesion 監控、資料庫表的訪問次數 等等。

配置 Druid 後臺管理 ServletStatViewServlet): Druid 資料來源具有監控的功能,並提供了一個 web 介面方便使用者檢視,類似安裝 路由器 時,人家也提供了一個預設的 web 頁面;需要設定 Druid 的後臺管理頁面的屬性,比如 登入賬號、密碼 等;

注意:

Druid Spring Boot Starter 配置屬性的名稱完全遵照 Druid,可以通過 Spring Boot 配置檔案來配置Druid資料庫連線池和監控,如果沒有配置則使用預設值。

application.ymlserver:

    port: 7000
spring:
  datasource:
    name: druidDataSource
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/qx?useUnicode=true&zeroDateBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8
    username: root
    password: root
    platform: mysql
    druid:
      #最大連線數
      max-active: 100
      #初始化大小
      initial-size: 1
      #最小連線數
      min-idle: 1
      #獲取連線等待超時時間
      max-wait: 60000
      #間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒
      time-between-eviction-runs-millis: 60000
      #一個連線在連線池中最小的生存時間,單位是毫秒
      min-evictable-idle-time-millis: 300000
      max-evictable-idle-time-millis: 9000000
      #用來測試連線是否可用的SQL語句預設值每種資料庫都不相同
      validation-query: select 'x'
        # 應用向連線池申請連線,並且testOnBorrow為false時,連線池將會判斷連線是否處於空閒狀態,如果是,則驗證這條連線是否可用
      testWhileIdle: true
        # 如果為true,預設是false,應用向連線池申請連線時,連線池會判斷這條連線是否是可用的
      testOnBorrow: false
        # 如果為true(預設false),當應用使用完連線,連線池回收連線的時候會判斷該連線是否還可用
      testOnReturn: false
        # 是否快取preparedStatement,也就是PSCache。PSCache對支援遊標的資料庫效能提升巨大,比如說oracle
      poolPreparedStatements: true
        # 要啟用PSCache,必須配置大於0,當大於0時, poolPreparedStatements自動觸發修改為true,
        # 在Druid中,不會存在Oracle下PSCache佔用記憶體過多的問題,
        # 可以把這個數值配置大一些,比如說100
      maxOpenPreparedStatements: 20
        # 連線池中的minIdle數量以內的連線,空閒時間超過minEvictableIdleTimeMillis,則會執行keepAlive操作
      keepAlive: true
        # Spring 監控,利用aop 對指定介面的執行時間,jdbc數進行記錄
      aop-patterns: "com.springboot.template.dao.*"
        ########### 啟用內建過濾器(第一個 stat必須,否則監控不到SQL)##########
      filters: stat,wall,log4j2
          # 自己配置監控統計攔截的filter
      filter:
            # 開啟druiddatasource的狀態監控
        stat:
           enabled: true
           db-type: mysql
              # 開啟慢sql監控,超過2s 就認為是慢sql,記錄到日誌中
           log-slow-sql: true
           slow-sql-millis: 2000
            # 日誌監控,使用slf4j 進行日誌輸出
        slf4j:
            enabled: true
            statement-log-error-enabled: true
            statement-create-after-log-enabled: false
            statement-close-after-log-enabled: false
            result-set-open-after-log-enabled: false
            result-set-close-after-log-enabled: false
      ########## 配置WebStatFilter,用於採集web關聯監控的資料 ##########
      web-stat-filter:
        enabled: true                   # 啟動 StatFilter
        url-pattern: /*                 # 過濾所有url
        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" # 排除一些不必要的url
        session-stat-enable: true       # 開啟session統計功能
        session-stat-max-count: 1000    # session的最大個數,預設100
      ########## 配置StatViewServlet(監控頁面),用於展示Druid的統計資訊 ##########
      stat-view-servlet:
        enabled: true                   # 啟用StatViewServlet
        url-pattern: /druid/*           # 訪問內建監控頁面的路徑,內建監控頁面的首頁是/druid/index.html
        reset-enable: false              # 不允許清空統計資料,重新計算
        login-username: root            # 配置監控頁面訪問密碼
        login-password: 123
        allow: 127.0.0.1           # 允許訪問的地址,如果allow沒有配置或者為空,則允許所有訪問
  deny:                                         # 拒絕訪問的地址,deny優先於allow,如果在deny列表中,就算在allow列表中,也會被拒絕
 

上述配置檔案的引數可以在 com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties 和 org.springframework.boot.autoconfigure.jdbc.DataSourceProperties中找到;

3.1 如何配置 Filter

可以通過 spring.datasource.druid.filters=stat,wall,log4j ...的方式來啟用相應的內建Filter,不過這些Filter都是預設配置。如果預設配置不能滿足需求,可以放棄這種方式,通過配置檔案來配置Filter,下面是例子。

# 配置StatFilter
spring.datasource.druid.filter.stat.enabled=true
spring.datasource.druid.filter.stat.db-type=h2
spring.datasource.druid.filter.stat.log-slow-sql=true
spring.datasource.druid.filter.stat.slow-sql-millis=2000

# 配置WallFilter
spring.datasource.druid.filter.wall.enabled=true
spring.datasource.druid.filter.wall.db-type=h2
spring.datasource.druid.filter.wall.config.delete-allow=false
spring.datasource.druid.filter.wall.config.drop-table-allow=false

目前為以下 Filter 提供了配置支援,根據(spring.datasource.druid.filter.*)進行配置。

StatFilter

WallFilter

ConfigFilter

EncodingConvertFilter

Slf4jLogFilter

Log4jFilter

Log4j2Filter

CommonsLogFilter

不想使用內建的 Filters,要想使自定義 Filter 配置生效需要將對應 Filter enabled 設定為 true Druid Spring Boot Starter 預設禁用 StatFilter,可以將其 enabled 設定為 true 來啟用它。

4 監控頁面

1)啟動專案後,訪問/druid/login.html來到登入頁面,輸入使用者名稱密碼登入

 

 

(2)資料來源頁面 是當前DataSource配置的基本資訊,上述配置的Filter可以在裡面找到,如果沒有配置Filter(一些資訊會無法統計,例如“SQL監控”,會無法獲取JDBC相關的SQL執行資訊)

3SQL監控頁面,統計了所有SQL語句的執行情況

4URL監控頁面,統計了所有Controller介面的訪問以及執行情況

 

 5Spring 監控頁面,利用aop 對指定介面的執行時間,jdbc數進行記錄

 

 6SQL防火牆頁面

druid提供了黑白名單的訪問,可以清楚的看到sql防護情況。

7Session監控頁面

可以看到當前的session狀況,建立時間、最後活躍時間、請求次數、請求時間等詳細引數。

8JSONAPI 頁面

通過api的形式訪問Druid的監控介面,api介面返回Json形式資料。

5 sql監控

配置 Druid web 監控 filter(WebStatFilter)這個過濾器,作用就是統計 web 應用請求中所有的資料庫資訊,比如 發出的 sql 語句,sql 執行的時間、請求次數、請求的 url 地址、以及seesion 監控、資料庫表的訪問次數 等等。

spring:
  datasource:
    druid:
      ########## 配置WebStatFilter,用於採集web關聯監控的資料 ##########
      web-stat-filter:
        enabled: true                   # 啟動 StatFilter
        url-pattern: /*                 # 過濾所有url
        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" # 排除一些不必要的url
        session-stat-enable: true       # 開啟session統計功能
        session-stat-max-count: 1000    # session的最大個數,預設100

6 慢sql記錄

有時候,系統中有些SQL執行很慢,我們希望使用日誌記錄下來,可以開啟Druid的慢SQL記錄功能

spring:
  datasource:
    druid:
      filter:
        stat:
          enabled: true         # 開啟DruidDataSource狀態監控
          db-type: mysql        # 資料庫的型別
          log-slow-sql: true    # 開啟慢SQL記錄功能
          slow-sql-millis: 2000 # 預設3000毫秒,這裡超過2s,就是慢,記錄到日誌

 

啟動後,如果遇到執行慢的SQL,便會輸出到日誌中。

 

7 spring 監控

訪問之後spring監控預設是沒有資料的;

這需要匯入SprngBootAOPStarter

<!--SpringBoot 的aop 模組-->

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-aop</artifactId>

</dependency>

需要在 application.yml 配置:

Spring監控AOP切入點,如com.springboot.template.dao.*,配置多個英文逗號分隔

spring.datasource.druid.aop-patterns="com.springboot.template.dao.*"

8 Ad(廣告)

訪問監控頁面的時候,你可能會在頁面底部(footer)看到阿里巴巴的廣告

原因:引入的druidjar包中的common.js(裡面有一段js程式碼是給頁面的footer追加廣告的)

如果想去掉,有兩種方式:

(1) 直接手動註釋這段程式碼

如果是使用Maven,直接到本地倉庫中,查詢這個jar

要註釋的程式碼:

// this.buildFooter();

common.js的位置:

com/alibaba/druid/1.1.23/druid-1.1.23.jar!/support/http/resources/js/common.js

(2) 使用過濾器過濾

註冊一個過濾器,過濾common.js的請求,使用正則表示式替換相關的廣告內容

@Configuration

@ConditionalOnWebApplication

@AutoConfigureAfter(DruidDataSourceAutoConfigure.class)

@ConditionalOnProperty(name = "spring.datasource.druid.stat-view-servlet.enabled",

havingValue = "true", matchIfMissing = true)

public class RemoveDruidAdConfig {

 

    /**

    * 方法名: removeDruidAdFilterRegistrationBean

    * 方法描述 除去頁面底部的廣告

    * @param properties com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties

    * @return org.springframework.boot.web.servlet.FilterRegistrationBean

    */

    @Bean

    public FilterRegistrationBean removeDruidAdFilterRegistrationBean(DruidStatProperties properties) {

 

        // 獲取web監控頁面的引數

        DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();

        // 提取common.js的配置路徑

        String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";

        String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");

 

        final String filePath = "support/http/resources/js/common.js";

 

        //建立filter進行過濾

        Filter filter = new Filter() {

            @Override

            public void init(FilterConfig filterConfig) throws ServletException {}

 

            @Override

            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

                chain.doFilter(request, response);

                // 重置緩衝區,響應頭不會被重置

                response.resetBuffer();

                // 獲取common.js

                String text = Utils.readFromResource(filePath);

                // 正則替換banner, 除去底部的廣告資訊

                text = text.replaceAll("<a.*?banner\"></a><br/>", "");

                text = text.replaceAll("powered.*?shrek.wang</a>", "");

                response.getWriter().write(text);

            }

 

            @Override

            public void destroy() {}

        };

 

        FilterRegistrationBean registrationBean = new FilterRegistrationBean();

        registrationBean.setFilter(filter);

        registrationBean.addUrlPatterns(commonJsPattern);

        return registrationBean;

    }

}

 

兩種方式都可以,建議使用的是第一種,從根源解決

9 獲取 Druid 的監控資料

Druid 的監控資料可以在 開啟 StatFilter 後,通過 DruidStatManagerFacade 進行獲取;

DruidStatManagerFacade#getDataSourceStatDataList 該方法可以獲取所有資料來源的監控資料,

除此之外 DruidStatManagerFacade 還提供了一些其他方法,可以按需選擇使用。

@RestController

@RequestMapping(value = "/druid")

public class DruidStatController {

 

    @GetMapping("/stat")

    public Object druidStat(){

        // 獲取資料來源的監控資料

        return DruidStatManagerFacade.getInstance().getDataSourceStatDataList();

    }

}