Log4j 1.x 已于2015年EOL,新项目禁用;应使用SLF4J门面+Log4j2实现,配置需注意Appenders位置、filePattern格式、AsyncLogger性能参数及MDC与StructuredDataMessage区别。

Log4j 1.x 已被标记为 EOL,别再新项目里用了
Apache 官方在 2015 年就宣布 log4j-1.2.x 进入 End-of-Life 状态,不再修复任何漏洞(包括后来曝光的严重 RCE 漏洞)。现在用它,等于主动把日志模块变成攻击入口。新项目必须避开 log4j-1.2.17 及更早版本。
如果你维护的老系统还在用它,优先考虑升级到 log4j-2.x,而不是打补丁或加 JVM 参数硬拦 JNDI 查找——这类“缓解”手段容易漏掉变体利用路径。
-
log4j-1.2.17的PatternLayout不支持%X{key}嵌套结构化数据,而log4j-2.x的RoutingAppender可按 MDC 内容分流日志 -
log4j-1.x的AsyncAppender是包装式异步,实际仍走同步 I/O;log4j-2.x的AsyncLogger基于LMAX Disruptor,吞吐高一个数量级 - Maven 排除传递依赖时,要同时排除
log4j:log4j和log4j:apache-log4j-extras,后者常被忽略但同样含过期核心类
SLF4J + Log4j2 组合才是当前 Java 日志事实标准
直接依赖 log4j-core 会锁死实现,一旦换日志框架就得改所有 Logger.getLogger(...) 调用。SLF4J 提供统一门面,让日志 API 和实现解耦。
正确引入方式是:只声明 slf4j-api 编译依赖,再通过 log4j-slf4j-impl 绑定到 Log4j2。不要混用 log4j-slf4j-impl 和 slf4j-log4j12,后者桥接的是已废弃的 Log4j 1.x。
立即学习“Java免费学习笔记(深入)”;
瑞宝通B2B系统使用当前流行的JAVA语言开发,以MySQL为数据库,采用B/S J2EE架构。融入了模型化、模板、缓存、AJAX、SEO等前沿技术。与同类产品相比,系统功能更加强大、使用更加简单、运行更加稳 定、安全性更强,效率更高,用户体验更好。系统开源发布,便于二次开发、功能整合、个性修改。 由于使用了JAVA开发语言,无论是在Linux/Unix,还是在Windows服务器上,均能良好运行
org.slf4j slf4j-api 2.0.12 org.apache.logging.log4j log4j-slf4j-impl 2.20.0
- 运行时若报
ClassCastException: org.slf4j.impl.Log4jLoggerAdapter cannot be cast to org.apache.logging.log4j.spi.Logger,说明 classpath 中存在多个 SLF4J 绑定(比如同时有log4j-slf4j-impl和slf4j-simple) -
log4j-slf4j-impl要求 Log4j2 的最低版本是2.17.0,低于该版本会触发NoClassDefFoundError找不到org.apache.logging.log4j.core.util.KeyValuePair - Spring Boot 2.7+ 默认使用 Log4j2,但需确认
spring-boot-starter-logging未被意外 exclude —— 否则可能 fallback 到 JUL,导致log4j2.xml配置失效
log4j2.xml 配置里最容易写错的三处
Log4j2 的 XML 配置看似简单,但几个关键属性拼错或位置放错,会导致 Appender 不生效、日志不输出、甚至启动失败。
-
必须放在下一级,若嵌套在里,整个配置会被忽略,且无任何警告 -
RollingFile的filePattern必须含%d{yyyy-MM-dd}或类似日期占位符,否则TimeBasedTriggeringPolicy不触发归档,日志文件永远不滚动 -
AsyncLogger的includeLocation="true"会显著降低性能(每次记录都要获取堆栈),仅在调试阶段开启;生产环境应设为false,且确保PatternLayout中不包含%class、%method、%line等需定位信息的转换器
Log4j2 的 MDC 和 StructuredDataMessage 不是同一回事
MDC(Mapped Diagnostic Context)是线程绑定的字符串 Map,适合传用户 ID、请求 ID 这类轻量上下文;而 StructuredDataMessage 是 Log4j2 原生支持的结构化日志载体,可序列化为 JSON,字段类型明确。
很多人误以为往 MDC 放 JSON 字符串就能当结构化日志用,结果日志平台解析失败——因为 MDC 值始终是字符串,不会自动转成 JSON 对象字段。
logger.info(new StructuredDataMessage("audit",
Map.of("action", "login", "status", "success", "ip", request.getRemoteAddr()),
"user_action"));
-
MDC.put("trace_id", "abc123")输出后是trace_id=abc123这样的 KV 字符串;StructuredDataMessage输出的是完整 JSON object,如{"action":"login","status":"success"} -
JsonLayout默认只序列化StructuredDataMessage的data字段,不包含MDC内容;如需合并,得自定义JsonLayout的eventEol和properties属性 - WebFlux 等响应式场景中,MDC 的线程上下文会丢失,必须配合
reactor.util.context.Context+Log4j2的ThreadContext传播机制,不能只靠MDC.put()
filePattern 少了个斜杠、Appenders 标签缩进错了一层、或者没意识到 AsyncLogger 和 AsyncAppender 是两套完全不同的异步机制。上线前务必用 -Dlog4j2.debug=true 启动,看控制台是否打印出有效的 AppenderRef 绑定日志。









