版本:
-
Spring Boot 2.1.5.RELEASE
-
maven 3.2.5
-
jdk1.8
1.我選用的日誌框架:
- 日誌門面(抽象層): SLF4J
- 日誌實現: Logback
Spring Boot: 底層是Spring框架,Spring框架預設是JCL;
而Spring Boot選用 SLF4j和Logback
2. SLF4j使用
1) 如何在系統中使用SLF4j
開發的時候,日誌記錄方法的呼叫,不用改直接呼叫日誌的實現類,而是呼叫日誌抽象層裡的方法;
- 匯入slf4j的jar和 logback的實現jar
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.info("Hello World");
}
}
複製程式碼
SLF4j與其他日誌框架結合示意圖:
2) 遺留問題
雖然我使用的是(slf4j & logback),但是其他的比如Spring框架用的commons-logging
日誌框架, Hibernate用的是jboss-logging
日誌框架,等等,太亂了了,所以我們要 統一日誌記錄,即使別的框架也要和我一起統一使用slf4j進行輸出;
官方給出的示意圖:
邏輯:
- 1.將系統其他的日誌框架排除;
- 2.用中間包來替換原有的日誌框架(紅色框起來的就是中間包);
- 3.匯入slf4j其他的實現
3. Spring Boot日誌關係
其實是這個依賴的這個包:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<version>2.1.5.RELEASE</version>
<scope>compile</scope>
</dependency>
複製程式碼
在 pom檔案下滑鼠右鍵點選:
SpringBoot所有依賴關係圖,我們只看logging相關的:
我用的是2.1.5版本的Spring Boot, 筆者在學習過程中發現我看的老師視訊裡跟我的版本不一樣,
這是那位老師的版本:
很明顯跟我不一樣,不過Spring肯定對自己的底層進行了升級;
確切的說不是升級,而是剔除掉了jcl框架的轉換,因為jcl框架最後更新日期是2014年,明顯已經過時
但是基本推理的出來,slf4j的官網圖確實是對SpringBoot1.x版本的示意,但是對我的2.x版本不符, 不過根據我的包名來看,他們的功能是差不多的,都是轉成slf4j;
小總結:
- 1.SpringBoot底層也是 slf4j+logback的方式j進行日誌記錄;
- 2.SpringBoot也把其他日誌都替換成了slf4j;
- 3.中間替換包;
中間替換包圖示:
4) 如果我們要引入其他的框架,一定要把這個框架預設日誌依賴移除掉!
Spring框架預設的日誌框架是: commons-logging;
但是Spring Boot引入spring核心jar包的時候去除了 日誌jar包;
Spring Boot能自動適配所有的日誌,而且底層使用 slf4j+logback的方式記錄日誌,引入其他框架的時候,只需要把這個框架依賴的日誌排除掉
4. 日誌使用
測試類:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootLoggingApplicationTests {
// 日誌記錄器記錄器
Logger logger = LoggerFactory.getLogger(getClass());
@Test
public void contextLoads() {
// 日誌的級別
// 由低到高 trace < debug < info < warn < error
logger.trace("這是trace日誌..");
logger.debug("這是debug除錯日誌..");
logger.info("這是info日誌..");
logger.warn("這是warn日誌...");
logger.error("這是error錯誤日誌");
}
}
複製程式碼
執行輸出結果:
2019-07-02 19:22:35.980 INFO 8404 --- [ main] c.c.s.SpringBootLoggingApplicationTests : 這是info日誌..
2019-07-02 19:22:35.981 WARN 8404 --- [ main] c.c.s.SpringBootLoggingApplicationTests : 這是warn日誌...
2019-07-02 19:22:35.981 ERROR 8404 --- [ main] c.c.s.SpringBootLoggingApplicationTests : 這是error錯誤日誌
複製程式碼
也就是說 SpringBoot預設的日誌級別是 info,所以只輸出了info 和 比info級別大的日誌;
開啟我的yml配置檔案:
logging:
level:
com.carson: trace
複製程式碼
意思是把我 com.carson下的所有包都設定為 trace 日誌級別
輸出結果:
2019-07-02 19:29:17.406 TRACE 7076 --- [ main] c.c.s.SpringBootLoggingApplicationTests : 這是trace日誌..
2019-07-02 19:29:17.407 DEBUG 7076 --- [ main] c.c.s.SpringBootLoggingApplicationTests : 這是debug除錯日誌..
2019-07-02 19:29:17.407 INFO 7076 --- [ main] c.c.s.SpringBootLoggingApplicationTests : 這是info日誌..
2019-07-02 19:29:17.408 WARN 7076 --- [ main] c.c.s.SpringBootLoggingApplicationTests : 這是warn日誌...
2019-07-02 19:29:17.408 ERROR 7076 --- [ main] c.c.s.SpringBootLoggingApplicationTests : 這是error錯誤日誌
複製程式碼
4.1 配置檔案詳解:
logging.level.com.carson= trace
# path: 只建立任意一個資料夾, SpringBoot會預設生成一個 spring.log 作為日誌檔案
logging.path= F:/spring/log
# file: 指定一個路徑和檔案把 日誌輸出到 指定檔案裡
logging.file= F:/springboot.log
# pattern.console: 控制檯輸出的日誌格式
logging.pattern.console= %d{yyyy‐MM‐dd} === [%thread] === %‐5level === %logger{50} ==== %msg%n
# pattern.file : 指定檔案中日誌的輸出格式
logging.pattern.file= %d{yyyy‐MM‐dd} === [%thread] === %‐5level === %logger{50} ==== %msg%n
複製程式碼
4.2 指定配置
日誌框架 | 檔案命名 |
---|---|
Logback | logback-spring.xml , logback-spring.groovy , logback.xml , or logback.groovy |
Log4j2 | log4j2-spring.xml or log4j2.xml |
JDK (Java Util Logging) | logging.properties |
以上來自SpringBoot的官方文件, 上面是他要求的命名,SpringBoot會讀取的
- logback-spring.xml :
<?xml version="1.0" encoding="UTF-8"?>
<!--
scan:當此屬性設定為true時,配置檔案如果發生改變,將會被重新載入,預設值為true。
scanPeriod:設定監測配置檔案是否有修改的時間間隔,如果沒有給出時間單位,預設單位是毫秒當scan為true時,此屬性生效。預設的時間間隔為1分鐘。
debug:當此屬性設定為true時,將列印出logback內部日誌資訊,實時檢視logback執行狀態。預設值為false。
-->
<configuration scan="false" scanPeriod="60 seconds" debug="false">
<!-- 定義日誌的根目錄 -->
<property name="LOG_HOME" value="/app/log" />
<!-- 定義日誌檔名稱 -->
<property name="appName" value="atguigu-springboot"></property>
<!-- ch.qos.logback.core.ConsoleAppender 表示控制檯輸出 -->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<!--
日誌輸出格式:
%d表示日期時間,
%thread表示執行緒名,
%-5level:級別從左顯示5個字元寬度
%logger{50} 表示logger名字最長50個字元,否則按照句點分割。
%msg:日誌訊息,
%n是換行符
-->
<layout class="ch.qos.logback.classic.PatternLayout">
<springProfile name="dev">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ----> [%thread] ---> %-5level %logger{50} - %msg%n</pattern>
</springProfile>
<springProfile name="!dev">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ==== [%thread] ==== %-5level %logger{50} - %msg%n</pattern>
</springProfile>
</layout>
</appender>
<!-- 滾動記錄檔案,先將日誌記錄到指定檔案,當符合某個條件時,將日誌記錄到其他檔案 -->
<appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 指定日誌檔案的名稱 -->
<file>${LOG_HOME}/${appName}.log</file>
<!--
當發生滾動時,決定 RollingFileAppender 的行為,涉及檔案移動和重新命名
TimeBasedRollingPolicy: 最常用的滾動策略,它根據時間來制定滾動策略,既負責滾動也負責出發滾動。
-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--
滾動時產生的檔案的存放位置及檔名稱 %d{yyyy-MM-dd}:按天進行日誌滾動
%i:當檔案大小超過maxFileSize時,按照i進行檔案滾動
-->
<fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
<!--
可選節點,控制保留的歸檔檔案的最大數量,超出數量就刪除舊檔案。假設設定每天滾動,
且maxHistory是365,則只儲存最近365天的檔案,刪除之前的舊檔案。注意,刪除舊檔案是,
那些為了歸檔而建立的目錄也會被刪除。
-->
<MaxHistory>365</MaxHistory>
<!--
當日志檔案超過maxFileSize指定的大小是,根據上面提到的%i進行日誌檔案滾動 注意此處配置SizeBasedTriggeringPolicy是無法實現按檔案大小進行滾動的,必須配置timeBasedFileNamingAndTriggeringPolicy
-->
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 日誌輸出格式: -->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%n</pattern>
</layout>
</appender>
<!--
logger主要用於存放日誌物件,也可以定義日誌型別、級別
name:表示匹配的logger型別字首,也就是包的前半部分
level:要記錄的日誌級別,包括 TRACE < DEBUG < INFO < WARN < ERROR
additivity:作用在於children-logger是否使用 rootLogger配置的appender進行輸出,
false:表示只用當前logger的appender-ref,true:
表示當前logger的appender-ref和rootLogger的appender-ref都有效
-->
<!-- hibernate logger -->
<logger name="com.atguigu" level="debug" />
<!-- Spring framework logger -->
<logger name="org.springframework" level="debug" additivity="false"></logger>
<!--
root與logger是父子關係,沒有特別定義則預設為root,任何一個類只會和一個logger對應,
要麼是定義的logger,要麼是root,判斷的關鍵在於找到這個logger,然後判斷這個logger的appender和level。
-->
<root level="info">
<appender-ref ref="stdout" />
<appender-ref ref="appLogAppender" />
</root>
</configuration>
複製程式碼
把上面配置複製一份,放到專案的 resources 裡面,或者自定義配置,命名規範的區別:
-
logback.xml: 直接被日誌框架識別了
-
但是如果你以 logback-spring.xml 命名(推薦): 日誌框架不直接載入日誌的配置項了,由SpringBoot解析日誌你就可以使用SpringBoot的一個高階功能
<springProfile name="prod">
<!-- 是不是 prod 環境 -->
</springProfile>
<springProfile name="dev | prod">
<!-- dev 和 prod 都會執行 -->
</springProfile>
<springProfile name="!dev">
<!-- 如果不是 dev環境 -->
</springProfile>
複製程式碼
也就是剛才的配置檔案裡的:
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<!--
日誌輸出格式:
%d表示日期時間,
%thread表示執行緒名,
%-5level:級別從左顯示5個字元寬度
%logger{50} 表示logger名字最長50個字元,否則按照句點分割。
%msg:日誌訊息,
%n是換行符
-->
<layout class="ch.qos.logback.classic.PatternLayout">
<springProfile name="dev">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ----> [%thread] ---> %-5level %logger{50} - %msg%n</pattern>
</springProfile>
<springProfile name="!dev">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ==== [%thread] ==== %-5level %logger{50} - %msg%n</pattern>
</springProfile>
</layout>
</appender>
複製程式碼
你可以在你的 yml或者properties裡配置一條:
spring.profiles.active= prod 複製程式碼
來設定執行環境
4.3 使用 log4j
其實SpringBoot官方為我們做了一些幫助:
Name | Description | Pom |
---|---|---|
spring-boot-starter-jetty |
Starter for using Jetty as the embedded servlet container. An alternative to spring-boot-starter-tomcat |
Pom |
spring-boot-starter-log4j2 |
Starter for using Log4j2 for logging. An alternative to spring-boot-starter-logging |
Pom |
spring-boot-starter-logging |
Starter for logging using Logback. Default logging starter | Pom |
spring-boot-starter-reactor-netty |
Starter for using Reactor Netty as the embedded reactive HTTP server. | Pom |
spring-boot-starter-tomcat |
Starter for using Tomcat as the embedded servlet container. Default servlet container starter used by spring-boot-starter-web |
Pom |
spring-boot-starter-undertow |
Starter for using Undertow as the embedded servlet container. An alternative to spring-boot-starter-tomcat |
Pom |
想使用哪個日誌框架就直接匯入哪個包就好了, 比如我想使用 log4j2 我先把預設的 spring-boot-starter-logging
排除掉 , 排除方法如下:
- 然後再pom檔案裡:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
複製程式碼
匯入log4j2的包;
- 然後在 resources 裡 建立一個 log4j的配置檔案,檔案命名就以剛才說的:
內容:
### set log levels ###
log4j.rootLogger = debug , stdout , D , E
### 輸出到控制檯 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %d{ABSOLUTE} ===== %5p %c{ 1 }:%L - %m%n
#### 輸出到日誌檔案 ###
#log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
#log4j.appender.D.File = logs/log.log
#log4j.appender.D.Append = true
#log4j.appender.D.Threshold = DEBUG ## 輸出DEBUG級別以上的日誌
#log4j.appender.D.layout = org.apache.log4j.PatternLayout
#log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
#
#### 儲存異常資訊到單獨檔案 ###
#log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
#log4j.appender.D.File = logs/error.log ## 異常日誌檔名
#log4j.appender.D.Append = true
#log4j.appender.D.Threshold = ERROR ## 只輸出ERROR級別以上的日誌!!!
#log4j.appender.D.layout = org.apache.log4j.PatternLayout
#log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
複製程式碼
也就是說,如果像引入其他日誌框架,只要把以前的框架排除,然後再引入新框架就ok了
個人部落格 : aaatao66.github.io/