title: Java 日志框架
date: 2021/02/05 12:28
一茧痕、Java 日志框架簡介
1.1 日志框架可以為我們做什么野来?
- 控制日志輸出的內(nèi)容和格式
- 控制日志輸出的位置
- 日志優(yōu)化:異步日志、日志文件的歸檔和壓縮
1.2 現(xiàn)有日志框架
日志門面:JCL(Jakarta Commons Logging踪旷,已廢棄)曼氛、slf4j(Simple Logging Facade for Java)、log4j2
日志實(shí)現(xiàn):log4j令野、JUL(java util logging)舀患、logback、log4j2
二气破、Java 原生日志框架
2.1 架構(gòu)(其他日志框架基本上也是這個(gè)架構(gòu))
Logger:記錄器聊浅,應(yīng)用程序通過 Logger 對(duì)象調(diào)用它的 api 方法來發(fā)布日志信息。Logger 對(duì)象通常是應(yīng)用程序訪問日志系統(tǒng)的入口。
Appender:也被稱為 Handlers低匙,每個(gè) Logger 會(huì)關(guān)聯(lián)一組 Handlers旷痕,Logger 會(huì)將日志交給關(guān)聯(lián)的 Handlers 處理,由 Handlers 負(fù)責(zé)對(duì)日志進(jìn)行記錄顽冶。Handler 是一個(gè)抽象欺抗,它的具體實(shí)現(xiàn)決定了日志記錄的位置(例如:控制臺(tái)、文件、網(wǎng)絡(luò)上的其他日志服務(wù)等)。
Layout:也被稱為 Formatters郑口,他負(fù)責(zé)對(duì)日志進(jìn)行轉(zhuǎn)換和格式化,Layouts決定了 數(shù)據(jù)在一條日志記錄中的最終形式报强。
Level:每條日志消息都有一個(gè)關(guān)聯(lián)的日志級(jí)別。該級(jí)別粗略的描述了該日志的重要性拱燃。
Filter:過濾器秉溉,根據(jù)需要來定制哪些信息會(huì)被記錄,哪些信息會(huì)被舍棄碗誉。
總結(jié):用戶使用 Logger 來進(jìn)行日志記錄召嘶,Logger 持有若干個(gè) Handler,日志的輸出操作是由Handler完成的哮缺。在 Handler 在輸出日志前弄跌,會(huì)經(jīng)過 Filter 的過濾,判斷哪些日志級(jí)別過濾放行哪些攔截尝苇,Handler 會(huì)將日志內(nèi)容輸出到指定位置(日志文件铛只、控制臺(tái)等)。Handler 在輸出日志時(shí)會(huì)使用 Layout糠溜,將輸出內(nèi)容進(jìn)行排版淳玩。
2.2 日志級(jí)別
JUL 中定義了 7 種日志級(jí)別:
- SEVERE(最高值)
- WARNING
- INFO (默認(rèn)級(jí)別)
- CONFIG
- FINE
- FINER
- FINEST(最低值)
其中還有兩個(gè)特殊的級(jí)別:
- OFF,可用來關(guān)閉日志記錄非竿。
- ALL蜕着,啟用所有消息的日志記錄。
2.3 快速入門
@Test
public void testQuick() throws Exception {
// 獲取日志記錄器對(duì)象
Logger logger = Logger.getLogger("cn.x5456.JULTest");
// 日志記錄輸出
logger.info("hello jul");
// 通用方法進(jìn)行日志記錄
logger.log(Level.INFO, "info msg");
// 通過占位符 方式輸出變量值
logger.log(Level.INFO, "用戶信息:{0},{1}", new Object[]{"x5456", 18});
}
2.4 硬編碼方式修改日志級(jí)別
@Test
public void testLogConfig() {
// 獲取日志記錄器對(duì)象
Logger logger = Logger.getLogger("cn.x5456.JULTest");
// 關(guān)閉系統(tǒng)默認(rèn)配置红柱,如果不關(guān)閉 info 級(jí)別以下的會(huì)記錄兩遍承匣,因?yàn)楫?dāng)前 Logger 的 Handler 記錄完之后又交給了父 Logger(RootLogger)的 Handler 記錄了一下
logger.setUseParentHandlers(false);
// 自定義配置日志級(jí)別
// 創(chuàng)建 ConsoleHandler 控制臺(tái)輸出
ConsoleHandler consoleHandler = new ConsoleHandler();
// 創(chuàng)建簡單格式轉(zhuǎn)換對(duì)象
SimpleFormatter simpleFormatter = new SimpleFormatter();
// 關(guān)聯(lián)輸出的格式
consoleHandler.setFormatter(simpleFormatter);
logger.addHandler(consoleHandler);
// 配置日志具體級(jí)別
logger.setLevel(Level.ALL);
// 配置控制臺(tái)輸出的等級(jí)
consoleHandler.setLevel(Level.ALL);
// // 場(chǎng)景FileHandler 文件輸出
// FileHandler fileHandler = new FileHandler("/log/jul.log");
// // 關(guān)聯(lián)輸出的格式
// ileHandler.setFormatter(simpleFormatter);
// logger.addHandler(fileHandler);
// 2.日志記錄輸出
logger.severe("severe");
logger.warning("warning");
logger.info("info"); // 默認(rèn)日志輸出級(jí)別
logger.config("config");
logger.fine("fine");
logger.finer("finer");
logger.finest("finest");
}
2.5 Logger 的父子關(guān)系
JUL 中 Logger 之間存在父子關(guān)系,這種父子關(guān)系通過樹狀結(jié)構(gòu)存儲(chǔ)锤悄,JUL在初始化時(shí)會(huì)創(chuàng)建一個(gè)頂層 RootLogger 作為所有 Logger 父 Logger韧骗,存儲(chǔ)上作為樹狀結(jié)構(gòu)的根節(jié)點(diǎn)。并父子關(guān)系通過路徑來關(guān)聯(lián)铁蹈。
@Test
public void testLogParent() {
Logger logger1 = Logger.getLogger("cn.x5456");
Logger logger2 = Logger.getLogger("cn");
// true
System.out.println(logger1.getParent() == logger2);
// 所有日志記錄器的頂級(jí)父元素 LogManager$RootLogger
System.out.println("logger2 Parent:" + logger2.getParent());
}
這樣做的目的是宽闲,我們可以指定某些包路徑下的類打印日志的級(jí)別众眨、格式等信息握牧。
2.6 使用配置文件
默認(rèn)配置文件路徑$JAVAHOME\jre\lib\logging.properties
中容诬。
配置文件:
# RootLogger 頂級(jí)父元素指定的默認(rèn)處理器為:ConsoleHandler
handlers= java.util.logging.FileHandler,java.util.logging.ConsoleHandler
# RootLogger 頂級(jí)父元素默認(rèn)的日志級(jí)別為:ALL
.level= ALL
# 自定義 Logger 使用哪些處理器
cn.x5456.handlers = java.util.logging.FileHandler,java.util.logging.ConsoleHandler
cn.x5456.level = CONFIG
# 關(guān)閉默認(rèn)配置
cn.x5456.useParentHandlers = false
# 向日志文件輸出的 handler 對(duì)象
# 指定日志文件路徑 /logs/java0.log
java.util.logging.FileHandler.pattern = /Users/x5456/logs/java%u.log
# 指定日志文件內(nèi)容大小
java.util.logging.FileHandler.limit = 50000
# 指定日志文件數(shù)量
java.util.logging.FileHandler.count = 1
# 指定 handler 對(duì)象日志消息格式對(duì)象
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
# 指定以追加方式添加日志內(nèi)容
java.util.logging.FileHandler.append = true
# 向控制臺(tái)輸出的 handler 對(duì)象
# 指定 handler 對(duì)象的日志級(jí)別
java.util.logging.ConsoleHandler.level = ALL
# 指定 handler 對(duì)象的日志消息格式對(duì)象
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
# 指定 handler 對(duì)象的字符集
java.util.logging.ConsoleHandler.encoding = UTF-8
# 指定日志消息格式
java.util.logging.SimpleFormatter.format = %4$s: %5$s [%1$tc]%n
測(cè)試代碼:
@Test
public void testLogProperties() throws IOException {
// 讀取配置文件,通過類加載器
InputStream ins = JULTest.class.getClassLoader().getResourceAsStream("logging.properties");
// 創(chuàng)建LogManager
LogManager logManager = LogManager.getLogManager();
// 通過LogManager加載配置文件
logManager.readConfiguration(ins);
// 獲取到的日志記錄器的父記錄器是我們自定義的日志記錄器
Logger logger = Logger.getLogger("cn.x5456.JULTest");
logger.severe("severe");
logger.warning("warning");
logger.info("info");
logger.config("config");
logger.fine("fine");
logger.finer("finer");
logger.finest("finest");
// 獲取到的日志記錄器的父記錄器是 RootLogger
Logger logger2 = Logger.getLogger("test");
logger2.severe("severe test");
logger2.warning("warning test");
logger2.info("info test");
logger2.config("config test");
logger2.fine("fine test");
logger2.finer("finer test");
logger2.finest("finest test");
}
2.7 JUL 原理
- 初始化LogManager
- LogManager加載logging.properties配置
- 添加Logger到LogManager
- 從單例LogManager獲取Logger
- 設(shè)置級(jí)別Level沿腰,并指定日志記錄LogRecord
- Filter提供了日志級(jí)別之外更細(xì)粒度的控制
- Handler是用來處理日志輸出位置
- Formatter是用來格式化LogRecord的
三览徒、Log4j
Log4j 是 Apache 下的一款開源的日志框架,通過在項(xiàng)目中使用 Log4J颂龙,我們可以控制日志信息輸出到控 制臺(tái)习蓬、文件、甚至是數(shù)據(jù)庫中措嵌。我們可以控制每一條日志的輸出格式躲叼,通過定義日志的輸出級(jí)別,可以更靈活的控制日志的輸出過程企巢。方便項(xiàng)目的調(diào)試枫慷。
使用 Log4j 記錄日志只需要引入下面的依賴即可:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
3.1 快速入門
@Test
public void test() {
/*
直接運(yùn)行下面的代碼會(huì)提示如下警告。
log4j:WARN No appenders could be found for logger (cn.x5456.Log4JTest). 沒有為 logger 配置 appenders
log4j:WARN Please initialize the log4j system properly. 請(qǐng)配置 log4j.properties 以初始化
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
也可以直接使用 BasicConfigurator.configure() 方法向 RootLogger 中新增一個(gè)默認(rèn)的 appender浪规,無需 properties 配置文件
*/
// BasicConfigurator.configure();
// 獲取日志記錄器對(duì)象
Logger logger = Logger.getLogger(Log4JTest.class);
// 日志記錄輸出
logger.fatal("fatal"); // 嚴(yán)重錯(cuò)誤或听,一般會(huì)造成系統(tǒng)崩潰并終止運(yùn)行
logger.error("error"); // 錯(cuò)誤信息,不會(huì)影響系統(tǒng)運(yùn)行
logger.warn("warn"); // 警告信息笋婿,可能會(huì)發(fā)生問題
logger.info("info"); // 運(yùn)行信息誉裆,數(shù)據(jù)連接、網(wǎng)絡(luò)連接缸濒、IO 操作等等
logger.debug("debug"); // 調(diào)試信息足丢,一般在開發(fā)中使用,記錄程序變量參數(shù)傳遞信息等等
logger.trace("trace"); // 追蹤信息庇配,記錄程序所有的流程信息
}
注:還有兩個(gè)特殊的級(jí)別: OFF斩跌,可用來關(guān)閉日志記錄。ALL讨永,啟用所有消息的日志記錄滔驶。
3.2 Log4j 的組件
Log4j 主要由 Loggers (日志記錄器)、Appenders(輸出端)和 Layout(日志格式化器)組成卿闹。
- Loggers 控制日志的輸出級(jí)別與日志是否輸出
- Appenders 指定日志的輸出方式(輸出到控制臺(tái)揭糕、文件 等)
- Layout 控制日志信息的輸出格式。
3.2.1 Loggers
日志記錄器锻霎,負(fù)責(zé)收集處理日志記錄著角,實(shí)例的命名就是類"XX"的full quailied name (類的全限定名),Logger的名字大小寫敏感旋恼,其命名有繼承機(jī)制:例如:name 為 org.apache.commons 的 Logger 會(huì)繼承 name 為 org.apache 的 Logger吏口。
Log4j 中有一個(gè)特殊的 Logger 叫做 RootLogger,他是所有 Logger 的根,也就意味著其他所有的Logger都會(huì)直接或者間接地繼承自 RootLogger产徊。RootLogger 可以用 Logger.getRootLogger()
方法獲取昂勒。
下圖的 Category 是 Log4j 早期的命名,1.2 版本之后已經(jīng)改成了 Logger舟铜。
3.2.2 Appenders
Appender 用來指定日志輸出到哪個(gè)地方戈盈,Log4j 常用的輸出目的地有以下幾種:
Appender 實(shí)現(xiàn) | 作用 |
---|---|
ConsoleAppender | 將日志輸出到控制臺(tái) |
FileAppender | 將日志輸出到文件中 |
DailyRollingFileAppender | 將日志輸出到一個(gè)日志文件,并且每天輸出到一個(gè)新的文件 |
RollingFileAppender | 將日志信息輸出到一個(gè)日志文件谆刨,并且指定文件的尺寸塘娶,當(dāng)文件大 小達(dá)到指定尺寸時(shí),會(huì)自動(dòng)把文件改名痊夭,同時(shí)產(chǎn)生一個(gè)新的文件 |
JDBCAppender | 把日志信息保存到數(shù)據(jù)庫中 |
3.2.3 Layouts
布局器 Layout 用于控制日志輸出內(nèi)容的格式刁岸,讓我們可以使用各種需要的格式輸出日志。
格式化器類型 | 作用 |
---|---|
HTMLLayout | 格式化日志輸出為HTML表格形式 |
SimpleLayout | 簡單的日志輸出格式化她我,打印的日志格式為(info - message) |
PatternLayout | 最強(qiáng)大的格式化期虹曙,可以根據(jù)自定義格式輸出日志,如果沒有指定轉(zhuǎn)換格式鸦难,就是用默認(rèn)的轉(zhuǎn)換格式 |
PatternLayout 的格式
log4j 采用類似 C 語言的 printf 函數(shù)的打印格式格式化日志信息根吁,具體的占位符及其含義如下:
- %m 輸出代碼中指定的日志信息
- %p 輸出優(yōu)先級(jí),及 DEBUG合蔽、INFO 等
- %n 換行符(Windows平臺(tái)的換行符為 "\r\n"击敌,Unix 平臺(tái)為 "\n")
- %r 輸出自應(yīng)用啟動(dòng)到輸出該 log 信息耗費(fèi)的毫秒數(shù)
- %c 輸出打印語句所屬的類的全名
- %t 輸出產(chǎn)生該日志的線程全名
- %d 輸出服務(wù)器當(dāng)前時(shí)間,默認(rèn)為 ISO8601拴事,也可以指定格式沃斤,如:%d{yyyy年MM月dd日 HH:mm:ss}
- %l 輸出日志時(shí)間發(fā)生的位置,包括類名刃宵、線程衡瓶、及在代碼中的行數(shù)。如:Test.main(Test.java:10)
- %F 輸出日志消息產(chǎn)生時(shí)所在的文件名稱
- %L 輸出代碼中的行號(hào)
- %% 輸出一個(gè) "%" 字符
可以在 % 與字符之間加上修飾符來控制最小寬度牲证、最大寬度和文本的對(duì)其方式哮针。如:
- %5c 輸出category名稱,最小寬度是5坦袍,category<5十厢,默認(rèn)的情況下右對(duì)齊
- %-5c 輸出category名稱,最小寬度是5捂齐,category<5蛮放,"-"號(hào)指定左對(duì)齊,會(huì)有空格
- %.5c 輸出category名稱奠宜,最大寬度是5包颁,category>5瞻想,就會(huì)將左邊多出的字符截掉,<5不會(huì)有空格
- %20.30c category名稱<20補(bǔ)空格娩嚼,并且右對(duì)齊蘑险,>30字符,就從左邊交遠(yuǎn)銷出的字符截掉
3.3 測(cè)試 Appender
@Test
public void testQuick() {
// 開啟 log4j 內(nèi)置日志記錄
LogLog.setInternalDebugging(true);
// 獲取日志記錄器對(duì)象
Logger logger = Logger.getLogger(Log4jTest.class);
//for (int i = 0; i < 10000; i++) {
// 日志級(jí)別
logger.fatal("fatal"); // 嚴(yán)重錯(cuò)誤待锈,一般會(huì)造成系統(tǒng)崩潰并終止運(yùn)行
logger.error("error"); // 錯(cuò)誤信息漠其,不會(huì)影響系統(tǒng)運(yùn)行
logger.warn("warn"); // 警告信息嘴高,可能會(huì)發(fā)生問題
logger.info("info"); // 運(yùn)行信息竿音,數(shù)據(jù)連接、網(wǎng)絡(luò)連接拴驮、IO 操作等等
logger.debug("debug"); // 調(diào)試信息春瞬,一般在開發(fā)中使用,記錄程序變量參數(shù)傳遞信息等等
logger.trace("trace"); // 追蹤信息套啤,記錄程序所有的流程信息
//}
}
配置文件:
# 指定 RootLogger 頂級(jí)父元素默認(rèn)配置信息
# 指定日志級(jí)別=trace宽气,使用的 apeender 為=console
log4j.rootLogger = trace,console,dailyFile
# 指定控制臺(tái)日志輸出的 appender
log4j.appender.console = org.apache.log4j.ConsoleAppender
# 指定消息格式 layout
log4j.appender.console.layout = org.apache.log4j.PatternLayout
# 指定消息格式的內(nèi)容
log4j.appender.console.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
# 日志文件輸出的 appender 對(duì)象
log4j.appender.file = org.apache.log4j.FileAppender
# 指定消息格式 layout
log4j.appender.file.layout = org.apache.log4j.PatternLayout
# 指定消息格式的內(nèi)容
log4j.appender.file.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
# 指定日志文件保存路徑
log4j.appender.file.file = /Users/x5456/logs/log4j.log
# 指定日志文件的字符集
log4j.appender.file.encoding = UTF-8
# 按照文件大小拆分的 appender 對(duì)象
# 日志文件輸出的 appender 對(duì)象
log4j.appender.rollingFile = org.apache.log4j.RollingFileAppender
# 指定消息格式 layout
log4j.appender.rollingFile.layout = org.apache.log4j.PatternLayout
# 指定消息格式的內(nèi)容
log4j.appender.rollingFile.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
# 指定日志文件保存路徑
log4j.appender.rollingFile.file = /Users/x5456/logs/log4j.log
# 指定日志文件的字符集
log4j.appender.rollingFile.encoding = UTF-8
# 指定日志文件內(nèi)容的大小
log4j.appender.rollingFile.maxFileSize = 1MB
# 指定日志文件的數(shù)量
log4j.appender.rollingFile.maxBackupIndex = 10
# 按照時(shí)間規(guī)則拆分的 appender 對(duì)象
log4j.appender.dailyFile = org.apache.log4j.DailyRollingFileAppender
# 指定消息格式 layout
log4j.appender.dailyFile.layout = org.apache.log4j.PatternLayout
# 指定消息格式的內(nèi)容
log4j.appender.dailyFile.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
# 指定日志文件保存路徑
log4j.appender.dailyFile.file = /Users/x5456/logs/log4j.log
# 指定日志文件的字符集
log4j.appender.dailyFile.encoding = UTF-8
# 指定日期拆分規(guī)則
log4j.appender.dailyFile.datePattern = '.'yyyy-MM-dd-HH-mm-ss
3.4 自定義 Logger
@Test
public void testQuick() {
// 開啟 log4j 內(nèi)置日志記錄
LogLog.setInternalDebugging(true);
// 獲取日志記錄器對(duì)象
Logger logger = Logger.getLogger(Log4jTest.class);
// 日志級(jí)別
logger.fatal("fatal"); // 嚴(yán)重錯(cuò)誤,一般會(huì)造成系統(tǒng)崩潰并終止運(yùn)行
logger.error("error"); // 錯(cuò)誤信息潜沦,不會(huì)影響系統(tǒng)運(yùn)行
logger.warn("warn"); // 警告信息萄涯,可能會(huì)發(fā)生問題
logger.info("info"); // 運(yùn)行信息,數(shù)據(jù)連接唆鸡、網(wǎng)絡(luò)連接涝影、IO 操作等等
logger.debug("debug"); // 調(diào)試信息,一般在開發(fā)中使用争占,記錄程序變量參數(shù)傳遞信息等等
logger.trace("trace"); // 追蹤信息燃逻,記錄程序所有的流程信息
// 再創(chuàng)建一個(gè)日志記錄器對(duì)象
Logger logger1 = Logger.getLogger(Logger.class);
logger1.fatal("fatal logger1"); // 嚴(yán)重錯(cuò)誤,一般會(huì)造成系統(tǒng)崩潰并終止運(yùn)行
logger1.error("error logger1"); // 錯(cuò)誤信息臂痕,不會(huì)影響系統(tǒng)運(yùn)行
logger1.warn("warn logger1"); // 警告信息伯襟,可能會(huì)發(fā)生問題
logger1.info("info logger1"); // 運(yùn)行信息,數(shù)據(jù)連接握童、網(wǎng)絡(luò)連接姆怪、IO 操作等等
logger1.debug("debug logger1"); // 調(diào)試信息,一般在開發(fā)中使用澡绩,記錄程序變量參數(shù)傳遞信息等等
logger1.trace("trace logger1"); // 追蹤信息稽揭,記錄程序所有的流程信息
}
配置文件:
# 指定 RootLogger 頂級(jí)父元素默認(rèn)配置信息
# 指定日志級(jí)別=trace,使用的 apeender 為=console
log4j.rootLogger = trace,console
# 此時(shí)會(huì)同時(shí)向控制臺(tái)和文件中輸出 info 級(jí)別的日志英古,因?yàn)槔^承了 rootLogger 的 Appender
log4j.logger.cn.x5456=info,file
log4j.logger.org.apache = error
# 指定控制臺(tái)日志輸出的 appender
log4j.appender.console = org.apache.log4j.ConsoleAppender
# 指定消息格式 layout
log4j.appender.console.layout = org.apache.log4j.PatternLayout
# 指定消息格式的內(nèi)容
log4j.appender.console.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
# 日志文件輸出的 appender 對(duì)象
log4j.appender.file = org.apache.log4j.FileAppender
# 指定消息格式 layout
log4j.appender.file.layout = org.apache.log4j.PatternLayout
# 指定消息格式的內(nèi)容
log4j.appender.file.layout.conversionPattern = [%-10p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
# 指定日志文件保存路徑
log4j.appender.file.file = /Users/x5456/logs/log4j.log
# 指定日志文件的字符集
log4j.appender.file.encoding = UTF-8
四淀衣、JCL(Jakarta Commons Logging)
Jakarta Commons Logging 是 Apache 提供的一個(gè)通用日志API。
它是為“所有的Java日志實(shí)現(xiàn)”提供一個(gè)統(tǒng)一的接口召调,它自身也提供一個(gè)日志的實(shí)現(xiàn)膨桥,但是功能非常弱 (SimpleLog)蛮浑,所以一般不會(huì)單獨(dú)使用它。
他允許開發(fā)人員使用不同的具體日志實(shí)現(xiàn)工具: Log4j, Jdk 自帶的日志(JUL)
JCL 有兩個(gè)基本的抽象類:Log(基本記錄器)和 LogFactory(負(fù)責(zé)創(chuàng)建Log實(shí)例)只嚣。
JCL 依賴:
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
4.1 為什么要使用日志門面
當(dāng)我們的系統(tǒng)變的更加復(fù)雜的時(shí)候沮稚,我們的日志就容易發(fā)生混亂。隨著系統(tǒng)開發(fā)的進(jìn)行册舞,可能會(huì)更新不同的日志框架蕴掏,造成當(dāng)前系統(tǒng)中存在不同的日志依賴,讓我們難以統(tǒng)一的管理和控制调鲸。就算我們強(qiáng)制要求所有的模塊使用相同的日志框架盛杰,系統(tǒng)中也難以避免使用其他類似 spring,mybatis 等其他的第三方框架,它們依賴于我們規(guī)定不同的日志框架藐石,而且他們自身的日志系統(tǒng)就有著不一致性即供,依然會(huì)出來日志體系的混亂。
所以我們需要借鑒 JDBC 的思想于微,為日志系統(tǒng)也提供一套門面逗嫡,那么我們就可以面向這些接口規(guī)范來開發(fā),避免了直接依賴具體的日志框架株依。這樣我們的系統(tǒng)在日志中驱证,就存在了日志的門面和日志的實(shí)現(xiàn)。
- 面向接口開發(fā)恋腕,不再依賴具體的實(shí)現(xiàn)類抹锄。減少代碼的耦合
- 項(xiàng)目通過導(dǎo)入不同的日志實(shí)現(xiàn)類,可以靈活的切換日志框架
- 統(tǒng)一API吗坚,方便開發(fā)者學(xué)習(xí)和使用
- 統(tǒng)一配置便于項(xiàng)目日志的管理
4.2 使用
@Test
public void testQuick()throws Exception{
// 獲取 log日志記錄器對(duì)象
Log log = LogFactory.getLog(JCLTest.class);
// 日志記錄輸出
log.info("hello jcl");
}
4.3 原理
五祈远、SLF4J
簡單日志門面(Simple Logging Facade For Java) SLF4J 主要是為了給 Java 日志訪問提供一套標(biāo)準(zhǔn)、規(guī)范的 API 框架商源,其主要意義在于提供接口车份,具體的實(shí)現(xiàn)可以交由其他日志框架(例如 log4j 和 logback 等)。 當(dāng)然 slf4j 自己也提供了功能較為簡單的實(shí)現(xiàn)牡彻,但是一般很少用到扫沼。對(duì)于一般的 Java 項(xiàng)目而言,日志框架會(huì)選擇 slf4j-api 作為門面庄吼,配上具體的實(shí)現(xiàn)框架(log4j缎除、logback等),中間使用橋接器完成橋接总寻。
SLF4J 日志門面主要提供兩大功能:
- 日志框架的綁定
- 日志框架的橋接
使用 SLF4J 的好處:
- 使用SLF4J框架器罐,可以在部署時(shí)遷移到所需的日志記錄框架。
- SLF4J提供了對(duì)所有流行的日志框架的綁定渐行,例如 log4j轰坊,JUL铸董,Simple logging 和 NOP。因此可以在部署時(shí)切換到任何這些流行的框架肴沫。
- 無論使用哪種綁定粟害,SLF4J 都支持參數(shù)化日志記錄消息。由于 SLF4J 將應(yīng)用程序和日志記錄框架分離颤芬,因此可以輕松編寫?yīng)毩⒂谌罩居涗浛蚣艿膽?yīng)用程序悲幅。而無需擔(dān)心用于編寫應(yīng)用程序的日志記錄框架。
- SLF4J 提供了一個(gè)簡單的 Java 工具站蝠,稱為遷移器汰具。使用此工具,可以遷移現(xiàn)有項(xiàng)目沉衣,這些項(xiàng)目使用日志框架(如Jakarta Commons Logging 或 log4j 或 Java.util.logging)到 SLF4J郁副。
5.1 綁定日志的實(shí)現(xiàn)
使用slf4j的日志綁定流程:
- 添加slf4j-api的依賴
- 使用slf4j的API在項(xiàng)目中進(jìn)行統(tǒng)一的日志記錄
- 綁定具體的日志實(shí)現(xiàn)框架
- 綁定已經(jīng)實(shí)現(xiàn)了slf4j的日志框架,直接添加對(duì)應(yīng)依賴
- 綁定沒有實(shí)現(xiàn)slf4j的日志框架豌习,先添加日志的適配器,再添加實(shí)現(xiàn)類的依賴
- slf4j有且僅有一個(gè)日志實(shí)現(xiàn)框架的綁定(如果出現(xiàn)多個(gè)默認(rèn)使用第一個(gè)依賴日志實(shí)現(xiàn))
代碼:
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Slf4jTest {
public static final Logger LOGGER = LoggerFactory.getLogger(Slf4jTest.class);
// 快速入門
@Test
public void test01()throws Exception{
// 日志輸出
LOGGER.error("error");
LOGGER.warn("wring");
LOGGER.info("info"); // 默認(rèn)級(jí)別
LOGGER.debug("debug");
LOGGER.trace("trace");
// 使用占位符輸出日志信息
String name = "itheima";
Integer age = 14;
LOGGER.info("用戶:{},{}",name,age);
// 將系統(tǒng)的異常信息輸出
try {
int i = 1/0;
} catch (Exception e) {
// e.printStackTrace();
LOGGER.error("出現(xiàn)異常:",e);
}
}
}
Maven 依賴:
<!-- slf4j 日志門面 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.26</version>
</dependency>
<!-- slf4j 內(nèi)置的簡單實(shí)現(xiàn)
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.21</version>
</dependency>
-->
<!--logback 日志實(shí)現(xiàn)-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!--nop 日志開關(guān)
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.25</version>
</dependency>
-->
<!--綁定 log4j 日志實(shí)現(xiàn),需要導(dǎo)入適配器
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
-->
<!--綁定 jul 日志實(shí)現(xiàn)拔疚,需要導(dǎo)入適配器
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.25</version>
</dependency>
-->
要切換日志框架肥隆,只需替換類路徑上的slf4j綁定。例如稚失,要從java.util.logging切換到log4j栋艳,只需將 slf4j-jdk14-1.7.27.jar 替換為 slf4j-log4j12-1.7.27.jar即可。
5.2 綁定原理
5.3 日志橋接
通常句各,您依賴的某些組件依賴于SLF4J以外的日志記錄API吸占。您也可以假設(shè)這些組件在不久的將來會(huì)切換到SLF4J。為了解決這種情況凿宾,SLF4J附帶了幾個(gè)橋接模塊矾屯,這些模塊將對(duì)log4j,JCL和 java.util.logging API的調(diào)用重定向初厚,就好像它們是對(duì)SLF4J API一樣件蚕。
橋接解決的是項(xiàng)目中日志的遺留問題,當(dāng)系統(tǒng)中存在之前的日志API产禾,可以通過橋接轉(zhuǎn)換到slf4j的實(shí)現(xiàn)排作。
使用步驟:
- 先去除之前老的日志框架的依賴
- 添加SLF4J提供的橋接組件
- 為項(xiàng)目添加SLF4J的具體實(shí)現(xiàn)
不常用,不想講了亚情。其實(shí)所謂的橋接器就是把之前的日志框架的一些類全部重寫了妄痪,改為調(diào)用 slf4j 了而已(JUL 除外)。
六楞件、Logback
Logback 是由 log4j 創(chuàng)始人設(shè)計(jì)的另一個(gè)開源日志組件衫生,性能比 log4j 要好僧著。
Logback主要分為三個(gè)模塊:
- logback-core:其它兩個(gè)模塊的基礎(chǔ)模塊
- logback-classic:它是log4j的一個(gè)改良版本,同時(shí)它完整實(shí)現(xiàn)了slf4j API
- logback-access:訪問模塊與Servlet容器集成提供通過Http來訪問日志的功能
注:后續(xù)的日志代碼都是通過 SLF4J 日志門面搭建日志系統(tǒng)障簿,所以在代碼是沒有區(qū)別盹愚,主要是通過修改配置文件和 pom.xml 依賴
6.1 快速開始
maven 依賴:
<!--slf4j 日志門面-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.26</version>
</dependency>
<!--logback 日志實(shí)現(xiàn)-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
代碼:
public static final Logger LOGGER = LoggerFactory.getLogger(LogbackTest.class);
@Test
public void testQuick() {
// 日志輸出
LOGGER.error("error");
LOGGER.warn("wring");
LOGGER.info("info");
LOGGER.debug("debug");// 默認(rèn)級(jí)別
LOGGER.trace("trace");
}
6.2 logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--
配置集中管理屬性
我們可以直接改屬性的 value 值
格式:${name}
-->
<property name="pattern" value="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread] %m%n" />
<!--
日志輸出格式:
%-5level
%d{yyyy-MM-dd HH:mm:ss.SSS}日期
%c類的完整名稱
%M為method
%L為行號(hào)
%thread線程名稱
%m或者%msg為信息
%n換行
-->
<!--定義日志文件保存路徑屬性-->
<property name="log_dir" value="/Users/x5456/logs" />
<!--控制臺(tái)日志輸出的 appender-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!--控制輸出流對(duì)象 默認(rèn) System.out 改為 System.err-->
<target>System.err</target>
<!--日志消息格式配置-->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
</appender>
<!--日志文件輸出的 appender-->
<appender name="file" class="ch.qos.logback.core.FileAppender">
<!--日志文件保存路徑-->
<file>${log_dir}/logback.log</file>
<!--日志消息格式配置-->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
</appender>
<!--html 格式日志文件輸出 appender-->
<appender name="htmlFile" class="ch.qos.logback.core.FileAppender">
<!--日志文件保存路徑-->
<file>${log_dir}/logback.html</file>
<!--html 消息格式配置-->
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.classic.html.HTMLLayout">
<pattern>%-5level%d{yyyy-MM-dd HH:mm:ss.SSS}%c%M%L%thread%m</pattern>
</layout>
</encoder>
</appender>
<!--日志拆分和歸檔壓縮的 appender 對(duì)象-->
<appender name="rollFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日志文件保存路徑-->
<file>${log_dir}/roll_logback.log</file>
<!--日志消息格式配置-->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${pattern}</pattern>
</encoder>
<!--指定拆分規(guī)則-->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--按照時(shí)間和壓縮格式聲明拆分的文件名-->
<fileNamePattern>${log_dir}/rolling.%d{yyyy-MM-dd}.log%i.gz</fileNamePattern>
<!--按照文件大小拆分-->
<maxFileSize>1MB</maxFileSize>
</rollingPolicy>
<!--日志級(jí)別過濾器-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!--日志過濾規(guī)則,只保存 ERROR 級(jí)別的錯(cuò)誤-->
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--異步日志-->
<appender name="async" class="ch.qos.logback.classic.AsyncAppender">
<!--指定某個(gè)具體的 appender-->
<appender-ref ref="rollFile"/>
</appender>
<!--root logger 配置-->
<root level="ALL">
<appender-ref ref="console"/>
<appender-ref ref="async"/>
<appender-ref ref="htmlFile"/>
</root>
<!--自定義 looger 對(duì)象
additivity="false" 自定義 logger 對(duì)象是否繼承 rootLogger
-->
<logger name="com.itheima" level="info" additivity="false">
<appender-ref ref="console"/>
</logger>
</configuration>
七站故、Log4j2
Apache Log4j 2是對(duì) Log4j 的升級(jí)版皆怕,參考了 Logback 的一些優(yōu)秀的設(shè)計(jì),并且修復(fù)了一些問題西篓,因此帶來了一些重大的提升愈腾,主要有:
- 異常處理,在logback中岂津,Appender中的異常不會(huì)被應(yīng)用感知到虱黄,但是在log4j2中,提供了一些異常處理機(jī)制吮成。
- 性能提升橱乱,log4j2 相較于 log4j 和 logback 都具有很明顯的性能提升,后面會(huì)有官方測(cè)試的數(shù)據(jù)粱甫。
- 自動(dòng)重載配置泳叠,參考了logback的設(shè)計(jì),當(dāng)然會(huì)提供自動(dòng)刷新參數(shù)配置茶宵,最實(shí)用的就是我們?cè)谏a(chǎn)上可以動(dòng)態(tài)的修改日志的級(jí)別而不需要重啟應(yīng)用危纫。
- 無垃圾機(jī)制,log4j2在大部分情況下乌庶,都可以使用其設(shè)計(jì)的一套無垃圾機(jī)制种蝶,避免頻繁的日志收集導(dǎo)致的jvm gc。
7.1 快速入門
使用 log4j2 自己的門面
依賴:
<!--log4j2日志門面-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.11.1</version>
</dependency>
<!--log4j2 日志實(shí)現(xiàn)-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.11.1</version>
</dependency>
代碼:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Test;
public class Log4j2Test {
// 定義日志記錄器對(duì)象
public static final Logger LOGGER = LogManager.getLogger(Log4j2Test.class);
// 快速入門
@Test
public void testQuick()throws Exception{
// 日志消息輸出
LOGGER.fatal("fatal");
LOGGER.error("error");
LOGGER.warn("warn");
LOGGER.info("inf");
LOGGER.debug("debug");
LOGGER.trace("trace");
}
}
使用 slf4j 做門面
依賴:
<!--使用slf4j 作為日志門面-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.26</version>
</dependency>
<!--使用 log4j2 的適配器進(jìn)行綁定-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.9.1</version>
</dependency>
<!--log4j2日志門面-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.11.1</version>
</dependency>
<!--log4j2 日志實(shí)現(xiàn)-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.11.1</version>
</dependency>
代碼:
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Slf4jTest {
public static final Logger LOGGER = LoggerFactory.getLogger(Slf4jTest.class);
// 快速入門
@Test
public void test01()throws Exception{
// 日志輸出
LOGGER.error("error");
LOGGER.warn("wring");
LOGGER.info("info");
LOGGER.debug("debug");
LOGGER.trace("trace");
}
}
7.2 log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
status="warn" 日志框架本身的輸出日志級(jí)別
monitorInterval="5" 自動(dòng)加載配置文件的間隔時(shí)間瞒大,不低于 5 秒
-->
<Configuration status="debug" monitorInterval="5">
<!--
集中配置屬性進(jìn)行管理
使用時(shí)通過:${name}
-->
<properties>
<property name="LOG_HOME">/logs</property>
</properties>
<!--日志處理-->
<Appenders>
<!--控制臺(tái)輸出 appender-->
<Console name="Console" target="SYSTEM_ERR">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n"/>
</Console>
<!--日志文件輸出 appender-->
<File name="file" fileName="${LOG_HOME}/myfile.log">
<PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %m%n"/>
</File>
<!--<Async name="Async">-->
<!--<AppenderRef ref="file"/>-->
<!--</Async>-->
<!--使用隨機(jī)讀寫劉的日志文件輸出 appender螃征,性能提高-->
<RandomAccessFile name="accessFile" fileName="${LOG_HOME}/myAcclog.log">
<PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %m%n"/>
</RandomAccessFile>
<!--按照一定規(guī)則拆分的日志文件的 appender-->
<RollingFile name="rollingFile" fileName="${LOG_HOME}/myrollog.log"
filePattern="/logs/$${date:yyyy-MM-dd}/myrollog-%d{yyyy-MM-dd-HH-mm}-%i.log">
<!--日志級(jí)別過濾器-->
<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
<!--日志消息格式-->
<PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %msg%n"/>
<Policies>
<!--在系統(tǒng)啟動(dòng)時(shí),出發(fā)拆分規(guī)則糠赦,生產(chǎn)一個(gè)新的日志文件-->
<OnStartupTriggeringPolicy/>
<!--按照文件大小拆分会傲,10MB -->
<SizeBasedTriggeringPolicy size="10 MB"/>
<!--按照時(shí)間節(jié)點(diǎn)拆分,規(guī)則根據(jù)filePattern定義的-->
<TimeBasedTriggeringPolicy/>
</Policies>
<!--在同一個(gè)目錄下拙泽,文件的個(gè)數(shù)限定為 30 個(gè)淌山,超過進(jìn)行覆蓋-->
<DefaultRolloverStrategy max="30"/>
</RollingFile>
</Appenders>
<!--logger 定義-->
<Loggers>
<!--自定義異步 logger 對(duì)象
includeLocation="false" 關(guān)閉日志記錄的行號(hào)信息
additivity="false" 不在繼承 rootlogger 對(duì)象
-->
<AsyncLogger name="com.itheima" level="trace" includeLocation="false" additivity="false">
<AppenderRef ref="Console"/>
</AsyncLogger>
<!--使用 rootLogger 配置 日志級(jí)別 level="trace"-->
<Root level="trace">
<!--指定日志使用的處理器-->
<AppenderRef ref="Console"/>
<!--使用異步 appender-->
<AppenderRef ref="Async"/>
</Root>
</Loggers>
</Configuration>
7.3 異步日志
log4j2最大的特點(diǎn)就是異步日志,其性能的提升主要也是從異步日志中受益顾瞻,我們來看看如何使用 log4j2 的異步日志泼疑。
異步日志需要下面這個(gè)依賴:
<!--異步日志依賴-->
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.3.4</version>
</dependency>
Log4j2 提供了兩種實(shí)現(xiàn)日志的方式,一個(gè)是通過 AsyncAppender荷荤,一個(gè)是通過 AsyncLogger退渗,分別對(duì)應(yīng)前面我們說的 Appender 組件和 Logger 組件移稳。
AsyncAppender 方式
<Appenders>
<!--控制臺(tái)輸出 appender-->
<Console name="Console" target="SYSTEM_ERR">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n"/>
</Console>
<!--日志文件輸出 appender-->
<File name="file" fileName="${LOG_HOME}/myfile.log">
<PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %m%n"/>
</File>
<Async name="Async">
<AppenderRef ref="file"/>
</Async>
AsyncLogger 方式
AsyncLogger才是log4j2 的重頭戲,也是官方推薦的異步方式会油。它可以使得調(diào)用Logger.log返回的更快个粱。你可以有兩種選擇:全局異步和混合異步。
全局異步就是翻翩,所有的日志都異步的記錄都许,在配置文件上不用做任何改動(dòng),只需要在類路徑中添加一個(gè) log4j2.component.properties 配置:
Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
混合異步就是嫂冻,你可以在應(yīng)用中同時(shí)使用同步日志和異步日志胶征,這使得日志的配置方式更加靈活。
<!--logger 定義-->
<Loggers>
<!--自定義異步 logger 對(duì)象
includeLocation="false" 關(guān)閉日志記錄的行號(hào)信息
additivity="false" 不在繼承 rootlogger 對(duì)象
-->
<AsyncLogger name="com.itheima" level="trace" includeLocation="false" additivity="false">
<AppenderRef ref="Console"/>
</AsyncLogger>
<!--使用 rootLogger 配置 日志級(jí)別 level="trace"-->
<Root level="trace">
<!--指定日志使用的處理器-->
<AppenderRef ref="Console"/>
<!--使用異步 appender-->
<AppenderRef ref="Async"/>
</Root>
</Loggers>
如上配置:com.itheima 日志是異步的桨仿,root日志是同步的睛低。
使用異步日志需要注意的問題:
- 如果使用異步日志,AsyncAppender服傍、AsyncLogger和全局日志钱雷,不要同時(shí)出現(xiàn)。性能會(huì)和 AsyncAppender 一致伴嗡,降至最低急波。
- 設(shè)置includeLocation=false,打印位置信息(行號(hào))會(huì)急劇降低異步日志的性能瘪校,比同步日志還要慢。
八名段、SpringBoot 中日志的使用
8.1 SpringBoot 中日志設(shè)計(jì)
<dependency>
<artifactId>spring-boot-starter-logging</artifactId>
<groupId>org.springframework.boot</groupId>
</dependency>
依賴關(guān)系圖:
總結(jié):
- springboot 底層默認(rèn)使用logback作為日志實(shí)現(xiàn)阱扬。
- 使用了SLF4J作為日志門面
- 將JUL也轉(zhuǎn)換成slf4j
- 也可以使用log4j2作為日志門面,但是最終也是通過slf4j調(diào)用logback
8.2 使用
springboot 支持 logback.xml 和 logback-spring.xml伸辟,兩者的區(qū)別是麻惶,后者可以被 spring 解析 springProfile、springProperties 等屬性信夫。
在 application.properties 中也可以簡單的對(duì)日志進(jìn)行配置:
# 指定自定義 logger 對(duì)象日志級(jí)別
logging.level.com.itheima=trace
# 指定控制臺(tái)輸出消息格式
logging.pattern.console=[%-5level] %d{yyyy-MM-dd HH:mm:ss} %c [%thread]===== %msg %n
# 指定存放日志文件的具體路徑
# logging.file=/logs/springboot.log
# 指定日志文件存放的目錄窃蹋,默認(rèn)的文件名 spring.log
logging.file.path=/logs/springboot/
# 指定日志文件消息格式
logging.pattern.file=[%-5level] %d{yyyy-MM-dd HH:mm:ss} %c [%thread]===== %msg %n
8.3 切換日志實(shí)現(xiàn)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!--排除 logback 日志實(shí)現(xiàn)-->
<exclusion>
<artifactId>spring-boot-starter-logging</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!--使用 log4j2 的日志啟動(dòng)器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
此時(shí) SpringBoot 支持解析 log4j2.xml 和 log4j2-spring.xml。