前言
對于一個web項目來說,日志框架是必不可少的,日志的記錄可以幫助我們在開發以及維護過程中快速的定位錯誤。相信很多人聽說過slf4j,log4j,logback,JDK Logging等跟日志框架有關的詞語,所以這里也簡單介紹下他們之間的關系。
關系
首先slf4j可以理解為規則的制定者,是一個抽象層,定義了日志相關的接口。log4j,logback,JDK Logging都是slf4j的實現層,只是出處不同,當然使用起來也就各有千秋,這里放一張網上的圖更明了的解釋了他們之間的關系:
為什么使用slf4j+logback
我使用這個框架是因為一開始接觸的時候就用的這個,后來在網上了解到slf4j+logback也確實當下最流行的日志框架,并且自己用著也確實很順手,也就一直用了下來。
在Spring boot中使用slf4j+logback日志框架
添加配置文件
在Spring boot使用是非常方便的,不需要我們有什么額外的配置,因為Spring boot默認支持的就是slf4j+logback的日志框架,想要靈活的定制日志策略,只需要我們在src/main/resources下添加配置文件即可,只是默認情況下配置文件的命名需要符合以下規則:
- logback.xml
- logback-spring.xml
其中logback-spring.xml是官方推薦的,并且只有使用這種命名規則,才可以配置不同環境使用不同的日志策略這一功能。
配置文件詳解
首先介紹配置文件的關鍵節點:
框架介紹
<configuration>:根節點,有三個屬性:
- scan:當配置文件發生修改時,是否重新加載該配置文件,兩個可選值true or false,默認為true。
- scanPeriod:檢測配置文件是否修改的時間周期,當沒有給出時間單位時默認單位為毫秒,默認值為一分鐘,需要注意的是這個屬性只有在scan屬性值為true時才生效。
- debug:是否打印loback內部日志信息,兩個可選值true or false,默認為false。
根節點<configuration>有三個重要的子節點,正是這三個子節點的不同組合構成配置文件的基本框架,使得logback.xml配置文件具備很強的靈活性:
- <Appender>:定義日志策略的節點,一個日志策略對應一個<appender>,一個配置文件中可以有零個或者多該節點,但一個配置文件如果沒有定義至少一個<appender>,雖然程序不會報錯,但就不會有任何的日志信息輸出,也失去了意義,該節點有兩個必要的屬性:
- name:指定該節點的名稱,方便之后的引用。
- class:指定該節點的全限定名,所謂的全限定名就是定義該節點為哪種類型的日志策略,比如我們需要將日志輸出到控制臺,就需要指定class的值為ch.qos.logback.core.ConsoleAppender;需要將日志輸出到文件,則class的值為ch.qos.logback.core.FileAppender等。
- <logger>:用來設置某個包或者類的日志打印級別,并且可以引用<appender>綁定日志策略,有三個屬性:
- name:用來指定受此<logger>約束的包或者類。
- level:可選屬性,用來指定日志的輸出級別,如果不設置,那么當前<logger>會繼承上級的級別。
- additivity:是否向上級傳遞輸出信息,兩個可選值true or false,默認為true。
在該節點內可以添加子節點<appender-ref>,該節點有一個必填的屬性ref,值為我們定義的<appender>節點的name屬性的值。
- <root>:根<logger>一個特殊的<logger>,即默認name屬性為root的<logger>,因為是根<logger>,所以不存在向上傳遞一說,故沒有additivity屬性,所以該節點只有一個level屬性。
介紹了根節點的三個主要的子節點,下面再介紹兩個不那么重要但可以了解的子節點:
- <contextName>:設置上下文名稱,每個<logger>都關聯到<logger>上下文,默認上下文名稱為default,但可以使用設置成其他名字,用于區分不同應用程序的記錄,一旦設置,不能修改,可以通過 %contextName 來打印日志上下文名稱,一般來說我們不用這個屬性,可有可無。
- <property>:用來定義變量的節點,定義變量后,可以使${}來使用變量,兩個屬性,當定義了多個<appender>的時候還是很有用的:
- name:變量名
- value:變量值
好了,介紹了上邊的節點我們就已經可以搭建一個簡單的配置文件框架了,如下:
<?xml version="1.0" encoding="UTF-8"?>
<!-- 一般根節點不需要寫屬性了,使用默認的就好 -->
<configuration>
<contextName>demo</contextName>
<!-- 該變量代表日志文件存放的目錄名 -->
<property name="log.dir" value="logs"/>
<!-- 該變量代表日志文件名 -->
<property name="log.appname" value="eran"/>
<!--定義一個將日志輸出到控制臺的appender,名稱為STDOUT -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- 內容待定 -->
</appender>
<!--定義一個將日志輸出到文件的appender,名稱為FILE_LOG -->
<appender name="FILE_LOG" class="ch.qos.logback.core.FileAppender">
<!-- 內容待定 -->
</appender>
<!-- 指定com.demo包下的日志打印級別為INFO,但是由于沒有引用appender,所以該logger不會打印日志信息,日志信息向上傳遞 -->
<logger name="com.demo" level="INFO"/>
<!-- 指定最基礎的日志輸出級別為DEBUG,并且綁定了名為STDOUT的appender,表示將日志信息輸出到控制臺 -->
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
上面搭建了框架,定義了一個輸出到控制臺的ConsoleAppender以及輸出到文件的FileAppender,下面來細說這兩個最基本的日志策略,并介紹最常用的滾動文件策略的RollingFileAppender,這三種類型的日志策略足夠我們的日常使用。
輸出到控制臺的ConsoleAppender的介紹:
先給出一個demo:
<!--定義一個將日志輸出到控制臺的appender,名稱為STDOUT -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[Eran]%date [%thread %line] %level >> %msg >> %logger{10}%n</pattern>
</encoder>
</appender>
ConsoleAppender的功能是將日志輸出到控制臺,有一個<encoder>節點用來指定日志的輸出格式,在較早以前的版本還有一個<layout>節點也是相同的作用,但是官方推薦使用encoder節點,所以這里我們介紹encoder節點即可。
<encoder>節點介紹
該節點主要做兩件事:
- 把日志信息轉換成字節數組
- 將字節數組寫到輸出流
該節點的子節點<pattern>作用就是定義日志的格式,即定義一條日志信息包含哪些內容,例如當前時間,在代碼中的行數線程名等。需要哪些內容由我們自己定義,按照%+轉換符的格式定義,下面列出常用的轉換符:
- %date{}:輸出時間,可以在花括號內指定時間格式,例如-%data{yyyy-MM-dd HH:mm:ss},格式語法和JAVA.text.SimpleDateFormat一樣,可以簡寫為%d{}的形式,使用默認的格式時可以省略{}。
- %logger{}:日志的logger名稱,可以簡寫為%c{},%lo{}的形式,使用默認的參數時可以省略{},可以定義一個整形的參數來控制輸出名稱的長度,有下面三種情況:
- 不輸入表示輸出完整的<logger>名稱
- 輸入0表示只輸出<logger>最右邊點號之后的字符串
- 輸入其他數字表示輸出小數點最后邊點號之前的字符數量
- %thread:產生日志的線程名,可簡寫為%t
- %line:當前打印日志的語句在程序中的行號,可簡寫為%L
- %level:日志級別,可簡寫為%le,%p
- %message:程序員定義的日志打印內容,可簡寫為%msg,%m
- %n:換行,即一條日志信息占一行
介紹了常用的轉換符,我們再看看上邊的例子中我們定義的格式:
<pattern>[Eran]%date [%thread %line] %level >> %msg >> %logger{10}%n</pattern>
日志的格式一目了然,可以看出我們在最前面加了[eran]的字符串,這里是我個人的使用習慣,一般將項目名統一展現在日志前邊,而且在每個轉換符之間加了空格,這更便于我們查看日志,并且使用了>>字符串來將%msg分割開來,更便于我們找到日志信息中我們關注的內容,這些東西大家可以自己按照自己的喜好來。
輸出到文件的FileAppender
先給出一個demo:
<!--定義一個將日志輸出到文件的appender,名稱為FILE_LOG -->
<appender name="FILE_LOG" class="ch.qos.logback.core.FileAppender">
<file>D:/test.log</file>
<append>true</append>
<encoder>
<pattern>[Eran]%date [%thread %line] %level >> %msg >> %logger{10}%n</pattern>
</encoder>
</appender>
FileAppender表示將日志輸出到文件,常用幾個子節點:
- <file>:定義文件名和路徑,可以是相對路徑 , 也可以是絕對路徑 , 如果路徑不存在則會自動創建
- <append>:兩個值true和false,默認為true,表示每次日志輸出到文件走追加在原來文件的結尾,false則表示清空現存文件
- <encoder>:和ConsoleAppender一樣
顯而易見,樣例中我們的日志策略表示,每次將日志信息追加到D:/test.log的文件中。
滾動文件策略RollingFileAppender介紹
按時間滾動TimeBasedRollingPolicy
demo如下:
<appender name="ROL-FILE-LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--滾動策略,按照時間滾動 TimeBasedRollingPolicy-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>D:/logs/test.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 只保留近七天的日志 -->
<maxHistory>7</maxHistory>
<!-- 用來指定日志文件的上限大小,那么到了這個值,就會刪除舊的日志 -->
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>[Eran]%date [%thread %line] %level >> %msg >> %logger{10}%n</pattern>
</encoder>
</appender>
RollingFileAppender是非常常用的一種日志類型,表示滾動紀錄文件,先將日志記錄到指定文件,當符合某種條件時,將日志記錄到其他文件,常用的子節點:
- <rollingPolicy>:滾動策略,通過屬性class來指定使用什么滾動策略,最常用是按時間滾動TimeBasedRollingPolicy,即負責滾動也負責觸發滾動,有以下常用子節點:
- <fileNamePattern>:指定日志的路徑以及日志文件名的命名規則,一般根據日志文件名+%d{}.log來命名,這邊日期的格式默認為yyyy-MM-dd表示每天生成一個文件,即按天滾動yyyy-MM,表示每個月生成一個文件,即按月滾動
- <maxHistory>:可選節點,控制保存的日志文件的最大數量,超出數量就刪除舊文件,比如設置每天滾動,且<maxHistory> 是7,則只保存最近7天的文件,刪除之前的舊文件
- <encoder>:同上
- <totalSizeCap>:這個節點表示設置所有的日志文件最多占的內存大小,當超過我們設置的值時,logback就會刪除最早創建的那一個日志文件。
以上就是關于RollingFileAppender的常用介紹,上面的demo的配置也基本滿足了我們按照時間滾動TimeBasedRollingPolicy生成日志的要求,下面再介紹一種常用的滾動類型
SizeAndTimeBasedRollingPolicy,即按照時間和大小來滾動。
按時間和大小滾動
SizeAndTimeBasedRollingPolicy
demo如下:
<appender name="ROL-SIZE-FILE-LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>D:/logs/test.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 單個文件的最大內存 -->
<maxFileSize>100MB</maxFileSize>
<!-- 只保留近七天的日志 -->
<maxHistory>7</maxHistory>
<!-- 用來指定日志文件的上限大小,那么到了這個值,就會刪除舊的日志 -->
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>[Eran]%date [%thread %line] %level >> %msg >> %logger{10}%n</pattern>
</encoder>
</appender>
仔細觀察上邊demo中的<fileNamePattern>會發現比TimeBasedRollingPolicy中定義的<fileNamePattern>多了.%i的字符,這個很關鍵,在
SizeAndTimeBasedRollingPolicy中是必不可少的。
上邊的demo中多了一個<maxFileSize>節點,這里介紹下,其他的節點上邊已經解釋過,這里就不再贅述。
<maxFileSize>:表示單個文件占用的最大內存大小,當某個文件超過這個值,就會觸發滾動策略,產生一個新的日志文件。
日志過濾
級別介紹
在說級別過濾之前,先介紹一下日志的級別信息:
- TRACE
- DEBUG
- INFO
- WARN
- ERROR
上述級別從上到下由低到高,我們開發測試一般輸出DEBUG級別的日志,生產環境配置只輸出INFO級別甚至只輸出ERROR級別的日志,這個根據情況而定,很靈活。
過濾節點<filter>介紹
過濾器通常配置在Appender中,一個Appender可以配置一個或者多個過濾器,有多個過濾器時按照配置順序依次執行,當然也可以不配置,其實大多數情況下我們都不需要配置,但是有的情況下又必須配置,所以這里也介紹下常用的也是筆者曾經使用過的兩種過率機制:級別過濾器LevelFilter和臨界值過濾器ThresholdFilter。
在此之前先說下<filter>的概念,首先一個過濾器<filter>的所有返回值有三個,每個過濾器都只返回下面中的某一個值:
- DENY:日志將被過濾掉,并且不經過下一個過濾器
- NEUTRAL:日志將會到下一個過濾器繼續過濾
- ACCEPT:日志被立即處理,不再進入下一個過濾器
級別過濾器LevelFilter
過濾條件:只處理INFO級別的日志,格式如下:
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
- <level>:日志級別
- <onMatch>:配置滿足過濾條件的處理方式
- <onMismatch>:配置不滿足過濾條件的處理方式
就如上邊的demo中的配置一樣,設置了級別為INFO,滿足的日志返回ACCEPT即立即處理,不滿足條件的日志則返回DENY即丟棄掉,這樣經過這一個過濾器就只有INFO級別的日志會被打印出輸出。
臨界值過濾器ThresholdFilter
過濾條件:只處理INFO級別之上的日志,格式如下:
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
當日志級別等于或高于臨界值時,過濾器返回NEUTRAL,當日志級別低于臨界值時,返回DENY。
帶過濾器的<Appender>
下面給出一個帶過濾器的<Appender>:
<appender name="ROL-SIZE-FILE-LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>D:/logs/test.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 單個文件的最大內存 -->
<maxFileSize>100MB</maxFileSize>
<!-- 只保留近七天的日志 -->
<maxHistory>7</maxHistory>
<!-- 用來指定日志文件的上限大小,那么到了這個值,就會刪除舊的日志 -->
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>[Eran]%date [%thread %line] %level >> %msg >> %logger{10}%n</pattern>
</encoder>
<!-- 只處理INFO級別以及之上的日志 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<!-- 只處理INFO級別的日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
上邊的demo中,我們給按時間和大小滾動
SizeAndTimeBasedRollingPolicy的滾動類型加上了過濾條件。
異步寫入日志AsyncAppender
都知道,我們的日志語句是嵌入在程序內部,如果寫入日志以及程序執行的處于一個串行的狀態,那么日志的記錄就必然會阻礙程序的執行,加長程序的響應時間,無疑是一種極為損耗效率的方式,所以實際的項目中我們的日志記錄一般都用異步的方式來記錄,這樣就和主程序形成一種并行的狀態,不會影響我們程序的運行,這也是我們性能調優需要注意的一個點。
AsyncAppender并不處理日志,只是將日志緩沖到一個BlockingQueue里面去,并在內部創建一個工作線程從隊列頭部獲取日志,之后將獲取的日志循環記錄到附加的其他appender上去,從而達到不阻塞主線程的效果。因此AsynAppender僅僅充當事件轉發器,必須引用另一個appender來寫日志。
<appender name ="ASYNC" class= "ch.qos.logback.classic.AsyncAppender">
<!-- 不丟失日志.默認的,如果隊列的80%已滿,則會丟棄TRACT、DEBUG、INFO級別的日志 -->
<discardingThreshold >0</discardingThreshold>
<!-- 更改默認的隊列的深度,該值會影響性能.默認值為256 -->
<queueSize>512</queueSize>
<!-- 添加附加的appender,最多只能添加一個 -->
<appender-ref ref ="FILE_LOG"/>
</appender>
常用節點:
- <discardingThreshold>:默認情況下,當BlockingQueue還有20%容量,他將丟棄TRACE、DEBUG和INFO級別的日志,只保留WARN和ERROR級別的日志。為了保持所有的日志,設置該值為0。
- <queueSize>:BlockingQueue的最大容量,默認情況下,大小為256。
- <appender-ref>:添加附加的<appender>,最多只能添加一個
<logger>和<root>節點介紹
上邊花費了很長的篇幅介紹了<appender>的相關內容,現在來詳細介紹下<logger>節點以及<root>節點的相關內容。
上文已經簡單介紹了<logger>節點的屬性以及子節點,這里我們就舉例來說明在logback-spring.xml文件中,該節點到底扮演怎樣的角色,以及他的運行原理,看下邊的demo:
首先在這里給出項目結構:
下面定義兩個<logger>以及<root>:
<!-- logger1 -->
<logger name="com.example" level="ERROR">
<appender-ref ref="STDOUT" />
</logger>
<!-- logger2 -->
<logger name="com.example.demo.controller" level="debug">
<appender-ref ref="STDOUT" />
</logger>
<!-- 指定最基礎的日志輸出級別為DEBUG,并且綁定了名為STDOUT的appender,表示將日志信息輸出到控制臺 -->
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
當存在多個<logger>時,會有父級子級的概念,日志的處理流程是先子級再父級,當然<root>是最高級別,怎樣區分級別大小呢,根據name屬性指定的包名來判斷,包名級別越高則<logger>的級別越高,跟我們定義<logger>的順序無關。
上邊我們定義了logger1和logger2,很明顯看出logger1是logger2的父級,以本例給出多個<logger>與<root>之間的執行流程圖:
流程圖看著一目了然,這里就不再贅述,只是在實際的項目中我們一般都不讓<logger>輸出日志,統一放在<root>節點中輸出,所以一般不給<logger>節點添加<appender>,當然這個按實際需要可以靈活配置。
配置profile
profile即根據不同的環境使用不同的日志策略,這里舉例開發和生產環境:
<!-- 開發環境輸出到控制臺 -->
<springProfile name="dev">
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</springProfile>
<!-- 生產環境輸出到文件 -->
<springProfile name="prod">
<root level="INFO">
<appender-ref ref="FILE_LOG" />
</root>
</springProfile>
可以看到我們只需要在<root>節點的外邊再套一層<springProfile>就可以了,并且指定name屬性的值,在配置文件里邊配置好之后,怎么啟用,這里介紹兩種方式:
- 執行jar包時添加參數:
java -jar xxx.jar --spring.profiles.active=prod
- 在項目的application.properties配置文件中添加:
spring.profiles.active=prod
整合
最后將所有的模塊整合在一起形成一個完整的配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--定義一個將日志輸出到控制臺的appender,名稱為STDOUT -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%contextName]%date [%thread %line] %level >> %msg >> %logger{10}%n</pattern>
</encoder>
</appender>
<!--定義一個將日志輸出到文件的appender,名稱為FILE_LOG -->
<appender name="FILE_LOG" class="ch.qos.logback.core.FileAppender">
<file>D:/test.log</file>
<append>true</append>
<encoder>
<pattern>[Eran]%date [%thread %line] %level >> %msg >> %logger{10}%n</pattern>
</encoder>
</appender>
<!-- 按時間滾動產生日志文件 -->
<appender name="ROL-FILE-LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--滾動策略,按照時間滾動 TimeBasedRollingPolicy-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>D:/logs/test.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 只保留近七天的日志 -->
<maxHistory>7</maxHistory>
<!-- 用來指定日志文件的上限大小,那么到了這個值,就會刪除舊的日志 -->
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>[Eran]%date [%thread %line] %level >> %msg >> %logger{10}%n</pattern>
</encoder>
</appender>
<!-- 按時間和文件大小滾動產生日志文件 -->
<appender name="ROL-SIZE-FILE-LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>D:/logs/test.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 單個文件的最大內存 -->
<maxFileSize>100MB</maxFileSize>
<!-- 只保留近七天的日志 -->
<maxHistory>7</maxHistory>
<!-- 用來指定日志文件的上限大小,那么到了這個值,就會刪除舊的日志 -->
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>[Eran]%date [%thread %line] %level >> %msg >> %logger{10}%n</pattern>
</encoder>
<!-- 只處理INFO級別以及之上的日志 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<!-- 只處理INFO級別的日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 異步寫入日志 -->
<appender name ="ASYNC" class= "ch.qos.logback.classic.AsyncAppender">
<!-- 不丟失日志.默認的,如果隊列的80%已滿,則會丟棄TRACT、DEBUG、INFO級別的日志 -->
<discardingThreshold >0</discardingThreshold>
<!-- 更改默認的隊列的深度,該值會影響性能.默認值為256 -->
<queueSize>512</queueSize>
<!-- 添加附加的appender,最多只能添加一個 -->
<appender-ref ref ="FILE_LOG"/>
</appender>
<!-- 指定com.demo包下的日志打印級別為DEBUG,但是由于沒有引用appender,所以該logger不會打印日志信息,日志信息向上傳遞 -->
<logger name="com.example" level="DEBUG"></logger>
<!-- 這里的logger根據需要自己靈活配置 ,我這里只是給出一個demo-->
<!-- 指定開發環境基礎的日志輸出級別為DEBUG,并且綁定了名為STDOUT的appender,表示將日志信息輸出到控制臺 -->
<springProfile name="dev">
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>
</springProfile>
<!-- 指定生產環境基礎的日志輸出級別為INFO,并且綁定了名為ASYNC的appender,表示將日志信息異步輸出到文件 -->
<springProfile name="prod">
<root level="INFO">
<appender-ref ref="ASYNC" />
</root>
</springProfile>
</configuration>
代碼中使用
終于到最后一步了,上邊介紹了怎么配置logback-spring.xml配置文件,下面介紹怎么在項目中引入日志對象,以及怎么使用它輸出日志,直接上代碼:
package com.example.demo.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestLog {
private final static Logger log = LoggerFactory.getLogger(TestLog.class);
@RequestMapping(value="/log",method=RequestMethod.GET)
public void testLog() {
log.trace("trace級別的日志");
log.debug("debug級別日志");
log.info("info級別日志");
log.warn("warn級別的日志");
log.error("error級別日志");
}
}
在每一個需要使用日志對象的方法里邊都要定義一次private final static Logger log = LoggerFactory.getLogger(xxx.class);其中xxx代指當前類名,如果覺得這樣很麻煩,也可以通過@Slf4j注解的方式注入,但是這種方式需要添加pom依賴并且需要安裝lombok插件,這里就不概述了,需要了解的朋友可以自己google。