Spring Boot 3.5.3 集成 Log4j2 日志系统

发布于:2025-09-03 ⋅ 阅读:(16) ⋅ 点赞:(0)

在 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栈

此配置提供了:

  1. 灵活的日志级别控制

  2. 高性能的异步日志处理

  3. 敏感信息保护

  4. 监控和管理功能


网站公告

今日签到

点亮在社区的每一天
去签到