druid 配置打印完整可執行的SQL

druid 是支持 打印完整可以執行SQL的,只是 druid 默認不會打印。這點我覺得做得不夠友好。這麼好用的功能,居然默認隱藏 ?

spring boot 配置

引入依賴
<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.4</version>
        </dependency>
		
		
配置文件配置

logging.level.druid.sql.Statement=debug
spring.datasource.druid.filter.slf4j.enabled=true
spring.datasource.druid.filter.slf4j.statementPrepareAfterLogEnabled=false
spring.datasource.druid.filter.slf4j.statementCreateAfterLogEnabled=false
spring.datasource.druid.filter.slf4j.statementExecuteQueryAfterLogEnabled=false
spring.datasource.druid.filter.slf4j.statementExecuteAfterLogEnabled=false
spring.datasource.druid.filter.slf4j.statementParameterSetLogEnabled=false

spring.datasource.druid.filter.slf4j.statementCloseAfterLogEnabled=false
spring.datasource.druid.filter.slf4j.statementExecuteBatchAfterLogEnabled=false
spring.datasource.druid.filter.slf4j.statementExecuteUpdateAfterLogEnabled=false
spring.datasource.druid.filter.slf4j.statementPrepareCallAfterLogEnabled=false
spring.datasource.druid.filter.slf4j.statementExecutableSqlLogEnable=true
spring.datasource.druid.filter.slf4j.statementLogEnabled=true



其實關鍵是 下面的兩個配置

spring.datasource.druid.filter.slf4j.statementExecutableSqlLogEnable=true
spring.datasource.druid.filter.slf4j.statementLogEnabled=true

其他也設置爲 false 是因爲 會 打印其他 SQL log 太多了。
參考 https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter

druid 自定義 配置

引入依賴

 <!-- druid數據庫連接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>${druid.version}</version>
        </dependency>

log2 文件配置

<!--記錄druid-sql的記錄-->
        <logger name="druid.sql.Statement" level="debug" additivity="false">
            <appender-ref ref="Console"/>       
        </logger>

配置類


package com.door.config;

import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.filter.logging.Log4j2Filter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.alibaba.druid.wall.WallConfig;
import com.alibaba.druid.wall.WallFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
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 org.springframework.context.annotation.Primary;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Cheng JiYe
 * @description:
 * @date 2020/9/9 16:51
 */
@Configuration
public class DruidConfiguration {

  private Logger logger = LoggerFactory.getLogger(DruidConfiguration.class);

  @Value("${spring.datasource.url}")
  private String dbUrl;

  @Value("${spring.datasource.username}")
  private String username;

  @Value("${spring.datasource.password}")
  private String password;

  @Value("${spring.datasource.driver-class-name}")
  private String driverClassName;

  @Value("${spring.datasource.initialSize}")
  private int initialSize;

  @Value("${spring.datasource.minIdle}")
  private int minIdle;

  @Value("${spring.datasource.maxActive}")
  private int maxActive;

  @Value("${spring.datasource.maxWait}")
  private int maxWait;

  @Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
  private int timeBetweenEvictionRunsMillis;

  @Value("${spring.datasource.minEvictableIdleTimeMillis}")
  private int minEvictableIdleTimeMillis;

  @Value("${spring.datasource.validationQuery}")
  private String validationQuery;

  @Value("${spring.datasource.testWhileIdle}")
  private boolean testWhileIdle;

  @Value("${spring.datasource.testOnBorrow}")
  private boolean testOnBorrow;

  @Value("${spring.datasource.testOnReturn}")
  private boolean testOnReturn;

  @Value("${spring.datasource.poolPreparedStatements}")
  private boolean poolPreparedStatements;

  @Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")
  private int maxPoolPreparedStatementPerConnectionSize;

  //  @Value("${spring.datasource.filters}")
  //private String filters;

  //  @Value("${spring.datasource.connectionProperties}")
  //private String connectionProperties;

  @Bean // 聲明其爲Bean實例
  @Primary // 在同樣的DataSource中,首先使用被標註的DataSource
  public DataSource dataSource() {
    DruidDataSource datasource = new DruidDataSource();

    datasource.setUrl(this.dbUrl);
    datasource.setUsername(this.username);
    datasource.setPassword(this.password);
    datasource.setDriverClassName(this.driverClassName);

    // configuration
    datasource.setInitialSize(this.initialSize);
    datasource.setMinIdle(this.minIdle);
    datasource.setMaxActive(this.maxActive);
    datasource.setMaxWait(this.maxWait);
    datasource.setTimeBetweenEvictionRunsMillis(this.timeBetweenEvictionRunsMillis);
    datasource.setMinEvictableIdleTimeMillis(this.minEvictableIdleTimeMillis);
    datasource.setValidationQuery(this.validationQuery);
    datasource.setTestWhileIdle(this.testWhileIdle);
    datasource.setTestOnBorrow(this.testOnBorrow);
    datasource.setTestOnReturn(this.testOnReturn);
    datasource.setPoolPreparedStatements(this.poolPreparedStatements);
    datasource.setMaxPoolPreparedStatementPerConnectionSize(
        this.maxPoolPreparedStatementPerConnectionSize);

    // 添加自定義的filter
    datasource.setProxyFilters(this.proxyFilters());

    //  可以通過一串內容來配置數據源屬性,這裏不需要了.不要用錯了
    //    datasource.setConnectionProperties(this.connectionProperties);

    // #druid recycle Druid的連接回收機制 . 別亂加,一般出問題的時候,調試用
    //    datasource.setRemoveAbandoned(true);// 超過時間是否回收
    //    datasource.setRemoveAbandonedTimeout(120); // 秒
    //    datasource.setLogAbandoned(true);

    // 連接時指定編碼,防止中文亂碼,與特殊字符和表情不能存入數據庫
    List<Object> initSql = new ArrayList<>();
    initSql.add("set names utf8mb4;");
    datasource.setConnectionInitSqls(initSql);

    return datasource;
  }

  private List<Filter> proxyFilters() {
    List<Filter> filters = new ArrayList<>(3);
    filters.add(this.logFilter());
    filters.add(this.statFilter());
    filters.add(this.wallFilter());

    return filters;
  }

  /**
   * http://localhost:8080/druid/login.html 註冊一個StatViewServlet
   *
   * @return
   */
  @Bean
  public ServletRegistrationBean DruidStatViewServle() {
    // org.springframework.boot.context.embedded.ServletRegistrationBean提供類的進行註冊.
    ServletRegistrationBean servletRegistrationBean =
        new ServletRegistrationBean(new StatViewServlet(), "/druid/*");

    // 添加初始化參數:initParams
    // 白名單:
    // servletRegistrationBean.addInitParameter("allow","127.0.0.1");
    // IP黑名單 (存在共同時,deny優先於allow) : 如果滿足deny的話提示:Sorry, you are not permitted to view this page.
    // servletRegistrationBean.addInitParameter("deny","192.168.1.73");
    // 登錄查看信息的賬號密碼.
    servletRegistrationBean.addInitParameter("loginUsername", "admin");
    servletRegistrationBean.addInitParameter("loginPassword", "123456Auth");
    // 是否能夠重置數據.
    servletRegistrationBean.addInitParameter("resetEnable", "false");
    return servletRegistrationBean;
  }

  /**
   * 註冊一個:filterRegistrationBean
   *
   * @return
   */
  @Bean
  public FilterRegistrationBean druidStatFilter() {

    FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());

    // 添加過濾規則.
    filterRegistrationBean.addUrlPatterns("/*");

    // 添加不需要忽略的格式信息.
    filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,");
    return filterRegistrationBean;
  }

  /**
   * 定義 log 過濾
   *
   * @return
   */
  private Log4j2Filter logFilter() {
    Log4j2Filter logFilter = new Log4j2Filter();
    logFilter.setStatementLogEnabled(true);

    // 不要創建後 log
    logFilter.setStatementCreateAfterLogEnabled(false);
    // 不要 關閉後 log
    logFilter.setStatementCloseAfterLogEnabled(false);
    // 不要參數 log
    logFilter.setStatementParameterClearLogEnable(false);
    logFilter.setStatementParameterSetLogEnabled(false);
    logFilter.setStatementPrepareAfterLogEnabled(false);
    logFilter.setStatementPrepareCallAfterLogEnabled(false);

    // 不要執行之後的log
    logFilter.setStatementExecuteAfterLogEnabled(false);
    logFilter.setStatementExecuteBatchAfterLogEnabled(false);
    logFilter.setStatementExecuteQueryAfterLogEnabled(false);
    logFilter.setStatementExecuteUpdateAfterLogEnabled(false);

    // 可以打印完整的SQL
    logFilter.setStatementExecutableSqlLogEnable(true);

    return logFilter;
  }

  /**
   * 自定義統計 SQL
   *
   * @return
   */
  private StatFilter statFilter() {
    StatFilter statFilter = new StatFilter();
    // 統計慢查詢
    statFilter.setSlowSqlMillis(5000);
    statFilter.setLogSlowSql(true);
    statFilter.setMergeSql(true);
    return statFilter;
  }

  /**
   * sql防火牆過濾器配置
   *
   * @return
   */
  private WallFilter wallFilter() {
    WallFilter wallFilter = new WallFilter();
    wallFilter.setConfig(this.wallConfig());
    wallFilter.setLogViolation(true); // 對被認爲是攻擊的SQL進行LOG.error輸出
    wallFilter.setThrowException(false); // 對被認爲是攻擊的SQL拋出SQLException
    return wallFilter;
  }

  /**
   * sql防火牆配置
   *
   * @return
   */
  private WallConfig wallConfig() {
    WallConfig wallConfig = new WallConfig();

    //    wallConfig.setDeleteAllow(false); // 不可以刪除全部

    return wallConfig;
  }
}


關閉 mybatis log 打印

以上 druid 配置好了之後,其實也就不需要 mybtis 配置打印 SQL了
也不需要 使用 啥 mybatis log plugin 等等 此類方式來獲取完整的可以執行SQL了


configuration:
    map-underscore-to-camel-case: true # 是否開啓自動駝峯命名規則(camel case)映射
    cache-enabled: false  #配置的緩存的全局開關
    #配置JdbcTypeForNull
    jdbc-type-for-null: 'null'
    lazy-loading-enabled: true  #延時加載的開關. 默認false
    # 不需要mybatis記錄  sql log 
    log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl

參考資料

https://www.bookstack.cn/read/Druid/4e582ac4d22e5709.md
https://www.bookstack.cn/read/Druid/f8a2f69d3df5ead2.md

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