Springboot日志打印、SpringBoot集成Log4j2、异步日志

文章目录

  • 一、Log4j2介绍
    • 1.1、常用日志框架
    • 1.2、为什么选用log4j2
  • 二、Log4j2整合步骤
    • 2.1、引入jar包
    • 2.2、配置文件
    • 2.3、配置文件模版
  • 三、异步日志
    • 3.1、引入disruptor
    • 3.2、修改启动类
    • 3.3、修改日志文件的内容
    • 3.4、再次进行测试
  • 四、可能遇到的问题
    • 4.1、日志打印不生效?

spring boot支持的日志框架有,logback,Log4j,Log4j2和Java Util Logging,默认使用的是logback日志框架。

之前整理过springboot集成logback日志,具体参考《springboot集成logback》。本文将整理springboot集成log4j2日志框架。

本文仅整理如何集成Log4j2,若需了解详细配置信息可参考《Springboot日志打印、SpringBoot集成Log4j2(附源码)、异步日志》

一、Log4j2介绍

1.1、常用日志框架

首先slf4j是一个简单的门面模式,意思就是说这只是一个日志标准,并不是日志系统的具体实现,slf4j只做两件事:提供日志接口和提供获取具体日志对象的方法。

  • java.util.logging:是JDK在1.4版本中引入的Java原生日志框架
  • Log4j:Apache的一个开源项目,可以控制日志信息输送的目的地是控制台、文件、GUI组件等,可以控制每一条日志的输出格式,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。目前已经停止维护了。
  • LogBack:是Log4j的一个改良版本,是slf4j的原生实现,目前是springboot的默认日志组件
  • Log4j2:Log4j2已经不仅仅是Log4j的一个升级版本了,它从头到尾都被重写了。据说采用了一些新技术(无锁异步、等等),使得日志的吞吐量、性能比log4j 1.x提高10倍 ,还提供了异步日志功能,所以这里重点介绍上log4j2的使用 以及一些概念

1.2、为什么选用log4j2

相比与其他的日志系统,log4j2丢数据这种情况少;disruptor技术(即异步日志)在多线程环境下,性能高于logback等10倍以上;利用jdk1.5并发的特性,减少了死锁的发生;

在这列举一下一些网上其他博文中对它们的性能评测:
在这里插入图片描述

  • 可以看到在同步日志模式下, Logback的性能是最糟糕的.
  • log4j2的性能无论在同步日志模式还是异步日志模式下都是最佳的.

log4j2优越的性能其原因在于log4j2使用了LMAX,一个无锁的线程间通信库代替了logback和log4j之前的队列. 并发性能大大提升。

二、Log4j2整合步骤

2.1、引入jar包

springboot默认是用logback的日志框架的,所以需要排除logback,不然会出现jar依赖冲突的报错。具体依赖包是spring-boot-starter-logging,一般存在于spring-boot-starter-web、actuator等依赖中。

排除springboot默认的logback依赖包并引入

<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-web</artifactId>  
    <exclusions><!-- 去掉springboot默认配置 -->  
        <exclusion>  
            <groupId>org.springframework.boot</groupId>  
            <artifactId>spring-boot-starter-logging</artifactId>  
        </exclusion>  
    </exclusions>  
</dependency> 

<dependency> <!-- 引入log4j2依赖 -->  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-log4j2</artifactId>  
</dependency> 

2.2、配置文件

需要在application或yml中指定log4j2使用的xml文件

1、如果自定义了文件名,需要在application.yml中配置

logging:
  config: classpath:log4j2.xml

2、默认名log4j2-spring.xml,就省下了在application.yml中配置

2.3、配置文件模版

log4j是通过一个.properties的文件作为主配置文件的,而现在的log4j2则已经弃用了这种方式,采用的是.xml,.json或者.jsn这种方式来做,可能这也是技术发展的一个必然性,因为properties文件的可阅读性真的是有点差。这里给出博主自配的一个模版,供大家参考。

<?xml version="1.0" encoding="UTF-8"?>
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration monitorInterval="5">
    <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->

    <!--变量配置-->
    <Properties>
        <!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
        <!-- %logger{36} 表示 Logger 名字最长36个字符 -->
        <property name="LOG_PATTERN" value="%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />
        <!-- 定义日志存储的路径 -->
        <property name="FILE_PATH" value="./logs" />
        <property name="FILE_NAME" value="demo" />
    </Properties>

    <appenders>

        <console name="Console" target="SYSTEM_OUT">
            <!--输出日志的格式及颜色-->
            <PatternLayout pattern="[%style{%d}{bright,yellow}][%style{%t}{bright,blue}][%highlight{%p}][%style{%C}{bright,green}]: %msg%n%style{%throwable}{red}"
                           disableAnsi="false" noConsoleNoAnsi="false"/>
        </console>

        <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用-->
        <File name="Filelog" fileName="${FILE_PATH}/test.log" append="false">
            <PatternLayout pattern="${LOG_PATTERN}"/>
        </File>

        <!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log" filePattern="${FILE_PATH}/$${date:yyyy-MM-dd}/info-%d{yyyy-MM-dd}_%i.log.gz">
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <!--interval属性用来指定多久滚动一次,此处单位是1 天
					单位是由于filePattern中的最小单位决定的,本示例中filePattern的格式是年月日,所以最小单位是天。若filePattern格式是时分秒,则TimeBasedTriggeringPolicy的单位是秒。
				-->
                <TimeBasedTriggeringPolicy interval="1"/>
                <SizeBasedTriggeringPolicy size="30MB"/>
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
            <DefaultRolloverStrategy fileIndex="nomax">
                <!--删除${FILE_PATH}目录及子目录下 180天前的.log.gz后缀的文件 -->
                <Delete basePath="${FILE_PATH}" maxDepth="2">
                    <IfFileName glob="*/*.log.gz"/>
                    <IfLastModified age="180d"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>

        <!-- 这个会打印出所有的warn及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingFile name="RollingFileWarn" fileName="${FILE_PATH}/warn.log" filePattern="${FILE_PATH}/$${date:yyyy-MM-dd}/warn-%d{yyyy-MM-dd}_%i.log.gz">
            <Filters>
                <!--过滤掉error及更高级别日志-->
                <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <!--interval属性用来指定多久滚动一次,此处单位是1-->
                <TimeBasedTriggeringPolicy interval="1"/>
                <SizeBasedTriggeringPolicy size="30MB"/>
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
            <DefaultRolloverStrategy fileIndex="nomax">
                <!--删除${FILE_PATH}目录及子目录下 180天前的.log.gz后缀的文件 -->
                <Delete basePath="${FILE_PATH}" maxDepth="2">
                    <IfFileName glob="*/*.log.gz"/>
                    <IfLastModified age="180d"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>

        <!-- 这个会打印出所有的error及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingFile name="RollingFileError" fileName="${FILE_PATH}/error.log" filePattern="${FILE_PATH}/$${date:yyyy-MM-dd}/error-%d{yyyy-MM-dd}_%i.log.gz">
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <!--interval属性用来指定多久滚动一次,默认是1 hour-->
                <TimeBasedTriggeringPolicy interval="1"/>
                <SizeBasedTriggeringPolicy size="30MB"/>
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
            <DefaultRolloverStrategy fileIndex="nomax">
                <!--删除${FILE_PATH}目录及子目录下 180天前的.log.gz后缀的文件 -->
                <Delete basePath="${FILE_PATH}" maxDepth="2">
                    <IfFileName glob="*/*.log.gz"/>
                    <IfLastModified age="180d"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>

    </appenders>

    <!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。-->
    <!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效-->
    <loggers>
        <!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
        <logger name="org.mybatis" level="info" additivity="false">
            <AppenderRef ref="Console"/>
        </logger>
        
        <!--监控系统信息-->
        <!--若是additivity设为false,则 子Logger 只会在自己的appender里输出,而不会在 父Logger 的appender里输出。-->
        <Logger name="org.springframework" level="info" additivity="true">
            <!--<AppenderRef ref="Console"/>-->
        </Logger>

        <!-- additivity:是否向上级logger传递打印信息。默认是true-->
        <!-- name="com.example"修改为自己的项目目录 -->
        <!--[需修改] level: 若需要打印sql日志则需要修改为debug级别;否则为info级别。 -->
        <Logger name="com.example" level="debug" additivity="true">
        </Logger>

        <root level="info">
            <appender-ref ref="Console" />
            <!--<appender-ref ref="Filelog"/>-->
            <appender-ref ref="RollingFileInfo"/>
            <appender-ref ref="RollingFileWarn" level="warn"/>
            <appender-ref ref="RollingFileError"/>
        </root>
    </loggers>


</configuration>

上述模版实现了控制台及log文件中会打印sql日志。若不想打印sql日志,则修改为

<!-- 修改level为info级别,debug级别的sql日志就不会打印出来了 -->
<Logger name="com.example" level="info" additivity="true"/>

使用注意事项:
1、修改配置文件中以下几个地方
在这里插入图片描述
2、root标签中引入了Filelog配置项,此处是为了测试使用的,会把所有日志都打印在同一个文件中,可以删除掉。即:

<root level="info">
    <appender-ref ref="Console" />
    <appender-ref ref="RollingFileInfo"/>
    <appender-ref ref="RollingFileWarn"/>
    <appender-ref ref="RollingFileError"/>
</root>

测试代码

package com.example.demo.controller;

import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;


@RestController(value = "/user")
@Api(value = "用户管理功能集", tags = "用户管理")
@Slf4j
public class UserController {
    private static final Logger logger = LoggerFactory.getLogger(UserController.class);
    
    @Autowired
    private UserMapper userMapper;

    @GetMapping(value = "/getUser")
    public List<User> getUser(){
        logger.info("===========进入方法===========");
        List<User> list = userMapper.getAllUser();
        log.info("===========查询结束===========");
        return list;
    }

}

打印后日志格式:

 .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.4.7)

[2024-12-23 14:55:23,870][main][INFO][org.springframework.boot.StartupInfoLogger]: Starting MainApplication using Java 1.8.0_202 on LAPTOP-9UHA7CHR with PID 44836 (D:\WorkSpace\springboot-bucket\springboot-log4j2\target\classes started by 13488 in D:\WorkSpace\springboot-bucket)
[2024-12-23 14:55:23,874][main][DEBUG][org.springframework.boot.StartupInfoLogger]: Running with Spring Boot v2.4.7, Spring v5.3.8
[2024-12-23 14:55:23,875][main][INFO][org.springframework.boot.SpringApplication]: No active profile set, falling back to default profiles: default
[2024-12-23 14:55:24,323][main][DEBUG][org.apache.ibatis.logging.LogFactory]: Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
[2024-12-23 14:55:24,494][main][INFO][org.springframework.boot.web.embedded.tomcat.TomcatWebServer]: Tomcat initialized with port(s): 8080 (http)
[2024-12-23 14:55:24,499][main][INFO][org.apache.juli.logging.DirectJDKLog]: Initializing ProtocolHandler ["http-nio-8080"]
[2024-12-23 14:55:24,499][main][INFO][org.apache.juli.logging.DirectJDKLog]: Starting service [Tomcat]
[2024-12-23 14:55:24,500][main][INFO][org.apache.juli.logging.DirectJDKLog]: Starting Servlet engine: [Apache Tomcat/9.0.46]

在这里插入图片描述

三、异步日志

log4j2日志框架有个比较牛的功能是异步日志记录性能。

我们先在上面的二、Log4j2整合步骤(即同步日志)框架下测试以下代码打印耗时。

package com.example.demo.controller;

import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController(value = "/user")
@Slf4j
public class UserController {
    private static final Logger logger = LoggerFactory.getLogger(UserController.class);


    @GetMapping("/testLog")
    public void testLog() {
        long start = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            log.info("这是第{}次日志", i);
        }
        long end = System.currentTimeMillis();
        log.info("当前打印日志耗时:{}", (end - start));
    }


}

在这里插入图片描述
由上面的结果可以看出日志打印的耗时很长,所以为了解决日志耗时过长的问题,我们引入一个“异步日志”的工具—disruptor,它可以大大缩短耗时,优化性能。

3.1、引入disruptor

<!-- 异步日志 -->
<dependency>
  <groupId>com.lmax</groupId>
  <artifactId>disruptor</artifactId>
  <version>3.4.2</version>
</dependency>

3.2、修改启动类

package com.example.demo;


import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;

@SpringBootApplication
@MapperScan("com.example.demo.mapper")
//开启swagger功能
@EnableSwagger2WebMvc
public class MainApplication {

    public static void main(String[] args) {
        // 异步日志
        System.setProperty("log4jContextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
        SpringApplication.run(MainApplication.class,args);
    }
}

3.3、修改日志文件的内容

这里我们只需要新增两个新的配置项即可

<?xml version="1.0" encoding="UTF-8"?>
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration monitorInterval="5">
    <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->

    <!--变量配置-->
    <Properties>
        <!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
        <!-- %logger{36} 表示 Logger 名字最长36个字符 -->
        <property name="LOG_PATTERN" value="%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />
        <!-- 定义日志存储的路径 -->
        <property name="FILE_PATH" value="./logs" />
        <property name="FILE_NAME" value="demo" />
    </Properties>

    <appenders>

        <console name="Console" target="SYSTEM_OUT">
            <!--输出日志的格式及颜色-->
            <PatternLayout pattern="[%style{%d}{bright,yellow}][%style{%t}{bright,blue}][%highlight{%p}][%style{%C}{bright,green}]: %msg%n%style{%throwable}{red}"
                           disableAnsi="false" noConsoleNoAnsi="false"/>
        </console>

        <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用-->
        <File name="Filelog" fileName="${FILE_PATH}/test.log" append="false">
            <PatternLayout pattern="${LOG_PATTERN}"/>
        </File>

        <!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log" filePattern="${FILE_PATH}/$${date:yyyy-MM-dd}/info-%d{yyyy-MM-dd}_%i.log.gz">
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <!--interval属性用来指定多久滚动一次,此处单位是1 天
					单位是由于filePattern中的最小单位决定的,本示例中filePattern的格式是年月日,所以最小单位是天。若filePattern格式是时分秒,则TimeBasedTriggeringPolicy的单位是秒。
				-->
                <TimeBasedTriggeringPolicy interval="1"/>
                <SizeBasedTriggeringPolicy size="30MB"/>
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
            <DefaultRolloverStrategy fileIndex="nomax">
                <!--删除${FILE_PATH}目录及子目录下 180天前的.log.gz后缀的文件 -->
                <Delete basePath="${FILE_PATH}" maxDepth="2">
                    <IfFileName glob="*/*.log.gz"/>
                    <IfLastModified age="180d"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>

        <!-- 这个会打印出所有的warn及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingFile name="RollingFileWarn" fileName="${FILE_PATH}/warn.log" filePattern="${FILE_PATH}/$${date:yyyy-MM-dd}/warn-%d{yyyy-MM-dd}_%i.log.gz">
            <Filters>
                <!--过滤掉error及更高级别日志-->
                <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <!--interval属性用来指定多久滚动一次,此处单位是1-->
                <TimeBasedTriggeringPolicy interval="1"/>
                <SizeBasedTriggeringPolicy size="30MB"/>
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
            <DefaultRolloverStrategy fileIndex="nomax">
                <!--删除${FILE_PATH}目录及子目录下 180天前的.log.gz后缀的文件 -->
                <Delete basePath="${FILE_PATH}" maxDepth="2">
                    <IfFileName glob="*/*.log.gz"/>
                    <IfLastModified age="180d"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>

        <!-- 这个会打印出所有的error及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingFile name="RollingFileError" fileName="${FILE_PATH}/error.log" filePattern="${FILE_PATH}/$${date:yyyy-MM-dd}/error-%d{yyyy-MM-dd}_%i.log.gz">
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <!--interval属性用来指定多久滚动一次,默认是1 hour-->
                <TimeBasedTriggeringPolicy interval="1"/>
                <SizeBasedTriggeringPolicy size="30MB"/>
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
            <DefaultRolloverStrategy fileIndex="nomax">
                <!--删除${FILE_PATH}目录及子目录下 180天前的.log.gz后缀的文件 -->
                <Delete basePath="${FILE_PATH}" maxDepth="2">
                    <IfFileName glob="*/*.log.gz"/>
                    <IfLastModified age="180d"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>

    </appenders>

    <!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。-->
    <!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效-->
    <loggers>
         <!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
        <logger name="org.mybatis" level="info" additivity="false">
            <AppenderRef ref="Console"/>
        </logger>
        <!--监控系统信息-->
        <!--若是additivity设为false,则 子Logger 只会在自己的appender里输出,而不会在 父Logger 的appender里输出。-->
        <Logger name="org.springframework" level="info" additivity="true">
            <!--<AppenderRef ref="Console"/>-->
        </Logger>

        <!-- additivity:是否向上级logger传递打印信息。默认是true-->
        <!-- name="com.example"修改为自己的项目目录 -->
        <!--[需修改] level: 若需要打印sql日志则需要修改为debug级别;否则为info级别。 -->
        <Logger name="com.example" level="debug" additivity="true">
        </Logger>

         <!-- 异步日志 -->
        <AsyncLogger name="asyncLog" level="info" additivity="false">
            <appender-ref ref="RollingFileInfo"/>
        </AsyncLogger>

        <AsyncRoot level="info">
            <AppenderRef ref="RollingFileInfo"/>
        </AsyncRoot>

        <!--<root level="info">
            <appender-ref ref="Console" />
            <appender-ref ref="Filelog"/>
            <appender-ref ref="RollingFileInfo"/>
            <appender-ref ref="RollingFileWarn" level="warn"/>
            <appender-ref ref="RollingFileError"/>
        </root>-->
    </loggers>


</configuration>

3.4、再次进行测试

可以发现,控制台没有输出相关日志,这时候我们需要去找到在日志文件中配置的日志存放地址,查看具体的日志
在这里插入图片描述
打开文件后可见耗时大大缩短!!!
在这里插入图片描述

四、可能遇到的问题

4.1、日志打印不生效?

日志打印不生效可能是由于以下几种原因:

  1. 依赖冲突 :springboot默认集成logback日志,所以需要把spring-boot-starter-logging依赖排除掉。spring-boot-starter-logging一般存在于spring-boot-starter-web、actuator等依赖中。

参考文章:
1.log4j官网地址:https://logging.apache.org/log4j/2.x/index.html
Log4j2配置官网地址:https://logging.apache.org/log4j/2.x/manual/configuration.html#AutomaticConfiguration
https://www.jianshu.com/p/8b30d312a47b


创作不易,欢迎打赏,你的鼓励将是我创作的最大动力。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

浏览器选中文字样式

效果 学习 Chrome: 支持 ::selection。Firefox: 支持 :-moz-selection 和 ::selection。Safari: 支持 ::selection。Internet Explorer: 支持 :-ms-selection。Microsoft Edge: 支持 ::-ms-selection 和 ::selection。 代码 <!DOCTYPE html> <html lang"en&qu…

【UE5】UnrealEngine源码构建2:windows构建unreal engine 5.3.2

参考大神知乎的文章:UE5 小白也能看懂的源码编译指南 据说会耗费400G的空间。 代码本身并不大,可能是依赖特别多,毕竟看起来UE啥都能干,核心还是c++的, 【UE5】UnrealEngine源码构建1:tag为5.3.2源码clone 本着好奇+ 学习的态度,想着也许有机会能更为深入的熟悉UE的机制…

STM32 拓展 RTC(实时时钟)

RTC简介 RTC(Real Time Clock,实时时钟)。是一个掉电后仍然可以继续运行的独立定时器。 RTC模块拥有一个连续计数的计数器,在相应的软件配置下,可以提供时钟日历的功能。修改计数器的值可以重新设置当前时间和日期 RTC还包含用于管理低功耗模式的自动唤醒单元。 RTC实质…

uniapp 自定义类微信支付键盘 (微信小程序)

效果图 代码: <view class"popups popupsB"><view class"appreciatePrice"><view class"appreciatePriceTitle">赞赏金额</view><view class"appreciatePriceInput flex ac">&#xffe5;<input typ…

Nginx代理本地exe服务http为https

Nginx代理本地exe服务http为https 下载NginxNginx命令exe服务http代理为https 下载Nginx 点击下载Nginx 下载好之后是一个压缩包&#xff0c;解压放到没有中文的路径下就可以了 Nginx命令 调出cmd窗口cd到安装路径 输入&#xff1a;nginx -v 查看版本 nginx -h&#xff…

二、CSS基础

一、选择器(1) 大白话&#xff1a;我们人为认为的解析方式是&#xff0c;从左往右查找&#xff0c;对于浏览器来说&#xff0c;是从右往左查找&#xff0c;解析速度更高。 注&#xff1a; 伪类选择器 - 作用于实际存在的元素&#xff0c;用于描述元素的某种特定状态或关系&…

GoF23种设计模式 简介

文章目录 面向对象(OO)设计原则&#xff08;7&#xff09;单一职责原则开闭原则里氏代换原则依赖倒转原则接口隔离原则合成复用原则迪米特法则 创建型模式 &#xff08;5&#xff09;工厂方法模式 &#xff08;类模式&#xff0c;其余都是对象模式&#xff09;抽象工厂模式建造…

关于Zotero

1、文献数据库&#xff1a; Zotero的安装 Zotero安装使用_zotero只能安装在c盘吗-CSDN博客 2、如何使用zotero插件 我刚下载的时候就结合使用的是下面的这两个博主的分享&#xff0c;感觉暂时是足够的。 Zotero入&#x1f6aa;基础 - 小红书 Green Frog申请easyscholar密钥…

Linux实验报告15-添加系统调用

目录 一&#xff1a;实验目的 二&#xff1a;实验内容 &#xff08;1&#xff09;查看系统内核版本 &#xff08;2&#xff09;安装内核版本源码 &#xff08;3&#xff09;修改注册表 &#xff08;4&#xff09;添加系统调用头文件 &#xff08;5&#xff09;实现系统调…

使用Clion在ubuntu上进行交叉编译,并在Linux上远程编译五子棋

目录 1.工具以及概念介绍 &#xff08;1&#xff09;Clion软件简介 &#xff08;2&#xff09;交叉编译 &#xff08;3&#xff09;远程编译 2.操作原理 3.详细操作步骤 &#xff08;1&#xff09;配置Clion与虚拟机ubuntu的ssh连接 CLion远程开发Ubuntu&#xff0c;并显…

Unity UGUI使用技巧与经验总结(不定期更新)

Text自动缩放参考连接&#xff1a; Unity -UGUI中Text文本框的自动调整&#xff0c;字体大小的自适应调节_unity添加的字体大小锁定-CSDN博客 Toggle按钮选择时&#xff0c;显示对应的UI界面&#xff1a; 为Toggle组件的On Value Change事件添加对需要显示的对象的SetActive…

无刷直流电机偏移角度

1、问题引入 (1)电机偏移角度是什么&#xff1f;若偏移角度不为0&#xff0c;如何让电机转起来&#xff1f; 1.1 GPT答案1 电机偏移角度的定义 电机的偏移角度是指电机的实际转子磁场位置与控制系统所认为的转子磁场位置之间的误差角度。这个误差可能是由于霍尔传感器安装不…

GitHub的简单操作

引言 今天开始就要开始做项目了&#xff0c;上午是要把git搭好。搭的过程中遇到好多好多的问题。下面就说一下git的简单操作流程。我们是使用的GitHub,下面也就以这个为例了 一、GitHub账号的登录注册 https://github.com/ 通过这个网址可以来到GitHub首页 点击中间绿色的S…

SD下载、安装、使用、卸载-Stable Diffusion整合包v4.10发布!

目录 前言概述 SD安装1、安装软件2、启动3、配置4、运行5、测试 导入SD模型【决定画风】常用模型下载安装模型 SD卸载SD文生图提示词提示词使用技巧提示词的高级使用技巧强调关键词 前言 我向来不喜欢搞一些没有用的概念&#xff0c;所以直接整理可能用到的东西。 sd简单的说…

CDN SSLTLS以及安全

随着互联网的发展&#xff0c;内容分发网络&#xff08;CDN&#xff09;在提升网站访问速度和安全性方面发挥了重要作用。然而&#xff0c;CDN在带来便利的同时也面临一些安全挑战。本文将探讨CDN的安全风险&#xff0c;并深入解析SSL/TLS加密技术及其在CDN中的应用。 CDN的安全…

电子电气架构 --- 中央处理器HPC及软件架构

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所谓鸡汤,要么蛊惑你认命,要么怂恿你拼命,但都是回避问题的根源,以现象替代逻辑,以情绪代替思考,把消极接受现实的懦弱,伪装成乐观面对不幸的…

手写顺序流程图组件

效果图 完整代码 <template><div><div class"container" :style"{ width: ${spacingX * (colNum - 1) itemWidth * colNum}px }"><divv-for"(item, i) in recordList":key"i"class"list-box":style&…

html+css+js网页设计 美食 好厨艺西餐美食企业网站模板6个页面

htmlcssjs网页设计 美食 好厨艺西餐美食企业网站模板6个页面 网页作品代码简单&#xff0c;可使用任意HTML辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 …

Vue3中使用 Vue Flow 流程图方法

效果图&#xff1a; 最近项目开发时有一个流程图的功能&#xff0c;需要做流程节点的展示&#xff0c;就搜到了 Vue Flow 这个插件&#xff0c;这个插件总得来说还可以&#xff0c;简单已使用&#xff0c;下边就总结一下使用的方法&#xff1a; Vue Flow官网&#xff1a;https…

37. 数组二叉树

一、题目描述 二叉树只也可以用数组来存储&#xff0c;给定一个数组&#xff0c;树的根节点的值储存在下标1&#xff0c;对于储存在下标n的节点&#xff0c;他的左子节点和右子节点分别储存在下标2n和2n1&#xff0c;并且我们用-1代表一个节点为空&#xff0c;给定一个数组存储…