1.去除默認的依賴並導入log4j2、lombok依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <exclusions> <!-- 引入log4j日志時需去掉默認的logback --> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <!-- 日志管理log4j2 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> <version>2.1.0.RELEASE</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
上面log4j2是直接導入了SpringBoot對應的版本,也可以導入spring的版本,兩種二選一:
<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.11.2</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.11.2</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>2.11.2</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.30</version> </dependency>
2.在資源目錄下新建log4j2.xml文件
1)通用日志記錄:所有等級的日志都記錄在同一個文件中
<?xml version="1.0" encoding="UTF-8"?> <configuration status="info"> <Properties> <!-- 聲明日志文件存儲的目錄 --> <Property name="LOG_HOME">E:/logs/app/</Property> <Property name="APP_NAME">log</Property> <Property name="LOG_PATTERN" value="%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread][%class{36}:%line] - %msg%n"></Property> </Properties> <Appenders> <!--輸出控制台的配置--> <Console name="Console" target="SYSTEM_OUT"> <!--控制台只輸出level及以上級別的信息(onMatch),其他的直接拒絕(onMismatch)--> <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> <!-- 輸出日志的格式--> <PatternLayout pattern="${LOG_PATTERN}"/> </Console> <!--輸出日志到文件的配置,每次大小超過size,則這size大小的日志會自動存入按年份-月份建立的文件夾下面--> <RollingFile name="RollingFile" fileName="${LOG_HOME}/${APP_NAME}.log" filePattern="${LOG_HOME}/%d{yyyy-MM}/%d{yyyy-MM-dd}_%i.log"> <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> <!-- 輸出日志的格式--> <PatternLayout pattern="${LOG_PATTERN}"/> <Policies> <TimeBasedTriggeringPolicy/> <SizeBasedTriggeringPolicy size="100MB"/> </Policies> <!-- 最多保留文件數 --> <DefaultRolloverStrategy max="365"/> </RollingFile> </Appenders> <!--然后定義Logger,只有定義了Logger並引入的Appender,Appender才會生效。Root中level配置了日志級別,可配置其他級別--> <Loggers> <Root level="info"> <AppenderRef ref="Console"/> <AppenderRef ref="RollingFile"/> </Root> </Loggers> </configuration>
在配置中指定了日志存儲的目錄是E:\logs\app,日志文件使用日期作為重要區分的條件。
2)分級日志記錄:不同等級的日志記錄到對應的文件中
<?xml version="1.0" encoding="UTF-8"?> <configuration status="info"> <Properties> <!-- 聲明日志文件存儲的目錄 --> <Property name="LOG_HOME">E:/logs/app/</Property> <Property name="LOG_PATTERN" value="%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread][%class{36}:%line] - %msg%n"></Property> </Properties> <Appenders> <!--輸出控制台的配置--> <Console name="Console" target="SYSTEM_OUT"> <!--控制台只輸出level及以上級別的信息(onMatch),其他的直接拒絕(onMismatch)--> <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> <!-- 輸出日志的格式--> <PatternLayout pattern="${LOG_PATTERN}"/> </Console> <!-- ERROR級別日志 --> <RollingFile name="infoAppender" fileName="${LOG_HOME}/info.log" filePattern="${LOG_HOME}/%d{yyyy-MM}/%d{yyyy-MM-dd}_info.log"> <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="${LOG_PATTERN}"/> <Policies> <TimeBasedTriggeringPolicy/> <SizeBasedTriggeringPolicy size="100MB"/> </Policies> </RollingFile> <!-- ERROR級別日志 --> <RollingFile name="errorAppender" fileName="${LOG_HOME}/error.log" filePattern="${LOG_HOME}/%d{yyyy-MM}/%d{yyyy-MM-dd}_error.log"> <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="${LOG_PATTERN}"/> <Policies> <TimeBasedTriggeringPolicy/> <SizeBasedTriggeringPolicy size="100MB" /> </Policies> </RollingFile> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="Console"/> <AppenderRef ref="infoAppender"/> <AppenderRef ref="errorAppender"/> </Root> </Loggers> </configuration>
對於是否分級記錄,根據需求決定。兩者選一即可。
3.在配置文件配置log4j2文件的位置
logging.config = classpath:log4j2.xml
4.添加測試方法進行測試
package com.zys.springboottestexample; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest public class SpringbootTestExampleApplicationTests { //創建日志對象 Logger logger = LogManager.getLogger(this.getClass()); @Test void test() { logger.info("我是info日志"); logger.warn("我是warn日志"); logger.error("我是error日志"); } }
執行測試方法后,在控制台打印了日志,同時在對應的目錄生成了日志文件,其內容和控制台是一致的。
5.在測試類上使用@Sl4j注解輸出日志
import lombok.extern.slf4j.Slf4j; ... @Slf4j public class SpringbootTestExampleApplicationTests { ... @Test public void test2() { log.info("天氣真熱啊"); log.error("天氣真熱啊"); } }
只寫了關鍵的代碼。使用sl4j時,直接使用log對象即可進行日志的輸出。這里分別演示了使用log4j2和sl4j進行日志的輸出和存儲到日志,可根據習慣選擇使用哪一種方式。使用sl4j輸出時實際上會轉成log4j2日志進行輸出。
6.日志占位符
當需要動態的輸出日志及參數時,可以使用占位符 "{}"進行占位。可以寫多個占位符,它會根據后面的參數進行位置匹配填充。log4j2和sl4j用法一樣,參考如下:
logger.info("你的姓名是:{},年齡是:{}", "張三", 20); log.info("你的姓名是:{},年齡是:{}", "張三", 20);
控制台打印的日志如下圖:
上述的實例中,有兩個大括號,第一個大括號匹配后面的第一個參數“張三”,第二個大括號匹配第二個參數20。依次類推。這樣可以減少字符串的拼接。
7.使用原生的logback
相比於log4j2,logback是有其自己的優勢的,其中有一點是它對sql日志的打印配置非常簡單,而log4j2配置會繁雜一些。下面看logback.xml配置
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="false" scanPeriod="60 seconds" debug="false"> <!-- 定義日志的根目錄 --> <property name="LOG_HOME" value="E:/logs/app" /> <!-- 定義日志文件名稱 --> <property name="appName" value="log"></property> <!-- 定義生成的文件夾 --> <timestamp key="package" datePattern="yyyy-MM"/> <!-- 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"> <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n</pattern> </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}/${package}/%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都有效 --> <!-- 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>
配置后,只需要在配置文件配置日志的級別即可:
#配置打印日志
logging:
level:
com.zys.demo: debug
配置不同的日志級別,就打印不同級別的日志。
對於logback和log4j2,各自有不同的優勢,但也有一定的問題。比如現在有個需求是按天生成日志文件,對於開發環境來說,使用默認的logback即可達到要求,但生產環境必須使用log4j2,若使用logback則不會自動切分日志文件,達不到要求。暫時不清楚問題出在哪里,故暫時按這種方式去處理。具體做法就是在開始時使用logback,而打包時使用log4j2,具體以pom.xml進行切換:
<!-- *********************************** -->
<!--
開發時使用logback,此次需要注釋,
正式環境使用log4j2,此處需要打開
-->
<!-- 引入log4j日志去掉默認的logback -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 日志管理log4j2 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>${log4j.version}</version>
</dependency>
<!-- *********************************** -->
當然各自的配置文件xml不能少。