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、日志打印不生效?
日志打印不生效可能是由于以下几种原因:
- 依赖冲突 :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