以前在 日誌?聊一聊slf4j吧 這篇文章中聊了下slf4j
。本文也從實際的例子出發,針對logback
的日誌配置進行學習。java
logback 官網:https://logback.qos.ch/git
目前尚未看過日誌類框架的源碼,僅限於如何使用。因此就不說那些「空話」了。最直觀的認知是:github
logback
和log4j
是一我的寫的springboot
默認使用的日誌框架是logback
。logback-core
是其它模塊的基礎設施,其它模塊基於它構建,顯然,logback-core
提供了一些關鍵的通用機制。logback-classic
的地位和做用等同於 Log4J
,它也被認爲是 Log4J
的一個改進版,而且它實現了簡單日誌門面 SLF4J
;而 logback-access
主要做爲一個與 Servlet
容器交互的模塊,好比說tomcat
或者 jetty
,提供一些與 HTTP
訪問相關的功能。web
這部分主要來學習下logback配置文件的一些配置項。算法
先來看這張圖,這個結構就是整個logback.xml配置文件的結構。spring
對應來看下配置文件:<configuration scan="true" scanPeriod="60 seconds" debug="false">
<property name="glmapper-name" value="glmapper-demo" />
<contextName>${glmapper-name}</contextName>
<appender>
//xxxx
</appender>
<logger>
//xxxx
</logger>
<root>
//xxxx
</root>
</configuration>
複製代碼
ps:想使用spring擴展profile支持,要以logback-spring.xml命名,其餘如property須要改成springPropertysql
每一個logger
都關聯到logger
上下文,默認上下文名稱爲「default」
。但可使用contextName
標籤設置成其餘名字,用於區分不一樣應用程序的記錄數組
用來定義變量值的標籤,property
標籤有兩個屬性,name
和value
;其中name
的值是變量的名稱,value
的值時變量定義的值。經過property
定義的值會被插入到logger
上下文中。定義變量後,可使「${name}」來使用變量。如上面的xml
所示。tomcat
用來設置某一個包或者具體的某一個類的日誌打印級別以及指定appender
。springboot
根logger,也是一種logger,且只有一個level屬性
負責寫日誌的組件,下面會細說
filter實際上是appender裏面的子元素。它做爲過濾器存在,執行一個過濾器會有返回DENY,NEUTRAL,ACCEPT三個枚舉值中的一個。
首先來配置一個很是簡單的文件。這裏申請下,我使用的是 logback-spring.xml
。和 logback.xml
在properties
上有略微差異。其餘都同樣。
工程:springboot+web
先來看下項目目錄
properties中就是指定了日誌的打印級別和日誌的輸出位置:
#設置應用的日誌級別
logging.level.com.glmapper.spring.boot=INFO
#路徑
logging.path=./logs
複製代碼
<configuration>
<!-- 默認的控制檯日誌輸出,通常生產環境都是後臺啓動,這個沒太大做用 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d{HH:mm:ss.SSS} %-5level %logger{80} - %msg%n</Pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
複製代碼
private static final Logger LOGGER =
LoggerFactory.getLogger(HelloController.class);
@Autowired
private TestLogService testLogService;
@GetMapping("/hello")
public String hello(){
LOGGER.info("GLMAPPER-SERVICE:info");
LOGGER.error("GLMAPPER-SERVICE:error");
testLogService.printLogToSpecialPackage();
return "hello spring boot";
}
複製代碼
01:50:39.633 INFO com.glmapper.spring.boot.controller.HelloController
- GLMAPPER-SERVICE:info
01:50:39.633 ERROR com.glmapper.spring.boot.controller.HelloController
- GLMAPPER-SERVICE:error
複製代碼
上面的就是經過控制檯打印出來的,這個時候由於咱們沒有指定日誌文件的輸出,由於不會在工程目錄下生產logs
文件夾。
先來看下配置文件:
<configuration>
<!-- 屬性文件:在properties文件中找到對應的配置項 -->
<springProperty scope="context" name="logging.path" source="logging.path"/>
<springProperty scope="context" name="logging.level" source="logging.level.com.glmapper.spring.boot"/>
<!-- 默認的控制檯日誌輸出,通常生產環境都是後臺啓動,這個沒太大做用 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d{HH:mm:ss.SSS} %-5level %logger{80} - %msg%n</Pattern>
</encoder>
</appender>
<appender name="GLMAPPER-LOGGERONE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${logging.level}</level>
</filter>
<file>
${logging.path}/glmapper-spring-boot/glmapper-loggerone.log
</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-loggerone.log.%d{yyyy-MM-dd}</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<root level="info">
<appender-ref ref="GLMAPPER-LOGGERONE"/>
</root>
</configuration>
複製代碼
這裏咱們appender-ref
指定的appender
是GLMAPPER-LOGGERONE
,由於以前沒有名字爲GLMAPPER-LOGGERONE
的appender
,因此要增長一個name
爲GLMAPPER-LOGGERONE
的appender
。
注意上面這個配置,咱們是直接接將root
的appender-ref
直接指定到咱們的GLMAPPER-LOGGERONE
這個appender的。因此控制檯中將只會打印出bannar以後就啥也不打印了,全部的啓動信息都會被打印在日誌文件glmapper-loggerone.log
中。
可是實際上咱們不但願個人業務日誌中會包括這些啓動信息。因此這個時候咱們就須要經過logger
標籤來搞事情了。將上面的配置文件進行簡單修改:
<logger name="com.glmapper.spring.boot.controller" level="${logging.level}" additivity="false">
<appender-ref ref="GLMAPPER-LOGGERONE" />
</logger>
<root level="${logging.level}">
<appender-ref ref="STDOUT"/>
</root>
複製代碼
讓root
指向控制檯輸出;logger
負責打印包com.glmapper.spring.boot.controller
下的日誌。
仍是經過咱們的測試controller來打印日誌爲例,可是這裏不會在控制檯出現日誌信息了。指望的日誌文件在./logs/glmapper-spring-boot/glmapper-loggerone.log
。
上面兩種是一個基本的配置方式,經過上面兩個案例,咱們先來了解下logger/appender/root
之間的關係,而後再詳細的說下logger
和appender
的配置細節。
在最前面介紹中提到,root
是根logger
,因此他兩是一回事;只不過root
中不能有name
和additivity
屬性,是有一個level
。
appender
是一個日誌打印的組件,這裏組件裏面定義了打印過濾的條件、打印輸出方式、滾動策略、編碼方式、打印格式等等。可是它僅僅是一個打印組件,若是咱們不使用一個logger
或者root
的appender-ref
指定某個具體的appender
時,它就沒有什麼意義。
所以appender
讓咱們的應用知道怎麼打、打印到哪裏、打印成什麼樣;而logger
則是告訴應用哪些能夠這麼打。例如某個類下的日誌可使用這個appender
打印或者某個包下的日誌能夠這麼打印。
這裏以上面案例中的名爲GLMAPPER-LOGGERONE
的appender
說明:
<appender name="GLMAPPER-LOGGERONE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${logging.level}</level>
</filter>
<file>
${logging.path}/glmapper-spring-boot/glmapper-loggerone.log
</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-loggerone.log.%d{yyyy-MM-dd}</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
複製代碼
appender
有兩個屬性 name
和class
;name
指定appender
名稱,class
指定appender
的全限定名。上面聲明的是名爲GLMAPPER-LOGGERONE
,class
爲ch.qos.logback.core.rolling.RollingFileAppender
的一個appender
。
<append>true</append>
複製代碼
若是是 true
,日誌被追加到文件結尾,若是是false
,清空現存文件,默認是true
。
在簡介中提到了filter
;做用就是上面說的。能夠爲appender
添加一個或多個過濾器,能夠用任意條件對日誌進行過濾。appender
有多個過濾器時,按照配置順序執行。
臨界值過濾器,過濾掉低於指定臨界值的日誌。當日志級別等於或高於臨界值時,過濾器返回NEUTRAL
;當日志級別低於臨界值時,日誌會被拒絕。
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
複製代碼
級別過濾器,根據日誌級別進行過濾。若是日誌級別等於配置級別,過濾器會根據onMath
(用於配置符合過濾條件的操做) 和 onMismatch
(用於配置不符合過濾條件的操做)接收或拒絕日誌。
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
複製代碼
關於NEUTRAL
、ACCEPT
、DENY
見上文簡介中關於filter
的介紹。
file
標籤用於指定被寫入的文件名,能夠是相對目錄,也能夠是絕對目錄,若是上級目錄不存在會自動建立,沒有默認值。
<file>
${logging.path}/glmapper-spring-boot/glmapper-loggerone.log
</file>
複製代碼
這個表示當前appender將會將日誌寫入到${logging.path}/glmapper-spring-boot/glmapper-loggerone.log
這個目錄下。
這個子標籤用來描述滾動策略的。這個只有appender
的class
是RollingFileAppender
時才須要配置。這個也會涉及文件的移動和重命名(a.log->a.log.2018.07.22)。
最經常使用的滾動策略,它根據時間來制定滾動策略,既負責滾動也負責出發滾動。這個下面又包括了兩個屬性:
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日誌文件輸出的文件名:按天回滾 daily -->
<FileNamePattern>
${logging.path}/glmapper-spring-boot/glmapper-loggerone.log.%d{yyyy-MM-dd}
</FileNamePattern>
<!--日誌文件保留天數-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
複製代碼
上面的這段配置代表天天生成一個日誌文件,保存30天的日誌文件
根據固定窗口算法重命名文件的滾動策略。
對記錄事件進行格式化。它幹了兩件事:
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}
- %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
複製代碼
目前encoder
只有PatternLayoutEncoder
一種類型。
<!-- 錯誤日誌 appender : 按照天天生成日誌文件 -->
<appender name="ERROR-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<!-- 過濾器,只記錄 error 級別的日誌 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>error</level>
</filter>
<!-- 日誌名稱 -->
<file>${logging.path}/glmapper-spring-boot/glmapper-error.log</file>
<!-- 天天生成一個日誌文件,保存30天的日誌文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日誌文件輸出的文件名:按天回滾 daily -->
<FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-error.log.%d{yyyy-MM-dd}</FileNamePattern>
<!--日誌文件保留天數-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日誌消息,%n是換行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<!-- 編碼 -->
<charset>UTF-8</charset>
</encoder>
</appender>
複製代碼
<!-- 默認的控制檯日誌輸出,通常生產環境都是後臺啓動,這個沒太大做用 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d{HH:mm:ss.SSS} %-5level %logger{80} - %msg%n</Pattern>
</encoder>
</appender>
複製代碼
<logger name="com.glmapper.spring.boot.controller" level="${logging.level}" additivity="false">
<appender-ref ref="GLMAPPER-LOGGERONE" />
</logger>
複製代碼
上面的這個配置文件描述的是:com.glmapper.spring.boot.controller
這個包下的${logging.level}
級別的日誌將會使用GLMAPPER-LOGGERONE
來打印。logger
有三個屬性和一個子標籤:
logger
約束的某一個包或者具體的某一個類。TRACE
, DEBUG
, INFO
, WARN
, ERROR
, ALL
和 OFF
),還有一個值INHERITED
或者同義詞NULL
,表明強制執行上級的級別。若是沒有設置此屬性,那麼當前logger
將會繼承上級的級別。logger
傳遞打印信息。默認是true
。appender-ref
則是用來指定具體appender
的。
在前面的例子中咱們有三種appender,一個是指定包約束的,一個是控制error級別的,一個是控制檯的。而後這小節咱們就來實現下不一樣日誌打印到不一樣的log文件中。
這個例子裏咱們將com.glmapper.spring.boot.controller
中的日誌輸出到glmapper-controller.log
;將com.glmapper.spring.boot.service
中的日誌輸出到glmapper-service.log
。
<!--打印日誌到glmapper-service.log的appender-->
<appender name="GLMAPPER-SERVICE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${logging.level}</level>
</filter>
<file>
${logging.path}/glmapper-spring-boot/glmapper-service.log
</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-service.log.%d{yyyy-MM-dd}</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!--打印日誌到glmapper-controller.log的appender-->
<appender name="GLMAPPER-CONTROLLER" class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${logging.level}</level>
</filter>
<file>
${logging.path}/glmapper-spring-boot/glmapper-controller.log
</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-controller.log.%d{yyyy-MM-dd}</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!--此logger約束將.controller包下的日誌輸出到GLMAPPER-CONTROLLER,錯誤日誌輸出到GERROR-APPENDE;GERROR-APPENDE見上面-->
<logger name="com.glmapper.spring.boot.controller" level="${logging.level}" additivity="false">
<appender-ref ref="GLMAPPER-CONTROLLER" />
<appender-ref ref="GERROR-APPENDER" />
</logger>
<!--此logger約束將.service包下的日誌輸出到GLMAPPER-SERVICE,錯誤日誌輸出到GERROR-APPENDE;GERROR-APPENDE見上面-->
<logger name="com.glmapper.spring.boot.service" level="${logging.level}" additivity="false">
<appender-ref ref="GLMAPPER-SERVICE" />
<appender-ref ref="GERROR-APPENDER" />
</logger>
複製代碼
來看運行結果
一、glmaper-controller
二、glmapper-service
三、glmapper-error
知足咱們的預期,可是這裏有個小問題。在info
日誌裏出現了error
,固然這是正常的。假如咱們不想在info
裏面出現error
怎麼辦呢?很簡單,咱們以APPENDER-SERVICE
爲例,將filter
過濾器進行修改:
將下面的:
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${logging.level}</level>
</filter>
複製代碼
修改成:
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<!-- 若是命中就禁止這條日誌 -->
<onMatch>DENY</onMatch>
<!-- 若是沒有命中就使用這條規則 -->
<onMismatch>ACCEPT</onMismatch>
</filter>
複製代碼
這裏同時要注意的是,在logger
中level
須要設置爲info
級別。
這個其實也是和上面那個差不過,只不過粒度更細一點,通常狀況下好比說咱們有個定時任務類須要單獨來記錄其日誌信息,這樣咱們就能夠考慮使用基於類維度來約束打印。
<!--特殊功能單獨appender 例如調度類的日誌-->
<appender name="SCHEDULERTASKLOCK-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${logging.level}</level>
</filter>
<file>${logging.path}/glmapper-spring-boot/scheduler-task-lock.log</file>
<!-- 天天生成一個日誌文件,保存30天的日誌文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日誌文件輸出的文件名:按天回滾 daily -->
<FileNamePattern>${logging.path}/glmapper-spring-boot/scheduler-task-lock.log.%d{yyyy-MM-dd}</FileNamePattern>
<!--日誌文件保留天數-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日誌消息,%n是換行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<!-- 編碼 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--這裏指定到了具體的某一個類-->
<logger name="com.glmapper.spring.boot.task.TestLogTask" level="${logging.level}" additivity="true">
<appender-ref ref="SCHEDULERTASKLOCK-APPENDER" />
<appender-ref ref="ERROR-APPENDER" />
</logger>
複製代碼
最終TestLogTask
中的日誌將會被打印到這個本身獨立的log文件中。以下所示:
logger
的name
除了類、包等約束以外,固然還能夠這樣來玩。。。
在進行案例以前,這裏先把前面案例中logger
聲明的代碼貼一下,以做對比,以TestLogTask
類中的日誌爲例:
private static final Logger LOGGER =
LoggerFactory.getLogger(TestLogTask.class);
複製代碼
在getLogger
中咱們是將當前對象的class
做爲參數的,這個是爲了打印時獲取其全限定名的(見下面3-)。
1-2018-07-21 11:15:42.003 [pool-1-thread-1]
2-INFO
3-com.glmapper.spring.boot.task.TestLogTask -
4-com.glmapper.spring.boot.task:info
複製代碼
咱們一樣是service
包下定義一個類TestLogNameServiceImpl
package com.glmapper.spring.boot.service;
@Service("testLogNameService")
public class TestLogNameServiceImpl implements TestLogNameService {
private static final Logger LOGGER =
LoggerFactory.getLogger("GLMAPPER-TEST-LOG");
@Override
public void print() {
LOGGER.info("GLMAPPER-TEST-LOG:this is special logger-----info");
LOGGER.error("GLMAPPER-TEST-LOG:this is special logger-------error");
}
}
複製代碼
<appender name="ROOT-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${logging.level}</level>
</filter>
<file>${logging.path}/glmapper-spring-boot/glmapper-test.log</file>
<!-- 天天生成一個日誌文件,保存30天的日誌文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日誌文件輸出的文件名:按天回滾 daily -->
<FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-test.log.%d{yyyy-MM-dd}
</FileNamePattern>
<!--日誌文件保留天數-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日誌消息,%n是換行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<!-- 編碼 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--這裏的name和業務類中的getLogger中的字符串是同樣的-->
<logger name="GLMAPPER-TEST-LOG" level="${logging.level}" additivity="true">
<appender-ref ref="ROOT-APPENDER" />
<appender-ref ref="ERROR-APPENDER" />
</logger>
複製代碼
咱們這個預期的是TestLogNameServiceImpl
中的日誌不打印到glmapper-service.log
中,而是打印到glmapper-test.log
中。
一、glmapper-test.log
二、glmapper-service.log
知足咱們的預期。
這個仍是比較坑的。爲何。看下這個:
<settings>
<setting name="logImpl" value="slf4j" />
</settings>
複製代碼
在mybatis-configration.xml
中,咱們經過這樣一個配置項來關聯到具體的日誌組件。可是logImpl
的實現中是沒有logback
的。那麼怎麼辦呢?這裏只能經過slf4j
的方式橋接到logback
。
而後在咱們的logback-spring.xml中進行以下配置:
<!-- 將sql語句輸出到具體的日誌文件中 -->
<logger name="com.alipay.sofa.cloudplatform.common.dao" level="${logging.sql.level}" additivity="false">
<appender-ref ref="SQL-APPENDER"/>
</logger>
複製代碼
這裏有幾個點須要注意的。首先是${logging.sql.level}
這個必須是debug,這個是由mybatis自己實現決定的。而這裏的name
設定的com.alipay.sofa.cloudplatform.common.dao
值就是咱們dao接口的包路徑。
網上看了一個比較典型的案例,這種方式只能輸出到控制檯,並不能將文件輸出到日誌文件;它是根據內部的一個實現機制偷了個懶。mybatis用logback日誌不顯示sql的解決辦法。
本篇博客主要是整理最近工做中的一些日誌配置積累,將每一個細節進行總結一下,以做備忘。若是有時間的話會考慮看一個日誌框架的源碼。其實我以爲仍是頗有必要的,日誌組件畢竟是須要進行日誌文件落盤的,這個會涉及到許多的性能問題、緩衝區問題、隊列問題、固然還有一些鎖的問題、同步打印或者異步打印等問題。有興趣的小夥伴能夠看看,而後分享給咱們。
後面準備寫一寫螞蟻金服SOFABoot和SpringBoot的一些文章,若是有興趣能夠先看一波。