前言
項目中日志系統(tǒng)是必不可少的衔峰,目前比較流行的日志框架有l(wèi)og4j、logback等录别,可能大家還不知道朽色,這兩個框架的作者是同一個人,Logback旨在作為流行的log4j項目的后續(xù)版本组题,從而恢復log4j離開的位置葫男。另外 slf4j(Simple Logging Facade for Java)則是一個日志門面框架,提供了日志系統(tǒng)中常用的接口崔列,logback 和 log4j 則對slf4j 進行了實現梢褐。我們本文將講述如何在spring boot 中應用 logback+slf4j實現日志的記錄。
為什么使用logback
Logback 是log4j 框架的作者開發(fā)的新一代日志框架赵讯,它效率更高盈咳、能夠適應諸多的運行環(huán)境,同時天然支持SLF4J
Logback的定制性更加靈活边翼,同時也是spring boot的內置日志框架
開始使用
添加依賴:
maven依賴中添加了spring-boot-starter-logging
<pre class="prettyprint hljs xml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </dependency>
</pre>
但是呢鱼响,實際開發(fā)中我們不需要直接添加該依賴,你會發(fā)現spring-boot-starter其中包含了 spring-boot-starter-logging组底,該依賴內容就是 Spring Boot 默認的日志框架 Logback+SLF4J丈积。而 spring-boot-starter-web 包含了spring-boot-starte筐骇,所以我們只需要引入web組件即可:
<pre class="prettyprint hljs xml" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
</pre>
默認配置:
默認情況下Spring Boot將日志輸出到控制臺,不會寫到日志文件江滨。如果要編寫除控制臺輸出之外的日志文件铛纬,則需在application.properties中設置logging.file或logging.path屬性
<pre class="prettyprint hljs delphi" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">`注:二者不能同時使用,如若同時使用唬滑,則只有l(wèi)ogging.file生效
logging.file=文件名
logging.path=日志文件路徑
logging.level.包名=指定包下的日志級別
logging.pattern.console=日志打印規(guī)則` </pre>
logging.file告唆,設置文件,可以是絕對路徑晶密,也可以是相對路徑擒悬。如:logging.file=my.log
logging.path,設置目錄稻艰,會在該目錄下創(chuàng)建spring.log文件茄螃,并寫入日志內容,如:logging.path=/var/log
注:二者不能同時使用连锯,如若同時使用,則只有l(wèi)ogging.file生效用狱,可以看到這種方式配置簡單运怖,但是能實現的功能也非常有限,如果想要更復雜的需求夏伊,就需要下面的定制化配置了摇展。
logback-spring.xml詳解
Spring Boot官方推薦優(yōu)先使用帶有 -spring
的文件名作為你的日志配置(如使用 logback-spring.xml
,而不是 logback.xml
)溺忧,命名為 logback-spring.xml
的日志配置文件咏连,將xml放至 src/main/resource
下面。
也可以使用自定義的名稱鲁森,比如logback-config.xml祟滴,只需要在application.properties文件中使用logging.config=classpath:logback-config.xml指定即可。
在講解log'back-spring.xml之前我們先來了解三個單詞: Logger, Appenders and Layouts(記錄器歌溉、附加器垄懂、布局):Logback基于三個主要類:Logger,Appender和Layout痛垛。這三種類型的組件協(xié)同工作草慧,使開發(fā)人員能夠根據消息類型和級別記錄消息,并在運行時控制這些消息的格式以及報告的位置匙头。首先給出一個基本的xml配置如下 :
<pre class="prettyprint hljs dust" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">`<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="chapters.configuration" level="INFO"/>
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>
</configuration>` </pre>
3.1:元素
logback.xml配置文件的基本結構可以描述為元素漫谷,包含零個或多個元素,后跟零個或多個元素蹂析,后跟最多一個元素(也可以沒有)舔示。下圖說明了這種基本結構:3.2:元素
元素只接受一個必需的name屬性碟婆,一個可選的level屬性和一個可選的additivity屬性,允許值為true或false斩郎。level屬性的值允許一個不區(qū)分大小寫的字符串值TRACE脑融,DEBUG,INFO缩宜,WARN肘迎,ERROR,ALL或OFF锻煌。特殊于大小寫不敏感的值INHERITED或其同義詞NULL將強制記錄器的級別從層次結構中的較高級別繼承妓布,元素可以包含零個或多個元素; 這樣引用的每個appender都被添加到指定的logger中,(注:additivity屬性下面詳說)宋梧,logger元素級別具有繼承性匣沼。
例1:示例中,僅為根記錄器分配了級別捂龄。此級別值DEBUG由其他記錄器X释涛,X.Y和X.Y.Z繼承
例2:所有記錄器都有一個指定的級別值。級別繼承不起作用
例3:記錄器root倦沧,X和X.Y.Z分別被分配了DEBUG唇撬,INFO和ERROR級別。Logger X.Y從其父X繼承其級別值展融。
例4:在示例4中窖认,記錄器root和X分別被分配了DEBUG和INFO級別。記錄器X.Y和X.Y.Z從其最近的父X繼承其級別值告希,該父級具有指定的級別扑浸。
3.3:元素
元素配置根記錄器。它支持單個屬性燕偶,即level屬性喝噪。它不允許任何其他屬性,因為additivity標志不適用于根記錄器杭跪。此外仙逻,由于根記錄器已被命名為“ROOT”,因此它也不允許使用name屬性涧尿。level屬性的值可以是不區(qū)分大小寫的字符串TRACE系奉,DEBUG,INFO姑廉,WARN缺亮,ERROR,ALL或OFF之一元素可以包含零個或多個元素; 這樣引用的每個appender都被添加到根記錄器中(注:additivity屬性下面詳說)。
3.4:元素
appender使用元素配置萌踱,該元素采用兩個必需屬性name和class葵礼。name屬性指定appender的名稱,而class屬性指定要實例化的appender類的完全限定名稱并鸵。元素可以包含零個或一個元素鸳粉,零個或多個元素以及零個或多個元素,下圖說明了常見的結構:
重要:在logback中园担,輸出目標稱為appender届谈,addAppender方法將appender添加到給定的記錄器logger。給定記錄器的每個啟用的日志記錄請求都將轉發(fā)到該記錄器中的所有appender以及層次結構中較高的appender弯汰。換句話說艰山,appender是從記錄器層次結構中附加地繼承的。例如咏闪,如果將控制臺appender添加到根記錄器曙搬,則所有啟用的日志記錄請求將至少在控制臺上打印。如果另外將文件追加器添加到記錄器(例如L)鸽嫂,則對L和L的子項啟用的記錄請求將打印在文件和控制臺上纵装。通過將記錄器的additivity標志設置為false,可以覆蓋此默認行為据某,以便不再添加appender累積搂擦。
Appender是一個接口,它有許多子接口和實現類哗脖,具體如下圖所示:
其中最重要的兩個Appender為:ConsoleAppender 、RollingFileAppender扳还。
3.4.1:ConsoleAppender
ConsoleAppender才避,如名稱所示,將日志輸出到控制臺上氨距。
3.4.2:RollingFileAppender
RollingFileAppender桑逝,是FileAppender的一個子類,擴展了FileAppender俏让,具有翻轉日志文件的功能楞遏。例如,RollingFileAppender 可以記錄到名為log.txt文件的文件首昔,并且一旦滿足某個條件寡喝,就將其日志記錄目標更改為另一個文件。
有兩個與RollingFileAppender交互的重要子組件勒奇。第一個RollingFileAppender子組件预鬓,即 RollingPolicy 負責執(zhí)行翻轉所需的操作。RollingFileAppender的第二個子組件赊颠,即 TriggeringPolicy 將確定是否以及何時發(fā)生翻轉格二。因此劈彪,RollingPolicy 負責什么和TriggeringPolicy 負責什么時候。
作為任何用途顶猜,RollingFileAppender 必須同時設置 RollingPolicy 和 TriggeringPolicy沧奴。但是,如果其 RollingPolicy 也實現了TriggeringPolicy 接口长窄,則只需要顯式指定前者滔吠。
3.4.3:滾動策略
TimeBasedRollingPolicy:可能是最受歡迎的滾動策略。它根據時間定義翻轉策略抄淑,例如按天或按月屠凶。TimeBasedRollingPolicy承擔滾動和觸發(fā)所述翻轉的責任。實際上肆资,TimeBasedTriggeringPolicy實現了RollingPolicy和TriggeringPolicy接口矗愧。
SizeAndTimeBasedRollingPolicy:有時您可能希望按日期歸檔文件,但同時限制每個日志文件的大小郑原,特別是如果后處理工具對日志文件施加大小限制唉韭。為了滿足此要求,logback 提供了 SizeAndTimeBasedRollingPolicy 犯犁,它是TimeBasedRollingPolicy的一個子類属愤,實現了基于時間和日志文件大小的翻滾策略。
3.5:元素
encoder中最重要就是pattern屬性酸役,它負責控制輸出日志的格式住诸,這里給出一個我自己寫的示例:
<pre class="prettyprint hljs xquery" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) --- [%15.15(%thread)] %cyan(%-40.40(%logger{40})) : %msg%n</pattern>
</pre>
使用后的輸出格式如下圖所示
其中:%d{yyyy-MM-dd HH:mm:ss.SSS}:日期
%-5level:日志級別
%highlight():顏色,info為藍色涣澡,warn為淺紅贱呐,error為加粗紅,debug為黑色
%thread:打印日志的線程
%15.15():如果記錄的線程字符長度小于15(第一個)則用空格在左側補齊,如果字符長度大于15(第二個),則從開頭開始截斷多余的字符
%logger:日志輸出的類名
%-40.40():如果記錄的logger字符長度小于40(第一個)則用空格在右側補齊,如果字符長度大于40(第二個),則從開頭開始截斷多余的字符
%cyan:顏色
%msg:日志輸出內容
%n:換行符
3.6:元素
filter中最重要的兩個過濾器為: LevelFilter入桂、ThresholdFilter
奄薇。
LevelFilter
根據精確的級別匹配過濾事件。如果事件的級別等于配置的級別抗愁,則篩選器接受或拒絕該事件馁蒂,具體取決于onMatch和onMismatch屬性的配置。例如下面配置將只打印INFO級別的日志蜘腌,其余的全部禁止打印輸出:
<pre class="prettyprint hljs dust" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><configuration> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>INFO</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> <encoder> <pattern> %-4relative [%thread] %-5level %logger{30} - %msg%n </pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="CONSOLE" /> </root> </configuration>
</pre>
ThresholdFilter
過濾低于指定閾值的事件沫屡。對于等于或高于閾值的事件,ThresholdFilter將在調用其decision()方法時響應NEUTRAL撮珠。但是谁鳍,將拒絕級別低于閾值的事件,例如下面的配置將拒絕所有低于INFO級別的日志,只輸出INFO以及以上級別的日志:
<pre class="prettyprint hljs dust" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><configuration> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>INFO</level> </filter> <encoder> <pattern> %-4relative [%thread] %-5level %logger{30} - %msg%n </pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="CONSOLE" /> </root> </configuration>
</pre>
四:詳細的logback-spring.xml示例:
以上介紹了xml中重要的幾個元素倘潜,下面將我配置的xml貼出來以供參考(實現了基于日期和大小翻滾的策略绷柒,以及經INFO和ERROR日志區(qū)分輸出,還有規(guī)范日志輸出格式等):
<pre class="prettyprint hljs dust" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">`<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) --- [%15.15(%thread)] %cyan(%-40.40(%logger{40})) : %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<appender name="info_log" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>logs/project_info.log</File>
<append>true</append>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>DENY</onMatch>
<onMismatch>ACCEPT</onMismatch>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logs/project_info.%d.%i.log</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>20GB</totalSizeCap>
<maxFileSize>10MB</maxFileSize>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%15.15(%thread)] %-40.40(%logger{40}) : %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<appender name="error_log" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>logs/project_error.log</File>
<append>true</append>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logs/project_error.%d.%i.log</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>20GB</totalSizeCap>
<maxFileSize>10MB</maxFileSize>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level --- [%15.15(%thread)] %-40.40(%logger{40}) : %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
<logger name="com.sailing.springbootmybatis" level="INFO">
<appender-ref ref="info_log" />
<appender-ref ref="error_log" />
</logger>
<logger name="com.sailing.springbootmybatis.mapper" level="DEBUG" additivity="false">
<appender-ref ref="info_log" />
<appender-ref ref="error_log" />
</logger>
<logger name="com.atomikos" level="INFO" additivity="false">
<appender-ref ref="info_log" />
<appender-ref ref="error_log" />
</logger>
</configuration>` </pre>
五:附加內容
5.1:這里再說下log日志輸出代碼涮因,一般有人可能在代碼中使用如下方式輸出:
<pre class="prettyprint hljs dart" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">Object entry = new SomeObject(); logger.debug("The entry is " + entry);
</pre>
5.2:上面看起來沒什么問題废睦,但是會存在構造消息參數的成本,即將entry轉換成字符串相加养泡。并且無論是否記錄消息嗜湃,都是如此,即:那怕日志級別為INFO澜掩,也會執(zhí)行括號里面的操作购披,但是日志不會輸出,下面是優(yōu)化后的寫法:
<pre class="prettyprint hljs dart" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">if(logger.isDebugEnabled()) { Object entry = new SomeObject(); logger.debug("The entry is " + entry); }
</pre>
5.3:5.2的寫法肩榕,首先對設置的日志級別進行了判斷刚陡,如果為debug模式,才進行參數的構造株汉,對第一種寫法進行了改善筐乳。不過還有最好的寫法,使用占位符:
<pre class="prettyprint hljs dart" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">Object entry = new SomeObject(); logger.debug("The entry is {}.", entry);
</pre>
只有在評估是否記錄之后乔妈,并且只有在決策是肯定的情況下蝙云,記錄器實現才會格式化消息并將“{}”對替換為條目的字符串值。換句話說路召,當禁用日志語句時勃刨,此表單不會產生參數構造的成本。
logback作者進行測試得出:第一種和第三種寫法將產生完全相同的輸出股淡。但是朵你,在禁用日志記錄語句的情況下,第三個變體將比第一個變體優(yōu)于至少30倍揣非。
如果有多個參數,寫法如下:
<pre class="prettyprint hljs css" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">logger.debug("The new entry is {}. It replaces {}.", entry, oldEntry);
</pre>
如果需要傳遞三個或更多參數躲因,則還可以使用Object []變體:
<pre class="prettyprint hljs dust" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">Object[] paramArray = {newVal, below, above}; logger.debug("Value {} was inserted between {} and {}.", paramArray);
</pre>
5.4:記錄日志的時候我們可能需要在文件中記錄下異常的堆棧信息早敬,經過測試,logger.error(e) 不會打印出堆棧信息大脉,正確的寫法是:
logger.error("程序異常, 詳細信息:{}", e.getLocalizedMessage() , e);