SpringBoot 日志新姿勢,你真的汉买,用對了嗎

前言

項目中日志系統(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配置文件的基本結構可以描述為元素漫谷,包含零個或多個元素,后跟零個或多個元素蹂析,后跟最多一個元素(也可以沒有)舔示。下圖說明了這種基本結構:
image.png

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繼承

image.png

例2:所有記錄器都有一個指定的級別值。級別繼承不起作用

image.png

例3:記錄器root倦沧,X和X.Y.Z分別被分配了DEBUG唇撬,INFO和ERROR級別。Logger X.Y從其父X繼承其級別值展融。

image.png

例4:在示例4中窖认,記錄器root和X分別被分配了DEBUG和INFO級別。記錄器X.Y和X.Y.Z從其最近的父X繼承其級別值告希,該父級具有指定的級別扑浸。

image.png

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類的完全限定名稱并鸵。元素可以包含零個或一個元素鸳粉,零個或多個元素以及零個或多個元素,下圖說明了常見的結構:

image.png

重要:在logback中园担,輸出目標稱為appender届谈,addAppender方法將appender添加到給定的記錄器logger。給定記錄器的每個啟用的日志記錄請求都將轉發(fā)到該記錄器中的所有appender以及層次結構中較高的appender弯汰。換句話說艰山,appender是從記錄器層次結構中附加地繼承的。例如咏闪,如果將控制臺appender添加到根記錄器曙搬,則所有啟用的日志記錄請求將至少在控制臺上打印。如果另外將文件追加器添加到記錄器(例如L)鸽嫂,則對L和L的子項啟用的記錄請求將打印在文件和控制臺上纵装。通過將記錄器的additivity標志設置為false,可以覆蓋此默認行為据某,以便不再添加appender累積搂擦。

Appender是一個接口,它有許多子接口和實現類哗脖,具體如下圖所示:

image.png

其中最重要的兩個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>

使用后的輸出格式如下圖所示

image.png

其中:%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);
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末搞监,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子镰矿,更是在濱河造成了極大的恐慌琐驴,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件敛助,死亡現場離奇詭異缚柳,居然都是意外死亡,警方通過查閱死者的電腦和手機译蒂,發(fā)現死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進店門牢酵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來悬包,“玉大人,你說我怎么就攤上這事馍乙〔冀” “怎么了?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵丝格,是天一觀的道長撑瞧。 經常有香客問我,道長显蝌,這世上最難降的妖魔是什么预伺? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮琅束,結果婚禮上扭屁,老公的妹妹穿的比我還像新娘。我一直安慰自己涩禀,他們只是感情好料滥,可當我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著艾船,像睡著了一般葵腹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上屿岂,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天践宴,我揣著相機與錄音,去河邊找鬼爷怀。 笑死阻肩,一個胖子當著我的面吹牛,可吹牛的內容都是我干的运授。 我是一名探鬼主播烤惊,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吁朦!你這毒婦竟也來了柒室?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤逗宜,失蹤者是張志新(化名)和其女友劉穎雄右,沒想到半個月后空骚,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡擂仍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年囤屹,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片防楷。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡牺丙,死狀恐怖,靈堂內的尸體忽然破棺而出复局,到底是詐尸還是另有隱情冲簿,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布亿昏,位于F島的核電站峦剔,受9級特大地震影響,放射性物質發(fā)生泄漏角钩。R本人自食惡果不足惜吝沫,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望递礼。 院中可真熱鬧惨险,春花似錦、人聲如沸脊髓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽将硝。三九已至恭朗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間依疼,已是汗流浹背痰腮。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留律罢,地道東北人膀值。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像误辑,于是被迫代替她去往敵國和親沧踏。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,630評論 2 359

推薦閱讀更多精彩內容