微信优化

weixinyouhua

如何配置log4j?log4j配置不生效怎么办及配置文件详解

2026-09-17 19:58:37

配置log4j的核心答案是:先确定你用哪个版本(1.x还是2.x),再根据日志场景选择properties或XML配置文件,最后完成Logger、Appender、Level、Layout四要素的组装这套流程跑通,日志就能按你的预期输出。

log4j1.x和log4j2.x选哪个更合适

很多人在搜索引擎里问“log4j配置教程”时,默认指的是老牌的log4j 1.x,但2026年的当下,log4j 2.x才是真正值得投入时间的版本,这个判断不是偏好问题,而是事实问题。

log4j 1.x已经停止维护多年,存在官方确认的远程代码执行漏洞,生产环境用它等于裸奔,而log4j 2.x重写了底层架构,支持异步日志、无锁设计,吞吐量比1.x高出数倍不止,对于新项目或者还在维护的老项目升级,答案没有悬念:直接用2.x。

如果你的诉求仅仅是“把日志打出来就行”,那1.x也够用,但代价是安全风险和性能瓶颈,业内专家指出,不少企业在2026年前后遭受的日志攻击事件,根源就是log4j 1.x没升级,别再走这条路了。

log4j核心配置流程详解

整个配置过程虽然涉及多个参数,但逻辑非常线性,用一句话概括:Logger定义谁记录日志,Appender决定日志写到哪,Level设定什么级别才记录,Layout控制日志长什么样,这四个要素缺一不可。

第一步:引入依赖

Maven项目在pom.xml中加入:

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.20.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.20.0</version>
</dependency>

Gradle项目在build.gradle中加入:

implementation 'org.apache.logging.log4j:log4j-core:2.20.0'
implementation 'org.apache.logging.log4j:log4j-api:2.20.0'

记得把版本号换成当前最新的稳定版,依赖不进来,后面的一切都是空谈。

第二步:选择配置文件类型

log4j 2.x支持四种配置格式:properties、XML、JSON、YAML,最常用的是properties和XML两种。

properties格式胜在简洁,适合日志需求不复杂的场景,XML格式结构清晰,支持更高级的配置项,比如Routing、RollingFile的复杂策略,下面分开说。

log4j properties配置的具体写法

在src/main/resources下创建log4j2.properties文件,一个完整的基础配置长这样:

name=MyAppConfig
appender.console.type=Console
appender.console.name=STDOUT
appender.console.layout.type=Patte

如何配置log4j?log4j配置不生效怎么办及配置文件详解

rnLayout appender.console.layout.pattern=[%p] %d{yyyy-MM-dd HH:mm:ss} [%t] %c{1}: %m%n appender.file.type=RollingFile appender.file.name=ROLLING_FILE appender.file.fileName=${sys:user.home}/logs/myapp.log appender.file.filePattern=${sys:user.home}/logs/myapp-%d{yyyy-MM-dd}-%i.log.gz appender.file.layout.type=PatternLayout appender.file.layout.pattern=[%p] %d{yyyy-MM-dd HH:mm:ss} [%t] %c{1}: %m%n appender.file.policies.type=Policies appender.file.policies.size.type=SizeBasedTriggeringPolicy appender.file.policies.size.size=10MB appender.file.strategy.type=DefaultRolloverStrategy appender.file.strategy.max=10 rootLogger.level=info rootLogger.appenderRef.stdout.ref=STDOUT rootLogger.appenderRef.file.ref=ROLLING_FILE

关键点拆解一下:

  • rootLogger.level=info表示根日志级别为INFO,低于这个级别的DEBUG日志不会输出
  • Console类型Appender输出到控制台,适合开发调试
  • RollingFile类型Appender实现按大小滚动,单个文件超过10MB自动归档
  • 归档文件保留最近10份,避免磁盘被日志蚕食

当你在网上搜“log4j怎么配置日志级别”时,修改rootLogger.level后面的值就是答案:从高到低依次是FATAL > ERROR > WARN > INFO > DEBUG > TRACE。

log4j XML配置的进阶玩法

XML配置文件默认为log4j2.xml,同样放在src/main/resources下,基础示例如下:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
        <RollingFile name="RollingFile" fileName="logs/app.log"
                     filePattern="logs/$${date:yyyy-MM}/app-%d{yyyy-MM-dd}-%i.log">
            <PatternLayout>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</pattern>
            </PatternLayout>
            <Policies>
              <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="10MB"/>
            </Policies>
        </RollingFile>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="RollingFile"/>
        </Root>
        <Logger name="com.example" level="DEBUG" additivity="false">
            <AppenderRef ref="RollingFile"/>
        </Logger>
    </Loggers>
</Configuration>

注意<Logger name="com.example">这个配置:它单独指定了com.example包的日志级别为DEBUG,且additivity="false"表示日志不会向上传递给Root Logger,这招对定位特定包的bug非常有用。

如何配置log4j?log4j配置不生效怎么办及配置文件详解

配置生产环境的日志输出策略

本地开发时控制台日志随便打,但生产环境要是这么搞,不出三天磁盘就报警了,基于多年踩坑经验,生产配置要把握三个原则。

日志分级分文件存储

把ERROR日志和普通INFO日志分开存放,问题排查时只需翻看错误文件,避免海量普通日志淹没关键线索,你需要两个RollingFile Appender,一个过滤级别为ERROR,另一个输出INFO及以上级别。

在XML中启用Filter实现:

<RollingFile name="ErrorLog" fileName="logs/error.log" filePattern="logs/error-%d{yyyy-MM-dd}.log">
    <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
    <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    <Policies>
        <TimeBasedTriggeringPolicy/>
    </Policies>
</RollingFile>

ThresholdFilter是这里的主角:onMatch="ACCEPT" onMismatch="DENY"意味着只接受ERROR及以上级别的日志,这就是log4j2配置详解里的常见操作模式。

异步日志让性能起飞

同步日志虽然实现简单,但高并发场景下会阻塞业务线程,log4j 2.x提供的AsyncLogger优势明显,推荐在耗时敏感的业务里使用,启用方式不复杂,加入disruptor依赖,然后配置Loggers时增加asyncLogger相关设置。

更简单的做法是给配置根节点加一个系统属性引导:

<Configuration status="WARN" packages="com.example">

实际生产部署时,在启动命令中加入:

-Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector

这条命令就是打开异步日志的开关,启用后,日志写入的耗时从毫秒级降到微秒级,业务响应时间几乎不受日志影响。

log4j常见报错排查

配置过程中一定会碰壁,这里把高频问题列出来。

配置文件没生效

看到控制台输出ERROR StatusLogger No log4j2 configuration file found.时,说明log4j没找到配置文件,检查两件事:第一,log4j2.properties或log4j2.xml确实放在classpath路径下(通常是resources目录);第二,文件命名拼写正确,尤其是2.x版本比1.x多了个2,写错就是找不到。

日志重复输出

同一个日志事件被打印了两次甚至多次,这种“复读机”症状最折腾人,多数情况下是因为Logger上设置了additivity="false"漏写,导致子Logger的输出向上传递,和Appender的直接输出构成重复,排查策略:检查每个自定义Logger是否漏设

如何配置log4j?log4j配置不生效怎么办及配置文件详解

additivity="false",或者Root Logger与自定义Logger引用了同一个Appender且传递属性为true。

中文日志乱码

控制台输出乱码通常是文件编码问题,在properties中给PatternLayout加上charset:

appender.console.layout.type=PatternLayout
appender.console.layout.charset=UTF-8

XML格式对应写法是:

<PatternLayout charset="UTF-8" pattern="..."/>

配置了滚动却一直没有拆分

触发策略写了SizeBasedTriggeringPolicy,但文件超过10MB不滚动,这种情况往往是策略配置缩进或标签顺序引起解析问题,确认filePattern是否正确包含日期或计数器变量(%i),没有变量就无法生成新文件。

log4j2配置详解:从入门到实战的关键路径

如果你想在百度搜索中找到直接的“log4j2配置详解”而不依赖翻烂官方文档,记住下面这条完整路径:

  • 理解API与Core分离:log4j-api提供接口,log4j-core提供实现,项目代码中只需面向api编程,配置和运行全靠core解析
  • 配置文件自动加载:应用启动时,log4j2按classpath依次搜索log4j2-test、log4j2.properties、log4j2.xml等命名
  • 动态修改日志级别:2.x支持在运行期通过代码修改,无需重启应用:
LoggerContext context = (LoggerContext) LogManager.getContext(false);
Configuration config = context.getConfiguration();
LoggerConfig loggerConfig = config.getLoggerConfig("com.example");
loggerConfig.setLevel(Level.DEBUG);
context.updateLoggers();

这段代码将com.example包下日志级别动态调整为DEBUG,线上排障时少一次重启,少背一次变更审批单。

常见问题解答

log4j和slf4j是什么关系?

SLF4J是日志门面接口,log4j 2.x是具体实现,你可以通过slf4j调用log4j2,好处是后续切换日志框架无需改业务代码,集成时引入log4j-slf4j-impl依赖即可。

如何关闭某个类或第三方库的冗余日志?

在Loggers标签内配置Logger,为具体类或包单独设级别:

<Logger name="org.apache.http" level="WARN"/>

将org.apache.http调为WARN级别后,其内部的INFO级调试输出直接消失,日志量肉眼可见地减少。

log4j2漏洞修复目前什么状态?

log4j 2.17.0及更高版本修复了CVE-2021-44228(Log4Shell)等已知漏洞,生产项目务必保持版本不低于2.17.0,官方已从2.x的特定分支持续发布安全更新,同时配合JVM参数-Dlog4j2.formatMsgNoLookups=true可进一步加固防御面,该参数同样适用于2.10以上版本。

相关文章

2024年,SaaS软件行业碰到获客难、增长慢等问题吗?

我们努力让每一次邂逅总能超越期待