org.apache.logging.log4j。<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.23.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.23.1</version>
</dependency>
<!-- Web 專用:Servlet 容器自動初始化/關閉 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.23.1</version>
</dependency>
<!-- 可選:SLF4J 橋接,統一日誌門面 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
<version>2.23.1</version>
</dependency>
log4j2.xml(放在 src/main/resources)<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorInterval="30">
<!-- 1. 定義所有 Appender -->
<Appenders>
<!-- 控制台:開發調試用 -->
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %logger{36} %L %M - %msg%n"/>
</Console>
<!-- 錯誤專用文件:每次啟動清空,只記 ERROR 及以上 -->
<File name="ErrorFile" fileName="${sys:log.dir}/error.log" append="false">
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger{36} %L %M - %msg%n"/>
</File>
<!-- 滾動文件:按大小 + 時間雙重觸發,自動壓縮歸檔 -->
<RollingFile name="RollingFile"
fileName="${sys:log.dir}/app.log"
filePattern="${sys:log.dir}/archive/%d{yyyy-MM}/app-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout charset="UTF-8" pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger{36} %L %M - %msg%n"/>
<Policies>
<SizeBasedTriggeringPolicy size="100 MB"/>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<DefaultRolloverStrategy max="20"/>
</RollingFile>
<!-- 異步 Appender:包裝上述任意 Appender,實現高吞吐 -->
<Async name="AsyncRoot" bufferSize="8192">
<AppenderRef ref="RollingFile"/>
<AppenderRef ref="ErrorFile"/>
<AppenderRef ref="Console"/>
</Async>
</Appenders>
<!-- 2. 定義 Logger -->
<Loggers>
<!-- 根 Logger:綁定異步根 Appender -->
<Root level="INFO">
<AppenderRef ref="AsyncRoot"/>
</Root>
<!-- 特定包級別覆蓋 -->
<Logger name="com.example.dao" level="DEBUG" additivity="false">
<AppenderRef ref="AsyncRoot"/>
</Logger>
<Logger name="org.springframework" level="WARN"/>
</Loggers>
</Configuration>
public class OrderService {
// 靜態常量,類名自動作為 Logger 名
private static final Logger LOG = LogManager.getLogger();
public void createOrder(OrderDTO dto) {
LOG.info("開始創建訂單: {}", dto.getOrderNo());
try {
// 業務邏輯...
LOG.debug("訂單入庫成功, ID: {}", orderId);
} catch (Exception e) {
LOG.error("創建訂單失敗", e); // 異常堆棧自動記錄
throw new BizException("下單失敗", e);
}
}
}
引入 log4j-web 後,**無需任何 web.xml 配置**,ServletContainerInitializer 會自動:
log4j2.xml。Log4jServletFilter 將請求上下文(MDC)綁定到線程,支持 %X{requestId} 等參數。
3. 銷毀時優雅關閉 Log4j,刷新異步隊列,釋放文件句柄。
若容器不支持 Servlet 3.0+(極少見),需在 web.xml 手動聲明:
<listener>
<listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
</listener>
<filter>
<filter-name>log4jServletFilter</filter-name>
<filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>log4jServletFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
| 模式 | 配置方式 | 適用場景 | 備註 |
|---|---|---|---|
| 全局異步 | JVM 參數 -Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector | 極高吞吐、日誌量大 | 所有 Logger 自動異步,需 JDK 8+ |
| 混合異步 | 配置文件用 <Async name="AsyncRoot"> 包裝具體 Appender | 大多數生產環境 | 靈活控制哪些 Appender 異步 |
| 同步 | 無特殊配置 | 開發、測試、低併發 | 異常堆棧即時可見,調試方便 |
建議:生產環境採用 **混合異步**(如上配置),核心業務 Appender 異步,控制台同步輸出以便即時觀察。
status="WARN":Configuration 節點屬性,控制 Log4j 自身啟動日誌級別,生產建議 ERROR 或 OFF。monitorInterval="30":熱加載間隔(秒),修改 log4j2.xml 30 秒內自動生效,無需重啟。${sys:log.dir}:啟動參數 -Dlog.dir=/var/log/myapp 指定日誌目錄,避免硬編碼路徑。MDC.put("traceId", traceId) → 模式 %X{traceId},鏈路追蹤必備。LogManager.shutdown(),獨立應用需手動註冊 Runtime.getRuntime().addShutdownHook(...)。掌握上述配置與最佳實踐,即可在項目中穩健落地 Log4j 2,享受高性能、可維護、可觀測的日誌系統。