Springboot配置log4j2爬坑

简介: Version Springboot 2.11.1 logging.config参数 logging.config 配置在application.yml中有效,指定路径有效 log4j2 log4j2官网支持多种自动配置方式,自动扫描: 系统属性(Log4j.

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默认配置。(不生效原因是,应该为appliaction-dev.yml)

原因解释
  1. springboot log4j2读取顺序:logging.config —> classpath(log4j2-spring.xml or log4j2.xml) —> spring-boot包下的logging.log4j.log4j2.xml
  2. springBoot项目中默认有一份日志配置文件,项目启动时先读取到了默认日志配置文件,没有读取resource目录中的配置文件,需要自定义日志信息的话需要在Springboot配置文件中指定读取自定义的配置文件
不能读取Yml配置原因
  1. 在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

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
2月前
|
监控 安全 程序员
Python日志模块配置:从print到logging的优雅升级指南
从 `print` 到 `logging` 是 Python 开发的必经之路。`print` 调试简单却难维护,日志混乱、无法分级、缺乏上下文;而 `logging` 支持级别控制、多输出、结构化记录,助力项目可维护性升级。本文详解痛点、优势、迁移方案与最佳实践,助你构建专业日志系统,让程序“有记忆”。
268 0
|
5月前
|
Java Spring
Spring Boot配置的优先级?
在Spring Boot项目中,配置可通过配置文件和外部配置实现。支持的配置文件包括application.properties、application.yml和application.yaml,优先级依次降低。外部配置常用方式有Java系统属性(如-Dserver.port=9001)和命令行参数(如--server.port=10010),其中命令行参数优先级高于系统属性。整体优先级顺序为:命令行参数 &gt; Java系统属性 &gt; application.properties &gt; application.yml &gt; application.yaml。
1003 0
|
2月前
|
JavaScript Java Maven
【SpringBoot(二)】带你认识Yaml配置文件类型、SpringMVC的资源访问路径 和 静态资源配置的原理!
SpringBoot专栏第二章,从本章开始正式进入SpringBoot的WEB阶段开发,本章先带你认识yaml配置文件和资源的路径配置原理,以方便在后面的文章中打下基础
333 3
|
3月前
|
缓存 Java 应用服务中间件
Spring Boot配置优化:Tomcat+数据库+缓存+日志,全场景教程
本文详解Spring Boot十大核心配置优化技巧,涵盖Tomcat连接池、数据库连接池、Jackson时区、日志管理、缓存策略、异步线程池等关键配置,结合代码示例与通俗解释,助你轻松掌握高并发场景下的性能调优方法,适用于实际项目落地。
625 5
|
3月前
|
传感器 Java 数据库
探索Spring Boot的@Conditional注解的上下文配置
Spring Boot 的 `@Conditional` 注解可根据不同条件动态控制 Bean 的加载,提升应用的灵活性与可配置性。本文深入解析其用法与优势,并结合实例展示如何通过自定义条件类实现环境适配的智能配置。
203 0
探索Spring Boot的@Conditional注解的上下文配置
|
4月前
|
安全 算法 Java
在Spring Boot中应用Jasypt以加密配置信息。
通过以上步骤,可以在Spring Boot应用中有效地利用Jasypt对配置信息进行加密,这样即使配置文件被泄露,其中的敏感信息也不会直接暴露给攻击者。这是一种在不牺牲操作复杂度的情况下提升应用安全性的简便方法。
1054 10
|
安全 BI 网络安全
EventLog Analyzer 如何满足等保合规要求?密码有效期、产品日志保留、配置备份三大核心问题全面解答
EventLog Analyzer(ELA)助力企业满足网络安全等级保护要求,支持配置自动/手动备份、日志180天留存及密码策略管理,提升合规性与安全运营效率。
130 0
|
5月前
|
机器学习/深度学习 XML Java
【spring boot logback】日志logback格式解析
在 Spring Boot 中,Logback 是默认的日志框架,它支持灵活的日志格式配置。通过配置 logback.xml 文件,可以定义日志的输出格式、日志级别、日志文件路径等。
921 5
|
5月前
|
人工智能 安全 Java
Spring Boot yml 配置敏感信息加密
本文介绍了如何在 Spring Boot 项目中使用 Jasypt 实现配置文件加密,包含添加依赖、配置密钥、生成加密值、在配置中使用加密值及验证步骤,并提供了注意事项,确保敏感信息的安全管理。
1202 1
|
5月前
|
JSON 安全 Go
Go语言项目工程化 —— 日志、配置、错误处理规范
本章详解Go语言项目工程化核心规范,涵盖日志、配置与错误处理三大关键领域。在日志方面,强调其在问题排查、性能优化和安全审计中的作用,推荐使用高性能结构化日志库zap,并介绍日志级别与结构化输出的最佳实践。配置管理部分讨论了配置分离的必要性,对比多种配置格式如JSON、YAML及环境变量,并提供viper库实现多环境配置的示例。错误处理部分阐述Go语言显式返回error的设计哲学,讲解标准处理方式、自定义错误类型、错误封装与堆栈追踪技巧,并提出按调用层级进行错误处理的建议。最后,总结各模块的工程化最佳实践,助力构建可维护、可观测且健壮的Go应用。