SpringBoot中日志的使用log4j

SpringBoot中日志的使用log4j

项目中日志系统是必不可少的,目前比较流行的日志框架有 log4jlogback 等,这两个框架的作者是同一个

人,Logback 旨在作为流行的 log4j 项目的后续版本,从而恢复 log4j 离开的位置。

另外 slf4j(Simple Logging Facade for Java) 则是一个日志门面框架,提供了日志系统中常用的接口,

logbacklog4j 则对 slf4j 进行了实现。

官网:https://logging.apache.org/log4j/1.x/

SpringBoot 默认就是使用 SLF4J 作为日志门面,logback 作为日志实现来记录日志。

Spring Boot在所有内部日志中使用Commons Logging,但也保留默认配置对常用日志的支持,如:

Java Util Logging, Log4J, Log4J2, SLF4J, Logback

每种 Logger 都可以通过配置使用控制台或者文件输出日志内容。

默认情况下,如果您使用 Starters,会使用 Logback 来实现日志管理。

我们没必要纠结使用默认的 Logback 还是 Log4j,直接用 Slf4j 即可。至于这个日志具体是如何写到控制台或

者文件的,则由Spring Boot项目中引入了什么具体的日志框架决定,默认情况下就是 Logback

我们本文将讲述如何在spring boot 中应用 logback+slf4j 实现日志的记录。

1、各个日志之间的关系

1.1 spring-boot-starter-logging

<dependency><artifactId>spring-boot-starter-logging</artifactId><groupId>org.springframework.boot</groupId>
</dependency>

在这里插入图片描述

org.springframework.boot的依赖:

<dependencies><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.6</version><scope>compile</scope></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-to-slf4j</artifactId><version>2.14.1</version><scope>compile</scope></dependency><dependency><groupId>org.slf4j</groupId><artifactId>jul-to-slf4j</artifactId><version>1.7.32</version><scope>compile</scope></dependency>
</dependencies>

1.2 spring-boot-starter

在这里插入图片描述

boot-starter-web 启动器当中,会依赖中我们所使用环境的一些 jar包的信息,里面就包含了slf4j 日志门面和

logback的日志实现。

1.3 总结

1、SpringBoot底层默认使用 logback 作为日志实现

2、使用了 SLF4J 作为日志门面

3、将JUL也转换成 slf4j

4、在使用Springboot框架之后,其内部所有的日志实现都通过桥接器转换成slf4j日志门面进行统一的管理,最终

交给logback日志实现框架进行日志输出。

2、为什么使用logback

  • Logback 是log4j 框架的作者开发的新一代日志框架,它效率更高、能够适应诸多的运行环境,同时天然支持

    SLF4J。

  • Logback的定制性更加灵活,同时也是spring boot的内置日志框架。

3、项目编写

3.1 添加依赖

maven依赖中添加了spring-boot-starter-logging

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId>
</dependency>

但是呢,实际开发中我们不需要直接添加该依赖,你会发现spring-boot-starter其中包含了spring-boot-

starter-logging,该依赖内容就是 Spring Boot 默认的日志框架Logback+SLF4J。而spring-boot-starter-

web包含了spring-boot-starte,所以我们只需要引入web组件即可:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

完整 pom.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.6</version><relativePath/></parent><groupId>com.log</groupId><artifactId>spring-boot-log</artifactId><version>0.0.1-SNAPSHOT</version><name>spring-boot-log</name><description>spring-boot-log</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

3.2 Controller编写

package com.log.controller;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;/*** @author zhangshixing* @date 2021年11月04日 17:42*/
// 也可以使用@Slf4j注解输出日志(建议)
@RestController
public class DemoController {/*** 声明日志记录器对象(slf4j包)*/public static final Logger logger = LoggerFactory.getLogger(DemoController.class);@GetMapping("get")public void test() {logger.error("error");logger.warn("warn");logger.info("info");logger.debug("debug");logger.trace("trace");}
}

3.3 测试类

package com.log;import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
class SpringBootLogApplicationTests {// 声明日志记录器对象(slf4j包)public static final Logger logger = LoggerFactory.getLogger(SpringBootLogApplicationTests.class);@Testvoid contextLoads() {logger.error("error");logger.warn("warn");logger.info("info");logger.debug("debug");logger.trace("trace");}
}

输出:

2023-11-18 10:17:19.458 ERROR 1596 --- [           main] com.log.SpringBootLogApplicationTests    : error
2023-11-18 10:17:19.458  WARN 1596 --- [           main] com.log.SpringBootLogApplicationTests    : warn
2023-11-18 10:17:19.458  INFO 1596 --- [           main] com.log.SpringBootLogApplicationTests    : info

因为我们没有提供任何配置文件,因此默认的日志级别就是info,所以 debug 和 trace 不会输出。

4、基本配置

Springboot 支持对日志进行具体的配置,可以直接在 application.properties 配置文件中简单定义,也可以

导入具体日志实现的配置文件。

4.1 默认配置

4.1.1 日志输出文件配置

默认情况下Spring Boot将日志输出到控制台,不会写到日志文件。

如果要编写除控制台输出之外的日志文件,则需在

application.properties中设置logging.file.namelogging.file.path属性。

注:二者不能同时使用,如若同时使用,则只有 logging.file.name 生效

  • logging.file.name=文件名

  • logging.file.path=日志文件路径

  • logging.level.包名=指定包下的日志级别

  • logging.pattern.console=日志打印规则

logging.file.name 设置文件,可以是绝对路径,也可以是相对路径。如:logging.file.name=my.log

logging.file.path设置目录,会在该目录下创建spring.log文件,并写入日志内容,如:

logging.file.path=/var/log

注:二者不能同时使用,如若同时使用,则只有logging.file.name生效,可以看到这种方式配置简单,但

是能实现的功能也非常有限,如果想要更复杂的需求,就需要下面的定制化配置了。

我们设置:

logging.file.path=D:

会生成:

在这里插入图片描述

我们设置:

logging.file.path=D:
logging.file.name=D:\\my_log.txt

在这里插入图片描述

4.1.2 指定日志输出的级别、格式
# 自定义logger对象的日志级别,com.log.controller是自定义logger对象的名称,也就是包名
logging.level.com.log.controller = trace
# 指定控制台输出消息格式
# 格式配置请参考:https://logging.apache.org/log4j/2.x/manual/layouts.html
logging.pattern.console = [%-5level] %d{yyyy-MM-dd HH:mm:ss} %c [%thread] %m%n

发送请求:http://127.0.0.1:8080/get

输出:

[ERROR] 2023-11-18 21:24:04 com.log.controller.DemoController [http-nio-8080-exec-1] error
[WARN ] 2023-11-18 21:24:04 com.log.controller.DemoController [http-nio-8080-exec-1] warn
[INFO ] 2023-11-18 21:24:04 com.log.controller.DemoController [http-nio-8080-exec-1] info
[DEBUG] 2023-11-18 21:24:04 com.log.controller.DemoController [http-nio-8080-exec-1] debug
[TRACE] 2023-11-18 21:24:04 com.log.controller.DemoController [http-nio-8080-exec-1] trace
4.1.3 指定日志文件消息格式
# 指定日志文件消息格式
logging.pattern.file=[%-5level] %d{yyyy-MM-dd HH:mm:ss} %c [%thread] %m%n

输出:

在这里插入图片描述

SpringBoot提供的默认配置文件无法进行复杂的配置,比如所有日志都放到一个文件当中,不易于后期维护和管

理,希望是按照一定的规则进行滚动拆分,比如文件大小,时间等。通过简单的SpringBoot提供的配置文件还不

够,通常在企业开发中会导入具体某个日志实现相应的配置文件。

给类路径下放上每个日志框架自己的配置文件,SpringBoot就不使用默认配置的了:

日志框架配置文件
Logbacklogback-spring.xml、logback.xml
Log4j2log4j2-spring.xml、log4j2.xml
JULlogging.properties

4.2 logback-spring.xml说明

Spring Boot 官方推荐优先使用带有 -spring 的文件名作为你的日志配置(如使用logback-spring.xml,而不

logback.xml),命名为logback-spring.xml的日志配置文件,将xml放至src/main/resource下面。

也可以使用自定义的名称,比如logback-config.xml,只需要在application.properties文件中使用

logging.config=classpath:logback-config.xml指定即可。

对于 logback 配置文件,logback-spring.xmllogback.xml 都能够被加载识别,增加了 -spring 的配置

文件会被 SpringBoot 框架解析,而不是由 logback 解析。

被 SpringBoot 框架解析的文件,只需修改 SpringBoot 的全局参数,就能对配置文件进行灵活调整,而不需要再

修改 logback 提供的核心配置文件了。

4.3 Logback架构

在讲解logback-spring.xml之前我们先来了解三个单词:Logger(记录器),Appenders(附加器) 和

Layouts(布局)。

Logback 的架构主要由三个核心组件组成:Logger、Appender 和 Layout。其中,Logger 用于记录 Log,

Appender 用于将 Log 输出到控制台或文件,Layout 用于定义 Log 输出格式。

这三种类型的组件协同工作,使开发人员能够根据消息类型和级别记录消息,并在运行时控制这些消息的格式以及

报告的位置。下面简要介绍一下这三个概念。

4.3.1 Logger

Logger 相当于一个记录器,用于产生 Log。Logger 有一个与之关联的 Log Level,表示记录 Log 要记录的最小等

级。Logger 可以选择是否记录它接收到的 Log,如果记录的 Log Level 低于 Logger 的 Log Level 则不记录。多个

Logger 可以形成一颗 Logger 的层次结构。

4.3.2 Appender

Appender 用于配置 Log 输出的目的地。Log 可以输出到控制台,文件,远程服务器等等。每个 Appender 都有

一个 Layout,用于格式化 Log 输出。一个 Logger 可以由多个 Appender 处理 Log 事件,例如,一个 Logger 可

以将所有 Error Level 的 Log 信息输出到一个文件中,同时将其他 Level 的 Log 输出到控制台。

4.3.3 Layout

Layout 用于格式化 Log 的输出方式。Layout 的作用是对 Log 进行格式化,然后由 Appender 输出。在 Layout

中可以定义 Log 的输出格式,比如时间,线程名称,Log Level 和 Log 的正文内容等。

4.3.4 Logback 配置文件

Logback 的配置文件使用 XML 格式编写,一般命名为 logback.xml 。配置文件中包括了 Logger、Appender 和

Encoder 等标签。下面是一个基本的 xml 配置文件的示例:

<configuration><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><!-- encoders are assigned the typech.qos.logback.classic.encoder.PatternLayoutEncoder by default --><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><logger name="chapters.configuration" level="INFO"/><!-- Strictly speaking, the level attribute is not necessary since --><!-- the level of the root level is set to DEBUG by default.       --><root level="DEBUG">          <appender-ref ref="STDOUT" /></root>  </configuration>

上面示例中,定义了一个名为 STDOUT 的 Appender,它是 ConsoleAppender 类型,用于将日志信息输出到控制

台上。同时定义了一个根 Logger,日志级别为 DEBUG,并将日志信息输出到 STDOUT Appender 中。Encoder

标签用于定义日志信息的输出格式。

<?xml version="1.0" encoding="UTF-8" ?>
<configuration><!-- 配置集中管理属性作用:如果其他标签要使用,可以直接通过表达式来引用:${property的name值}--><!-- 1.配置日志的输出格式,name:自定义名称  value:具体格式值 --><property name="pattern" value="[%-5level]  %d{yyyy-MM-dd HH:mm:ss}  %c  %M  %L  %thread  %m  %n"/><!-- 2.配置控制台输出的appender, name:自定义appender名称  class:appender类型--><appender name="myConsole" class="ch.qos.logback.core.ConsoleAppender"><!-- 2.1控制输出流对象,默认System.out控制台黑色字体,修改为System.err红色字体 --><target>System.err</target><!-- 2.2日志消息的格式 --><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${pattern}</pattern></encoder></appender><!-- 3.自定义logger 对象,additivity:是否继承父元素RootLogger的属性配置--><logger name="com.ahead" level="info" additivity="false"><appender-ref ref="myConsole" /></logger>
</configuration>

上传了具体日志实现的配置文件后,默认的SpringBoot配置信息就会作废。

4.3 <configuration>元素

logback.xml配置文件的基本结构可以描述为<configuration>元素,包含零个或多个<appender>元素,后跟

零个或多个<logger>元素,后跟最多一个<root>元素(也可以没有)。

下图说明了这种基本结构:

在这里插入图片描述

4.4 <logger>元素

<logger>元素只接受一个必需的name属性,一个可选的level属性和一个可选的additivity属性,允许值为

true或false。level属性的值允许一个不区分大小写的字符串值TRACE,DEBUG,INFO,WARN,ERROR,ALL或OFF

特殊于大小写不敏感的值INHERITED或其同义词NULL将强制记录器的级别从层次结构中的较高级别继承。

<logger>元素可以包含零个或多个<appender-ref>元素,这样引用的每个appender都被添加到指定的logger

中,logger元素级别具有继承性。

例1:示例中,仅为根记录器分配了级别。 此级别值DEBUG由其他记录器X,X.Y和X.Y.Z继承

Logger nameAssigned levelEffective level
rootDEBUGDEBUG
XnoneDEBUG
X.YnoneDEBUG
X.Y.ZnoneDEBUG

例2:所有记录器都有一个指定的级别值。 级别继承不起作用

Logger nameAssigned levelEffective level
rootERRORERROR
XINFOINFO
X.YDEBUGDEBUG
X.Y.ZWARNWARN

例3:记录器root,X和X.Y.Z分别被分配了DEBUG,INFO和ERROR级别。 Logger X.Y从其父X继承其级别值。

Logger nameAssigned levelEffective level
rootDEBUGDEBUG
XINFOINFO
X.YnoneINFO
X.Y.ZERRORERROR

例4:在示例4中,记录器root和X分别被分配了DEBUG和INFO级别。 记录器X.Y和X.Y.Z从其最近的父X继承其级别

值,该父级具有指定的级别。

Logger nameAssigned levelEffective level
rootDEBUGDEBUG
XINFOINFO
X.YnoneINFO
X.Y.ZnoneINFO

4.5 <root>元素

<root>元素配置根记录器,它支持单个属性,即 level 属性。它不允许任何其他属性,因为 additivity 标志不适

用于根记录器。此外,由于根记录器已被命名为 ROOT,因此它也不允许使用 name 属性。

level 属性的值可以是不区分大小写的字符串 TRACE, DEBUG, INFO, WARN, ERROR, ALL, OFF之一。

<root>元素可以包含零个或多个<appender-ref>元素,这样引用的每个 appender 都被添加到根记录器中。

4.6 <appender>元素

appender使用<appender>元素配置,该元素采用两个必需属性 name 和 class。name 属性指定 appender 的名

称,而 class 属性指定要实例化的 appender 类的完全限定名称。

<appender>元素可以包含零个或一个<layout>元素,零个或多个<encoder>元素以及零个或多个<filter>

素,下图说明了常见的结构:

在这里插入图片描述

重要:在logback中,输出目标称为appenderaddAppender方法将appender添加到给定的记录器logger。给

定记录器的每个启用的日志记录请求都将转发到该记录器中的所有appender以及层次结构中较高的appender

换句话说,appender是从记录器层次结构中附加地继承的。

例如,如果将控制台appender添加到根记录器,则所有启用的日志记录请求将至少在控制台上打印。如果另外将

文件追加器添加到记录器(例如L),则对L和L的子项启用的记录请求将打印在文件和控制台上。通过将记录器的

additivity标志设置为false,可以覆盖此默认行为,以便不再添加appender累积。

Appender是一个接口,它有许多子接口和实现类,具体如下图所示:

在这里插入图片描述

其中最重要的两个Appender为:ConsoleAppenderRollingFileAppender

4.6.1 ConsoleAppender

ConsoleAppender,如名称所示,将日志输出到控制台上。

4.6.2 RollingFileAppender

RollingFileAppenderFileAppender的一个子类,扩展了FileAppender,具有翻转日志文件的功能。例

RollingFileAppender可以记录到名为log.txt文件的文件,并且一旦满足某个条件,就将其日志记录目标

更改为另一个文件。

有两个与RollingFileAppender交互的重要子组件。第一个RollingFileAppender子组件,即RollingPolicy

负责执行翻转所需的操作。RollingFileAppender的第二个子组件,即TriggeringPolicy将确定是否以及何时

发生翻转。因此,RollingPolicy负责什么和TriggeringPolicy负责什么时候。

作为任何用途,RollingFileAppender必须同时设置RollingPolicyTriggeringPolicy。但是,如果其

RollingPolicy也实现了TriggeringPolicy接口,则只需要显式指定前者。

滚动策略:

  • TimeBasedRollingPolicy:可能是最受欢迎的滚动策略。它根据时间定义翻转策略,例如按天或按月。

    TimeBasedRollingPolicy承担滚动和触发所述翻转的责任。实际上,TimeBasedTriggeringPolicy

    现了RollingPolicyTriggeringPolicy接口。

  • SizeAndTimeBasedRollingPolicy:有时您可能希望按日期归档文件,但同时限制每个日志文件的大小,特

    别是如果后处理工具对日志文件施加大小限制。为了满足此要求,logback 提供了

    SizeAndTimeBasedRollingPolicy,它是TimeBasedRollingPolicy的一个子类,实现了基于时间和日志

    文件大小的翻滚策略。

4.6.3 <encoder>元素

encoder中最重要就是pattern属性,它负责控制输出日志的格式,这里给出一个我自己写的示例:

<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) --- [%15.15(%thread)] %cyan(%-40.40(%logger{40})) : %msg%n</pattern>

其中:

# 日期
%d{yyyy-MM-dd HH:mm:ss.SSS}# 日志级别
%-5level# 颜色,info为蓝色,warn为浅红,error为加粗红,debug为黑色
%highlight()# 打印日志的线程
%thread# 如果记录的线程字符长度小于15(第一个)则用空格在左侧补齐,如果字符长度大于15(第二个),则从开头开始截断多余的字符
%15.15()# 颜色
%cyan# 日志输出的类名
# 表示logger名字最长40个字符,否则按照句点分割。
%logger{40}# 如果记录的logger字符长度小于40(第一个)则用空格在右侧补齐,如果字符长度大于40(第二个),则从开头开始截断多余的字符
%-40.40()# 日志输出内容
%msg# 换行符
%n

格式配置请参考:https://logging.apache.org/log4j/2.x/manual/layouts.html

4.6.4 <filter>元素

filter中最重要的两个过滤器为:LevelFilterThresholdFilter

LevelFilter根据精确的级别匹配过滤事件。如果事件的级别等于配置的级别,则筛选器接受或拒绝该事件,具

体取决于onMatchonMismatch属性的配置。例如下面配置将只打印INFO级别的日志,其余的全部禁止打印输

出:

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

ThresholdFilter过滤低于指定阈值的事件。对于等于或高于阈值的事件,ThresholdFilter将在调用其

decision()方法时响应NEUTRAL

但是,将拒绝级别低于阈值的事件,例如下面的配置将拒绝所有低于INFO级别的日志,只输出INFO以及以上级别

的日志:

<configuration><appender name="CONSOLE"class="ch.qos.logback.core.ConsoleAppender"><!-- deny all events with a level below INFO, that is TRACE and DEBUG --><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>

5、详细的logback-spring.xml示例1

<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL, 如果设置为WARN, 则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时, 配置文档如果发生改变, 将会被重新加载, 默认值为true -->
<!-- scanPeriod:设置监测配置文档是否有修改的时间间隔, 如果没有给出时间单位, 默认单位是毫秒, 当scan为true时, 此属性生效, 默认的时间间隔为1分钟 -->
<!-- debug:当此属性设置为true时, 将打印出logback内部日志信息, 实时查看logback运行状态, 默认值为false -->
<configuration scan="true" scanPeriod="10 seconds"><contextName>spring-boot-log</contextName><!-- 彩色日志 --><!-- 彩色日志依赖的渲染类 --><conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" /><conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" /><conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" /><!-- 变量定义begin--><!-- 使用spring.application.name设置的名字 --><springProperty scope="context" name="APP_NAME" source="spring.application.name"/><!-- 定义日志存储的路径,建议不要配置相对路径 --><property name="FILE_DIR" value="D:\\logs\\${APP_NAME}" /><!-- 设置全局属性,通过获取变量的形式${APP_NAME} --><property name="ROLL_FILE_DIR" value="D:\\logs\\${APP_NAME}" /><!-- 彩色日志格式 --><property name="CONSOLE_LOG_FORMAT" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/><!--默认日志格式: 时间日期 -> 日志级别 -> 线程ID -> 分隔符 -> 线程名 -> Logger名(通常对应的是类名) -> 日志内容 --><!-- 格式化输出:%date表示日期, %thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息, %n是换行符--><property name="LOG_FORMAT" value="%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" /><!-- 变量定义end--><!-- 日志输出方式定义 begin --><!--1、输出到控制台--><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><!--此日志appender是为开发使用, 只配置最低级别, 控制台输出的日志级别是大于或等于此级别的日志信息--><!-- 日志级别过滤DEBUG以下 --><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>DEBUG</level></filter><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!-- 如果是开发环境,使用默认的消息格式 --><springProfile name="dev"><pattern>%d{yyyy-MM-dd HH:mm:ss} [%-5level]  %m%n</pattern></springProfile><!-- 如果是生产环境,使用简单的消息格式输出消息 --><springProfile name="pro"><!-- 按照上面配置的LOG_FORMAT来打印日志 --><pattern>${CONSOLE_LOG_FORMAT}</pattern><!-- 设置字符集 --><charset>UTF-8</charset></springProfile></encoder></appender><!-- 2、输出到文件  --><!-- 输出到文件, 这种方式是单个日志文件保存, 文件会不停的增大, 除非手动删除 --><appender name="FILE" class="ch.qos.logback.core.FileAppender"><file>${FILE_DIR}\\spring-log.log</file><append>true</append><encoder><!-- 按照上面配置的LOG_FORMAT来打印日志 --><pattern>${LOG_FORMAT}</pattern></encoder></appender><!-- 3、滚动输出到文件  --><!-- 滚动日志输出,每天生成一个日志文件,保存30天的日志文件,FILE用来切分文件的 --><appender name="FILE_ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- 当前记录的日志文档完整路径 --><file>${ROLL_FILE_DIR}\\spring-log-rolling.log</file><!--日志文档输出格式--><encoder><!-- 按照上面配置的LOG_FORMAT来打印日志 --><pattern>${LOG_FORMAT}</pattern><!-- 此处设置字符集 --><charset>UTF-8</charset></encoder><!--日志滚动策略,按照时间、按大小滚动记录--><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>${ROLL_FILE_DIR}\\spring-log-rolling.%d{yyyy-MM-dd}.%i.log</fileNamePattern><!-- 只保留30天的日志(非持续运行情况下,30天外不会清理)--><maxHistory>30</maxHistory><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><!-- 日志文件的最大大小 --><maxFileSize>100MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!-- 应对服务非持续偶尔运行,日志清理机制无法触发而导致日志得不到清理的情况--><!-- 超出删除老文件 --><totalSizeCap>500MB</totalSizeCap><cleanHistoryOnStart>true</cleanHistoryOnStart></rollingPolicy><!-- 以上的配置是当日志文件的大小达到100MB时,就新建一个日志文件,当滚动日志所占控件总和超过500MB时,就将最老的日志文件删除掉最多保存30天的日志文件,超过30天也会将最老的日志文件删除需要注意的是,如果日志文件比较大,如果1个小时就创建了5个日志文件,每个100MB,那下一个小时重新生成的日志文件会将上一个小时的日志文件覆盖掉,而且由于日志文件大小总和超过500MB,所以实际无法保存30天的日志文件,所以需要根据实际项目确定以上参数该怎么设置--></appender><!-- 日志输出方式定义 end --><!-- <logger>用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender><logger>仅有一个name属性,一个可选的level和一个可选的addtivity属性name:用来指定受此logger约束的某一个包或者具体的某一个类level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别如果未设置此属性,那么当前logger将会继承上级的级别addtivity:是否向上级logger传递打印信息,默认是true--><!--root节点是必选节点,用来指定通用的日志输出级别,只有一个level属性level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF不能设置为INHERITED或者同义词NULL,默认是DEBUG可以包含零个或多个元素,标识这个appender将会添加到这个logger--><!-- 日志输出级别 begin--><!-- cloud环境下,去掉nacos的日志打印信息 --><!--<logger name="com.alibaba.nacos" level="OFF" addtivity="false"> </logger>--><!-- 打印info级别的信息 --><!--<root level="INFO"><appender-ref ref="FILE"/></root>--><!-- 控制整个项目的日志级别 --><root level="info"><!--使用info级别输出日志到控制台、文件及滚动文件--><!--采用上面定义的日志输出方式确定本项目究竟将日志输出到什么地方--><!--输出到终端--><appender-ref ref="CONSOLE" /><!--输出到文件--><appender-ref ref="FILE" /><!--输出到文件,滚动输出,避免单个文件过大,通常采用这种方式--><appender-ref ref="FILE_ROLLING" /></root><!-- 日志输出级别 end--><!--如果采用root定义,则是所有包的日志都会打印,如果要控制只需要当前的包,则使用下面的logger的标签定义name表示是打印哪个包下面的level表示这个包下面什么级别的日志打印出来--><!--<logger name="com.log.controller" level="debug"><appender-ref ref="CONSOLE"/><appender-ref ref="FILE"/><appender-ref ref="FILE_ROLLING" /></logger>--><!-- 本地环境输出至控制台 --><!-- 如果使用了 springProfile, 需要将logback.xml名称改为logback-spring.xml--><!--<springProfile name="dev"><root level="DEBUG"><appender-ref ref="CONSOLE" /><appender-ref ref="FILE" /></root></springProfile>-->
</configuration>

使用是需要设置:

spring.profiles.active = dev/pro

6、详细的logback-spring.xml示例2

<?xml version="1.0" encoding="UTF-8"?>  <!-- 从高到地低 OFF 、 FATAL 、 ERROR 、 WARN 、 INFO 、 DEBUG 、 TRACE 、 ALL -->  
<!-- 日志输出规则  根据当前ROOT 级别,日志输出时,级别高于root默认的级别时  会输出 -->  
<!-- 以下  每个配置的 filter 是过滤掉输出文件里面,会出现高级别文件,依然出现低级别的日志信息,通过filter 过滤只记录本级别的日志-->  <!-- 属性描述 scan:性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。   debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->  
<configuration scan="true" scanPeriod="60 seconds" debug="false">  <!-- 定义日志文件 输入位置 -->  <property name="log_dir" value="/customize/logs" />  <!-- 日志最大的历史 30天 -->  <property name="maxHistory" value="30"/>  <!-- ConsoleAppender 控制台输出日志 -->  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">  <!-- 对日志进行格式化 -->  <encoder>  <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger -%msg%n</pattern>  </encoder>  </appender>  <!-- ERROR级别日志 -->  <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 RollingFileAppender-->  <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">  <!-- 过滤器,只记录WARN级别的日志 -->  <filter class="ch.qos.logback.classic.filter.LevelFilter">  <level>ERROR</level>  <onMatch>ACCEPT</onMatch>  <onMismatch>DENY</onMismatch>  </filter>  <!-- 最常用的滚动策略,它根据时间来制定滚动策略.既负责滚动也负责出发滚动 -->  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  <!--日志输出位置  可相对、和绝对路径 -->  <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/error-log.log</fileNamePattern>  <!-- 可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件假设设置每个月滚动,且<maxHistory>是6,  则只保存最近6个月的文件,删除之前的旧文件。注意,删除旧文件是,那些为了归档而创建的目录也会被删除-->  <maxHistory>${maxHistory}</maxHistory>  </rollingPolicy>  <!-- 按照固定窗口模式生成日志文件,当文件大于20MB时,生成新的日志文件。窗口大小是1到3,当保存了3个归档文件后,将覆盖最早的日志。   <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">     <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/.log.zip</fileNamePattern>     <minIndex>1</minIndex>     <maxIndex>3</maxIndex>     </rollingPolicy>   -->  <!-- 查看当前活动文件的大小,如果超过指定大小会告知RollingFileAppender 触发当前活动文件滚动   <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">     <maxFileSize>5MB</maxFileSize>     </triggeringPolicy>   -->  <encoder>  <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>  </encoder>  </appender>  <!-- WARN级别日志 appender -->  <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">  <!-- 过滤器,只记录WARN级别的日志 -->  <filter class="ch.qos.logback.classic.filter.LevelFilter">  <level>WARN</level>  <onMatch>ACCEPT</onMatch>  <onMismatch>DENY</onMismatch>  </filter>  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  <!-- 按天回滚 daily -->  <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/warn-log.log  </fileNamePattern>  <!-- 日志最大的历史 60天 -->  <maxHistory>${maxHistory}</maxHistory>  </rollingPolicy>  <encoder>  <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>  </encoder>  </appender>  <!-- INFO级别日志 appender -->  <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">  <!-- 过滤器,只记录INFO级别的日志 -->  <filter class="ch.qos.logback.classic.filter.LevelFilter">  <level>INFO</level>  <onMatch>ACCEPT</onMatch>  <onMismatch>DENY</onMismatch>  </filter>  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  <!-- 按天回滚 daily -->  <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/info-log.log  </fileNamePattern>  <!-- 日志最大的历史 60天 -->  <maxHistory>${maxHistory}</maxHistory>  </rollingPolicy>  <encoder>  <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>  </encoder>  </appender>  <!-- DEBUG级别日志 appender -->  <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">  <!-- 过滤器,只记录DEBUG级别的日志 -->  <filter class="ch.qos.logback.classic.filter.LevelFilter">  <level>DEBUG</level>  <onMatch>ACCEPT</onMatch>  <onMismatch>DENY</onMismatch>  </filter>  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  <!-- 按天回滚 daily -->  <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/debug-log.log  </fileNamePattern>  <!-- 日志最大的历史 60天 -->  <maxHistory>${maxHistory}</maxHistory>  </rollingPolicy>  <encoder>  <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>  </encoder>  </appender>  <!-- TRACE级别日志 appender -->  <appender name="TRACE" class="ch.qos.logback.core.rolling.RollingFileAppender">  <!-- 过滤器,只记录ERROR级别的日志 -->  <filter class="ch.qos.logback.classic.filter.LevelFilter">  <level>TRACE</level>  <onMatch>ACCEPT</onMatch>  <onMismatch>DENY</onMismatch>  </filter>  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  <!-- 按天回滚 daily -->  <fileNamePattern>${log_dir}/%d{yyyy-MM-dd}/trace-log.log  </fileNamePattern>  <!-- 日志最大的历史 60天 -->  <maxHistory>${maxHistory}</maxHistory>  </rollingPolicy>  <encoder>  <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>  </encoder>  </appender>  <logger name="java.sql.PreparedStatement" value="DEBUG" />    <logger name="java.sql.Connection" value="DEBUG" />    <logger name="java.sql.Statement" value="DEBUG" />    <logger name="com.ibatis" value="DEBUG" />    <logger name="com.ibatis.common.jdbc.SimpleDataSource" value="DEBUG" />    <logger name="com.ibatis.common.jdbc.ScriptRunner" level="DEBUG"/>    <logger name="com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate" value="DEBUG" />    <!-- root级别   DEBUG -->  <root level="debug">  <!-- 控制台输出 -->  <appender-ref ref="STDOUT" />  <!-- 文件输出 -->  <appender-ref ref="ERROR" />  <appender-ref ref="INFO" />  <appender-ref ref="WARN" />  <appender-ref ref="DEBUG" />  <appender-ref ref="TRACE" />  </root>  
</configuration>  

7、详细的logback-spring.xml示例3

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true"><!-- appender是configuration的子节点,是负责写日志的组件。 --><!-- ConsoleAppender:把日志输出到控制台 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><!-- 默认情况下,每个日志事件都会立即刷新到基础输出流。 这种默认方法更安全,因为如果应用程序在没有正确关闭appender的情况下退出,则日志事件不会丢失。但是,为了显着增加日志记录吞吐量,您可能希望将immediateFlush属性设置为false --><!--<immediateFlush>true</immediateFlush>--><encoder><!-- %37():如果字符没有37个字符长度,则左侧用空格补齐 --><!-- %-37():如果字符没有37个字符长度,则右侧用空格补齐 --><!-- %15.15():如果记录的线程字符长度小于15(第一个)则用空格在左侧补齐,如果字符长度大于15(第二个),则从开头开始截断多余的字符 --><!-- %-40.40():如果记录的logger字符长度小于40(第一个)则用空格在右侧补齐,如果字符长度大于40(第二个),则从开头开始截断多余的字符 --><!-- %msg:日志打印详情 --><!-- %n:换行符 --><!-- %highlight():转换说明符以粗体红色显示其级别为ERROR的事件,红色为WARN,BLUE为INFO,以及其他级别的默认颜色。 --><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) --- [%15.15(%thread)] %cyan(%-40.40(%logger{40})) : %msg%n</pattern><!-- 控制台也要使用UTF-8,不要使用GBK,否则会中文乱码 --><charset>UTF-8</charset></encoder></appender><!-- info 日志--><!-- RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 --><!-- 以下的大概意思是:1.先按日期存日志,日期变了,将前一天的日志文件名重命名为XXX%日期%索引,新的日志仍然是project_info.log --><!--             2.如果日期没有发生变化,但是当前日志的文件大小超过10MB时,对当前日志进行分割 重命名--><appender name="info_log" class="ch.qos.logback.core.rolling.RollingFileAppender"><!--日志文件路径和名称--><File>logs/project_info.log</File><!--是否追加到文件末尾,默认为true--><append>true</append><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>DENY</onMatch><!-- 如果命中ERROR就禁止这条日志 --><onMismatch>ACCEPT</onMismatch><!-- 如果没有命中就使用这条规则 --></filter><!--有两个与RollingFileAppender交互的重要子组件。 第一个RollingFileAppender子组件,即RollingPolicy:负责执行翻转所需的操作。RollingFileAppender的第二个子组件,即TriggeringPolicy:将确定是否以及何时发生翻转。 因此,RollingPolicy负责什么和TriggeringPolicy负责什么时候.作为任何用途,RollingFileAppender必须同时设置RollingPolicy和TriggeringPolicy,但是,如果其RollingPolicy也实现了TriggeringPolicy接口,则只需要显式指定前者。--><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!-- 日志文件的名字会根据fileNamePattern的值,每隔一段时间改变一次 --><!-- 文件名:logs/project_info.2017-12-05.0.log --><!-- 注意:SizeAndTimeBasedRollingPolicy中 %i和%d令牌都是强制性的,必须存在,要不会报错 --><fileNamePattern>logs/project_info.%d.%i.log</fileNamePattern><!-- 每产生一个日志文件,该日志文件的保存期限为30天, ps:maxHistory的单位是根据fileNamePattern中的翻转策略自动推算出来的,例如上面选用了yyyy-MM-dd,则单位为天如果上面选用了yyyy-MM,则单位为月,另外上面的单位默认为yyyy-MM-dd--><maxHistory>30</maxHistory><!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到20GB,哪怕没到30天也要删除多余的日志 --><totalSizeCap>20GB</totalSizeCap><!-- maxFileSize:这是活动文件的大小,默认值是10MB,测试时可改成5KB看效果 --><maxFileSize>10MB</maxFileSize></rollingPolicy><!--编码器--><encoder><!-- pattern节点,用来设置日志的输入格式 ps:日志文件中没有设置颜色,否则颜色部分会有ESC[0:39em等乱码--><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><!-- error 日志--><!-- RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 --><!-- 以下的大概意思是:1.先按日期存日志,日期变了,将前一天的日志文件名重命名为XXX%日期%索引,新的日志仍然是project_error.log --><!--             2.如果日期没有发生变化,但是当前日志的文件大小超过10MB时,对当前日志进行分割 重命名--><appender name="error_log" class="ch.qos.logback.core.rolling.RollingFileAppender"><!--日志文件路径和名称--><File>logs/project_error.log</File><!--是否追加到文件末尾,默认为true--><append>true</append><!-- ThresholdFilter过滤低于指定阈值的事件。 对于等于或高于阈值的事件,ThresholdFilter将在调用其decision()方法时响应NEUTRAL。 但是,将拒绝级别低于阈值的事件 --><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>ERROR</level><!-- 低于ERROR级别的日志(debug,info)将被拒绝,等于或者高于ERROR的级别将相应NEUTRAL --></filter><!--有两个与RollingFileAppender交互的重要子组件。 第一个RollingFileAppender子组件,即RollingPolicy:负责执行翻转所需的操作。RollingFileAppender的第二个子组件,即TriggeringPolicy:将确定是否以及何时发生翻转。 因此,RollingPolicy负责什么和TriggeringPolicy负责什么时候.作为任何用途,RollingFileAppender必须同时设置RollingPolicy和TriggeringPolicy,但是,如果其RollingPolicy也实现了TriggeringPolicy接口,则只需要显式指定前者。--><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!-- 活动文件的名字会根据fileNamePattern的值,每隔一段时间改变一次 --><!-- 文件名:logs/project_error.2017-12-05.0.log --><!-- 注意:SizeAndTimeBasedRollingPolicy中 %i和%d令牌都是强制性的,必须存在,要不会报错 --><fileNamePattern>logs/project_error.%d.%i.log</fileNamePattern><!-- 每产生一个日志文件,该日志文件的保存期限为30天, ps:maxHistory的单位是根据fileNamePattern中的翻转策略自动推算出来的,例如上面选用了yyyy-MM-dd,则单位为天如果上面选用了yyyy-MM,则单位为月,另外上面的单位默认为yyyy-MM-dd--><maxHistory>30</maxHistory><!-- 每个日志文件到10mb的时候开始切分,最多保留30天,但最大到20GB,哪怕没到30天也要删除多余的日志 --><totalSizeCap>20GB</totalSizeCap><!-- maxFileSize:这是活动文件的大小,默认值是10MB,测试时可改成5KB看效果 --><maxFileSize>10MB</maxFileSize></rollingPolicy><!--编码器--><encoder><!-- pattern节点,用来设置日志的输入格式 ps:日志文件中没有设置颜色,否则颜色部分会有ESC[0:39em等乱码--><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以及层次结构中较高的appender(不用在意level值)。换句话说,appender是从记录器层次结构中附加地继承的。例如,如果将控制台appender添加到根记录器,则所有启用的日志记录请求将至少在控制台上打印。如果另外将文件追加器添加到记录器(例如L),则对L和L'子项启用的记录请求将打印在文件和控制台上。通过将记录器的additivity标志设置为false,可以覆盖此默认行为,以便不再添加appender累积--><!-- configuration中最多允许一个root,别的logger如果没有设置级别则从父级别root继承 --><root level="INFO"><appender-ref ref="STDOUT" /></root><!-- 指定项目中某个包,当有日志操作行为时的日志记录级别 --><!-- 级别依次为【从高到低】:FATAL > ERROR > WARN > INFO > DEBUG > TRACE  --><logger name="com.sailing.springbootmybatis" level="INFO"><appender-ref ref="info_log" /><appender-ref ref="error_log" /></logger><!-- 利用logback输入mybatis的sql日志,注意:如果不加 additivity="false" 则此logger会将输出转发到自身以及祖先的logger中,就会出现日志文件中sql重复打印--><logger name="com.sailing.springbootmybatis.mapper" level="DEBUG" additivity="false"><appender-ref ref="info_log" /><appender-ref ref="error_log" /></logger><!-- additivity=false代表禁止默认累计的行为,即com.atomikos中的日志只会记录到日志文件中,不会输出层次级别更高的任何appender--><logger name="com.atomikos" level="INFO" additivity="false"><appender-ref ref="info_log" /><appender-ref ref="error_log" /></logger>
</configuration>

8、使用注意事项

8.1 日志级别判断

这里再说下 log 日志输出代码,一般有人可能在代码中使用如下方式输出:

Object entry = new SomeObject(); 
logger.debug("The entry is " + entry);

上面看起来没什么问题,但是会存在构造消息参数的成本,即将entry转换成字符串相加。

并且无论是否记录消息,都是如此,即:哪怕日志级别为 INFO,也会执行括号里面的操作,但是日志不会输出,

下面是优化后的写法:

if(logger.isDebugEnabled()) { Object entry = new SomeObject(); logger.debug("The entry is " + entry);
}

上面的写法,首先对设置的日志级别进行了判断,如果为debug模式,才进行参数的构造,对第一种写法进行

了改善。

8.2 占位符

不过还有最好的写法,使用占位符:

Object entry = new SomeObject(); 
logger.debug("The entry is {}.", entry);

只有在评估是否记录之后,并且只有在决策是肯定的情况下,记录器实现才会格式化消息并将{} 对替换为条目

的字符串值。换句话说,当禁用日志语句时,此表单不会产生参数构造的成本。

logback 作者进行测试得出:第一种和第三种写法将产生完全相同的输出。但是,在禁用日志记录语句的情况下,

第三个变体将比第一个变体优于至少30倍。

如果有多个参数,写法如下:

logger.debug("The new entry is {}. It replaces {}.", entry, oldEntry);

如果需要传递三个或更多参数,则还可以使用Object []变体:

Object[] paramArray = {newVal, below, above};
logger.debug("Value {} was inserted between {} and {}.", paramArray);

记录日志的时候我们可能需要在文件中记录下异常的堆栈信息,经过测试,logger.error(e)不会打印出堆

栈信息,正确的写法是:

logger.error("程序异常, 详细信息:{}", e.getLocalizedMessage() , e);

我们可以看到 info 的多个重载函数:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/148715.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vulhub redis-4-unacc

环境搭建 cd vulhub/redis/4-unacc docker-compose up -d 漏洞复现 检测 redis-cli -h ip 使用redis工具 工具地址&#xff1a;https://github.com/vulhub/redis-rogue-getshell 下载完成后&#xff0c;先进入RedisModulesSDK/exp/ 目录进行make操作 获得exp.so后可以进行…

【开发流程】持续集成、持续交付、持续部署

一、开发工作流程 假设把开发流程分为以下几个阶段&#xff1a; 编码 -> 构建 -> 集成 -> 测试 -> 交付 -> 部署 如上图所示&#xff0c;持续集成、持续交付、持续部署有着不同的软件自动交付周期。 二、持续集成、持续交付、持续部署 1、持续集成 持续集成…

服务器数据恢复—热备盘同步中断导致Raid5数据丢失的数据恢复案例

服务器数据恢复环境&#xff1a; 某单位一台服务器上有一组raid5阵列&#xff0c;该raid5阵列有15块成员盘。上层是一个xfs裸分区&#xff0c;起始位置是0扇区。 服务器故障&检测&#xff1a; 服务器raid5阵列中有硬盘性能表现不稳定&#xff0c;但是由于管理员长时间没有关…

nodejs+vue实验室上机管理系统的设计与实现-微信小程序-安卓-python-PHP-计算机毕业设计

用户&#xff1a;管理员、教师、学生 基础功能&#xff1a;管理课表、管理机房情况、预约机房预约&#xff1b;权限不同&#xff0c;预约类型不同&#xff0c;教师可选课堂预约和个人&#xff1b;课堂预约。 在实验室上机前&#xff0c;实验室管理员需要对教务处发来的上机课表…

浅析AcrelEMS-CIA机场智慧能源管平台解决方案-安科瑞 蒋静

1 概述 机场智慧能源管平台解决方案对机场范围内变电站内的高低压配电设备 、 发电机、变压器 、UPS、EPS 、广场照明 、 室内照明 、通风及排水等机电设备进行实时分布式监控和集中管理 , 实现无人值守 , 确保高速公路安全畅通 , 提高 自动化管理水平 , 降低机电设备的运行维…

SpringBoot常见注解

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a;每天一个知识点 ✨特色专栏&#xff1a…

程序员告诉你:人工智能是什么?

随着科技的快速发展&#xff0c;人工智能这个词汇已经逐渐融入了我们的日常生活。然而&#xff0c;对于大多数人来说&#xff0c;人工智能仍然是一个相对模糊的概念。 首先&#xff0c;让我们从人工智能的定义开始。人工智能是一种模拟人类智能的技术&#xff0c;它涵盖了多个领…

flink入门

1.安装flink&#xff0c;启动flink 文档地址&#xff1a;Apache Flink 1.3-SNAPSHOT 中文文档: Apache Flink 中文文档 代码&#xff1a;GitHub - apache/flink: Apache Flink 2. 打开端口 端口号&#xff0c; 启动jar ### 切换到flink 目录bin下 [rootlocalhost ~]# cd /…

参考文献格式

目录 期刊会议预印本&#xff08;如arxiv&#xff09; 期刊 找不到页码可以在文献中查看bibtex格式&#xff0c;其中有 外文期刊可在web of science中查找卷号、期号和所在页数&#xff1a; [1] ZHANG F, HU Z Q, FU Y K, et al. A New Identification Method for Surface …

【0到1学习Unity脚本编程】第一人称视角的角色控制器

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;【0…

自动驾驶学习笔记(九)——车辆控制

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《Apollo Beta宣讲和线下沙龙》免费报名—>传送门 文章目录 前言 控制器设计 比例积分微分控制 线性…

Kotlin 知识体系

Kotlin 知识体系 1、Kotlin 文档2、Kotlin 基础3、桌面应用程序4、Android 与 iOS 应用程序 1、Kotlin 文档 Kotlin 是一门现代但已成熟的编程语言&#xff0c;旨在让开发人员更幸福快乐。 它简洁、安全、可与 Java 及其他语言互操作&#xff0c;并提供了多种方式在多个平台间复…

『亚马逊云科技产品测评』活动征文|借助AWS EC2搭建服务器群组运维系统Zabbix+spug

授权声明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 Developer Centre, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道。 本文基于以下软硬件工具&#xff1a; aws ec2 frp-0.52.3 zabbix 6…

LRU最近最少使用算法

LRU(LeastRecentlyUsed)“最近最少使用”算法&#xff1a; 1.当缓存空间已满耗用时&#xff0c;淘汰最近最少使用数据的缓存对象以释放更多的缓存空间(用于历史缓存对象的维护)。 2. 哈希表:快速查找缓存对象&#xff1b;双向链表:维护 历史数据所在的节点顺序。 步骤&#xff…

掌握深度学习利器——TensorFlow 2.x实战应用与进阶

掌握深度学习利器——TensorFlow 2.x实战应用与进阶 摘要&#xff1a;随着人工智能技术的飞速发展&#xff0c;深度学习已成为当下最热门的领域之一。作为深度学习领域的重要工具&#xff0c;TensorFlow 2.x 备受关注。本文将通过介绍TensorFlow 2.x的基本概念和特性&#xff…

在 Linux 上搭建 Java Web 项目环境(最简单的进行搭建)

要在 Linux 上安装的程序有 1.JDK (要想运行 java 程序 JDK 是必不可少的) 2.Tomcat &#xff08;HTTP 服务器&#xff0c;是管理 Web 项目的常用工具&#xff09; 3. mysql &#xff08;数据库&#xff09; 一.安装 JDK 博主使用的 Linux 发行版是 centos &#xff0c;cen…

母婴服务预约小程序的效果如何

二胎家庭增速明显&#xff0c;占比较大&#xff0c;成为市场各母婴品牌的目标&#xff0c;而随着行业发展及市场变化&#xff0c;线上互联网深入人们生活&#xff0c;各家母婴品牌开始向“数字化”靠拢。 目前母婴门店商家主要面临服务/产品线上曝光不足、宣传度不够或扩圈无门…

git rebase 和 git merge的区别?以及你对它们的理解?

文章目录 前言是什么分析区别后言 前言 hello world欢迎来到前端的新世界 &#x1f61c;当前文章系列专栏&#xff1a;git操作相关 &#x1f431;‍&#x1f453;博主在前端领域还有很多知识和技术需要掌握&#xff0c;正在不断努力填补技术短板。(如果出现错误&#xff0c;感谢…

【论文解读】FFHQ-UV:用于3D面部重建的归一化面部UV纹理数据集

【论文解读】FFHQ-UV 论文地址&#xff1a;https://arxiv.org/pdf/2211.13874.pdf 0. 摘要 我们提出了一个大规模的面部UV纹理数据集&#xff0c;其中包含超过50,000张高质量的纹理UV贴图&#xff0c;这些贴图具有均匀的照明、中性的表情和清洁的面部区域&#xff0c;这些都是…

基于深度学习的恶意软件检测

恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞&#xff0c;例如可以被劫持的合法软件&#xff08;例如浏览器或 Web 应用程序插件&#xff09;中的错误。 恶意软件渗透可能会造成灾难性的后果&#xff0c;包括数据被盗、勒索或网…