在 Spring Boot 3.5.3 中,要将默认的 Logback 替换为 Log4j2,需要以下步骤:
1. 添加 Log4j2 依赖
在 pom.xml
中排除默认的 Logback 依赖并添加 Log4j2 依赖:
<dependencies>
<!-- 排除默认的 Logback -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 添加 Log4j2 Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!-- 可选:日志配置刷新支持 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-liquibase</artifactId>
</dependency>
</dependencies>
2. 创建 Log4j2 配置文件
在 src/main/resources
目录下创建 log4j2.xml
文件:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorInterval="30">
<Appenders>
<!-- 控制台输出 -->
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<!-- 文件输出 -->
<RollingFile name="File" fileName="logs/application.log"
filePattern="logs/application-%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 />
<!-- 文件大小达到100MB时滚动 -->
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
<!-- 保留最近7天的日志 -->
<DefaultRolloverStrategy max="7"/>
</RollingFile>
<!-- 异步日志配置 -->
<Async name="Async" bufferSize="262144">
<AppenderRef ref="File"/>
</Async>
</Appenders>
<Loggers>
<!-- Spring Boot 核心日志 -->
<Logger name="org.springframework" level="INFO"/>
<Logger name="org.apache" level="WARN"/>
<!-- Hibernate 日志 -->
<Logger name="org.hibernate.SQL" level="DEBUG" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="org.hibernate.type.descriptor.sql" level="TRACE" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<!-- 自定义包日志级别 -->
<Logger name="com.myapp" level="DEBUG"/>
<!-- Root 日志设置 -->
<Root level="INFO">
<AppenderRef ref="Console"/>
<AppenderRef ref="Async"/> <!-- 使用异步文件输出 -->
</Root>
</Loggers>
</Configuration>
3. 添加 application.yml 配置
在 application.yml
中添加 Log4j2 相关配置:
spring:
application:
name: my-application
logging:
config: classpath:log4j2.xml
level:
root: info
org.springframework.web: debug
com.myapp.service: trace
# 启用日志配置热更新
log4j2:
watch: true
shutdown-hook: disable
shutdown-timeout: 30
4. 添加日志工具类
创建日志工具类以简化使用:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class LogUtil {
private LogUtil() {}
public static Logger getLogger() {
// 获取调用此方法的上层类名
return LogManager.getLogger(Thread.currentThread().getStackTrace()[2].getClassName());
}
// 方法入参日志(使用MDC添加上下文信息)
public static void logMethodEntry(Object... params) {
Logger logger = getLogger();
if(logger.isTraceEnabled()) {
String methodName = Thread.currentThread().getStackTrace()[2].getMethodName();
logger.trace("Entering: {} with params: {}", methodName, params);
}
}
}
5. 高级功能配置
5.1 日志脱敏配置
添加敏感信息脱敏配置类:
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.pattern.ConverterKeys;
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
@Plugin(name = "SafeConverter", category = "Converter")
@ConverterKeys({"safe"})
public class SafeConverter extends LogEventPatternConverter {
// 敏感信息正则匹配
private static final String SENSITIVE_PATTERN =
"\\b(?:password|passwd|pwd|secret|token|key|card|ccn|phone|tel|id)\\b[^=]*=\\s*['\"]?([^'\",\\s]+)";
protected SafeConverter() {
super("safe", "safe");
}
public static SafeConverter newInstance(String[] options) {
return new SafeConverter();
}
@Override
public void format(LogEvent event, StringBuilder toAppendTo) {
String message = event.getMessage().getFormattedMessage();
toAppendTo.append(message.replaceAll(SENSITIVE_PATTERN, "$1=***"));
}
}
在 log4j2.xml
中使用:
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %safe{%msg}%n"/>
5.2 日志指标监控
添加 Log4j2 指标采集:
import io.micrometer.core.instrument.MeterRegistry;
import org.apache.logging.log4j.LogManager;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
@Configuration
public class LogMetricsConfig {
private final MeterRegistry meterRegistry;
public LogMetricsConfig(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
@PostConstruct
public void init() {
// 采集ERROR级别的日志计数
meterRegistry.gauge("log.error.count",
LogManager.getRootLogger(),
logger -> logger instanceof org.apache.logging.log4j.core.Logger
? ((org.apache.logging.log4j.core.Logger) logger).getCount().get()
: 0
);
}
}
5.3 日志集中式管理
添加 Logstash 或 ELK 支持:
<!-- pom.xml 添加依赖 -->
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>7.3</version>
</dependency>
配置 Logstash Appender:
<Appenders>
<!-- Logstash TCP 输出 -->
<LogstashTcpSocket name="Logstash" host="logstash.mycompany.com" port="5000">
<JsonLayout compact="true" eventEol="true">
<KeyValuePair key="appName" value="${spring:spring.application.name}"/>
<KeyValuePair key="environment" value="${spring:spring.profiles.active}"/>
</JsonLayout>
</LogstashTcpSocket>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="Logstash"/>
</Root>
</Loggers>
6. Spring Boot 配置类
添加日志相关的配置管理:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import java.net.URI;
@Configuration
public class LogConfig {
/**
* 应用启动后重新加载日志配置
*/
@EventListener(ApplicationStartedEvent.class)
public void reloadLogConfig() {
LoggerContext context = (LoggerContext) LogManager.getContext(false);
context.setConfigLocation(URI.create("classpath:log4j2.xml"));
context.reconfigure();
}
}
7. 日志性能优化
7.1 异步日志配置优化
<!-- log4j2.xml -->
<AsyncLogger name="com.myapp" level="debug" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="File"/>
<!-- 队列大小 -->
<AsyncQueueSize>262144</AsyncQueueSize>
<!-- 等待策略 -->
<AsyncWaitStrategy type="Block"/>
</AsyncLogger>
7.2 日志开关控制器
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configurator;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LogController {
@GetMapping("/log/level")
public String changeLogLevel(String logger, String level) {
LoggerContext context = (LoggerContext) LogManager.getContext(false);
// 设置特定日志级别
if ("root".equalsIgnoreCase(logger)) {
Configurator.setRootLevel(Level.valueOf(level));
} else {
Configurator.setLevel(logger, Level.valueOf(level));
}
context.reconfigure();
return "Log level updated: " + logger + " -> " + level;
}
}
8. 验证日志配置
创建测试控制器验证日志输出:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LogTestController {
private static final Logger logger = LogManager.getLogger(LogTestController.class);
@GetMapping("/test/log")
public String testLog() {
logger.trace("This is a TRACE message");
logger.debug("This is a DEBUG message");
logger.info("This is an INFO message");
logger.warn("This is a WARN message");
logger.error("This is an ERROR message");
return "Log messages generated!";
}
}
访问 http://localhost:8080/test/log
后,检查控制台和日志文件验证输出。
配置总结
功能 |
配置位置 |
说明 |
---|---|---|
基础配置 |
log4j2.xml |
定义日志格式、输出目的地等 |
级别控制 |
application.yml |
设置不同包的日志级别 |
热更新 |
logging.log4j2.watch |
配置自动检测配置变化 |
异步日志 |
Async Appender |
提高日志性能 |
日志脱敏 |
SafeConverter |
保护敏感信息 |
日志监控 |
Micrometer |
采集日志指标 |
远程日志 |
LogstashTcpSocket |
集成ELK栈 |
此配置提供了:
灵活的日志级别控制
高性能的异步日志处理
敏感信息保护
监控和管理功能