Springboot配置log4j2爬坑
Version Springboot 2.11.1
logging.config参数
logging.config 配置在application.yml中有效,指定路径有效
log4j2
log4j2官网支持多种自动配置方式,自动扫描:
系统属性(Log4j.configuration) -> classpath中的(log4j2-test.properties)
-> classpath中的(log4j2-test.yml/yaml/json/jsn/xml)
-> classpath中的(log4j2.yml/yaml/json/jsn/xml) -> 默认配置
Log4j获取ConfigurationFactory
// 按照测试前缀log4j2-test 和 LoggerContext上下文实例获取ConfigurationFactory Configuration config = getConfiguration(loggerContext, true, name); if (config == null) { // 按照测试前缀log4j2-test 获取ConfigurationFactory config = getConfiguration(loggerContext, true, null); if (config == null) { // 按照前缀log4j2 和LoggerContext上下文实例获取ConfigurationFactory config = getConfiguration(loggerContext, false, name); if (config == null) { // 按照前缀log4j2 获取ConfigurationFactory // Springboot 加载Log4j2的工厂实例在这里获取,指向Springboot包log4j2.springboot中的SpringBootConfigurationFactory config = getConfiguration(loggerContext, false, null); } } }
log4j2
核心代码如下:
String ALL_TYPES = "*"; for (final ConfigurationFactory factory : getFactories()) { final String[] types = factory.getSupportedTypes(); if (types != null) { for (final String type : types) { // 只有 XmlConfigurationFactory 符合条件 if (type.equals(ALL_TYPES)) { final Configuration config = factory.getConfiguration(loggerContext, name, configLocation); if (config != null) { return config; } } } } }
springboot logging
springboot使用Common logging组件加载日志模块,提供了Java Util、Log4J2和Logback日志的默认配置,预先配置了控制台输出,还提供可选的文件输出。
springboot默认日志配置文件
Logging System | Customization |
---|---|
Logback | logback-spring.xml , logback-spring.groovy , logback.xml , or logback.groovy |
Log4j2 | log4j2-spring.xml or log4j2.xml |
JDK (Java Util Logging) | logging.properties |
Springboot log4j2配置工厂
log4j2 加载log4j-core中的ConfigurationFactory继承类,排序如下:
- PropertiesConfigurationFactory
- YamlConfigurationFactory
- JsonConfigurationFactory
- XmlConfigurationFactory
- SpringBootConfigurationFactory (匹配.springboot)
springboot 中修改了log4j2.xml的名称后不生效
log4j2.xml文件修改名称为log4j2_dev.xml同时在appliaction_dev.yml配置文件中指定了logging.config
路径,但是结果还是走spring默认配置。
原因解释
- springboot log4j2读取顺序:logging.config —> classpath(
log4j2-spring.xml
orlog4j2.xml
) —> spring-boot包下的logging.log4j.log4j2.xml - springBoot项目中默认有一份日志配置文件,项目启动时先读取到了默认日志配置文件,没有读取resource目录中的配置文件,需要自定义日志信息的话需要在Springboot配置文件中指定读取自定义的配置文件
不能读取Yml配置原因
- 在Log4J2装载时,会检查jackson中的ObjectMapper、JsonNode、JsonParser和YAMLFactory,装载YAMLFactory会失败,所以无法解析yml配置的yml文件,导致失败
public class YamlConfigurationFactory extends ConfigurationFactory { /** * The file extensions supported by this factory. */ private static final String[] SUFFIXES = new String[] {".yml", ".yaml"}; private static final String[] dependencies = new String[] { "com.fasterxml.jackson.databind.ObjectMapper", "com.fasterxml.jackson.databind.JsonNode", "com.fasterxml.jackson.core.JsonParser", "com.fasterxml.jackson.dataformat.yaml.YAMLFactory" }; private final boolean isActive; public YamlConfigurationFactory() { for (final String dependency : dependencies) { if (!Loader.isClassAvailable(dependency)) { LOGGER.debug("Missing dependencies for Yaml support, ConfigurationFactory {} is inactive", getClass().getName()); isActive = false; return; } } isActive = true; }
测试过程中
将logging.config配置写入application.yml中发现可以读取配置位置
public class LoggingApplicationListener{ // logFile 指定日志文件输出位置 private void initializeSystem(ConfigurableEnvironment environment, LoggingSystem system, LogFile logFile) { LoggingInitializationContext initializationContext = new LoggingInitializationContext( environment); // 可以读取到配置 String logConfig = environment.getProperty(CONFIG_PROPERTY); if (ignoreLogConfig(logConfig)) { system.initialize(initializationContext, null, logFile); } ... } }
Spring支持Log4j2默认配置的代码
public abstract class AbstractLoggingSystem extends LoggingSystem { // Log4j 初始化 public void initialize(LoggingInitializationContext initializationContext, String configLocation, LogFile logFile) { if (StringUtils.hasLength(configLocation)) { initializeWithSpecificConfig(initializationContext, configLocation, logFile); return; } // 无配置,调用默认配置 initializeWithConventions(initializationContext, logFile); } private String[] getCurrentlySupportedConfigLocations() { List<String> supportedConfigLocations = new ArrayList<>(); if (isClassAvailable("com.fasterxml.jackson.dataformat.yaml.YAMLParser")) { Collections.addAll(supportedConfigLocations, "log4j2.yaml", "log4j2.yml"); } if (isClassAvailable("com.fasterxml.jackson.databind.ObjectMapper")) { Collections.addAll(supportedConfigLocations, "log4j2.json", "log4j2.jsn"); } supportedConfigLocations.add("log4j2.xml"); return StringUtils.toStringArray(supportedConfigLocations); } protected String[] getSpringConfigLocations() { String[] locations = getStandardConfigLocations(); for (int i = 0; i < locations.length; i++) { String extension = StringUtils.getFilenameExtension(locations[i]); locations[i] = locations[i].substring(0, locations[i].length() - extension.length() - 1) + "-spring." + extension; } return locations; } }
Spring最终配置文件位置
Spring通过默认配置查找,classpath路径下的配置文件,如果没有找到,就会加载spring-boot包下的logging.log4j.log4j2.xml,如果配置了日志输出位置,则为log4j2-file.xml
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Springboot日志基础
Springboot配置日志配置文件位置 logging.config: classpath:logging/logback.yml Springboot日志分类 log4j: 是apache实现的一个开源日志组件 logback: 同样是由log4j的作者设计完成的,拥有更好的特性,用来取代log4j的一个日志框架,是slf4j的原生实现 log4j2: 是log4j 1.x和logback的改进版,采用了一些新技术(无锁异步、等等),使得日志的吞吐量、性能比log4j 1.x提高10倍,并解决了一些死锁的bug,而且配置更加简单灵活 slf4j+log4j和直接用log4j的区别 slf4j是对所有日志框架制定的一种规范、标准、接口,并不是一个框架的具体的实现,因为接口并不能独立使用,需要和具体的日志框架实现配合使用(如log4j、logback),使用接口的好处是当项目需要更换日志框架的时候,只需要更换jar和配置,不需要更改相关java代码。 import org.slf4j.Logger; import org.slf4j.LoggerFactory; public clas...
- 下一篇
Springboot加载日志模块顺序
Springboot加载日志模块 Spring jcl Spring jcl 是Springboot连接SLF4J的基础包,实现了对Log4j 2.x API是否存在,以及Spring框架类路径中的SLF4J 1.7api。 ServiceLoader 通过配置寻找接口的实现类,实现类的jar包的META-INF下新建一个文件夹services,并在services下新建一个文件,以接口的全限定名为文件名,内容为实现类的全限定名。 参考链接: https://www.jianshu.com/p/7601ba434ff4 https://blog.csdn.net/shi2huang/article/details/80308531 Log4j获取ConfigurationFactory 核心代码 String ALL_TYPES = "*"; for (final ConfigurationFactory factory : getFactories()) { final String[] types = factory.getSupportedTypes(); if (types !...
相关文章
文章评论
共有0条评论来说两句吧...