Java SLF4J案例如何整合使用

wen java案例 22

本文目录导读:

Java SLF4J案例如何整合使用

  1. SLF4J + Logback 整合(最常用方案)
  2. SLF4J + Log4j2 整合
  3. Spring Boot 整合 SLF4J
  4. 高级使用技巧
  5. 常见问题解决

我来为你详细介绍SLF4J的整合使用方法,包含多个实际案例。

SLF4J + Logback 整合(最常用方案)

Maven依赖配置

<!-- SLF4J API -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>2.0.9</version>
</dependency>
<!-- Logback 实现 -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.4.11</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>1.4.11</version>
</dependency>

logback.xml 配置

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 定义日志文件路径 -->
    <property name="LOG_PATH" value="./logs"/>
    <property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"/>
    <!-- 控制台输出 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
    </appender>
    <!-- 文件输出 - 滚动日志 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/app.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 按天滚动 -->
            <fileNamePattern>${LOG_PATH}/app.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 保留30天日志 -->
            <maxHistory>30</maxHistory>
            <!-- 单个文件最大100MB -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
    </appender>
    <!-- 错误日志单独输出 -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/error.log</file>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
    </appender>
    <!-- 根日志级别 -->
    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
        <appender-ref ref="ERROR_FILE"/>
    </root>
    <!-- 特定包的日志级别 -->
    <logger name="com.example" level="DEBUG"/>
</configuration>

使用示例

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UserService {
    private static final Logger logger = LoggerFactory.getLogger(UserService.class);
    public void createUser(String username, String email) {
        logger.info("开始创建用户: {}", username);
        try {
            // 业务逻辑
            logger.debug("用户参数: username={}, email={}", username, email);
            // 占位符替换
            logger.info("用户 {} 创建成功, 邮箱: {}", username, email);
        } catch (Exception e) {
            logger.error("创建用户失败: {}", username, e);
            throw new RuntimeException("创建用户失败", e);
        }
    }
}

SLF4J + Log4j2 整合

Maven依赖

<!-- SLF4J API -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>2.0.9</version>
</dependency>
<!-- Log4j2 桥接 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j2-impl</artifactId>
    <version>2.20.0</version>
</dependency>
<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>

log4j2.xml 配置

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Properties>
        <Property name="basePath">./logs</Property>
    </Properties>
    <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="${basePath}/app.log"
                     filePattern="${basePath}/app-%d{yyyy-MM-dd}-%i.log">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
            <DefaultRolloverStrategy max="20"/>
        </RollingFile>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="RollingFile"/>
        </Root>
        <!-- 特定包级别 -->
        <Logger name="com.example" level="debug" additivity="false">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="RollingFile"/>
        </Logger>
    </Loggers>
</Configuration>

Spring Boot 整合 SLF4J

Spring Boot 自动配置(application.yml)

logging:
  level:
    root: INFO
    com.example: DEBUG
    org.springframework.web: INFO
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} - %msg%n"
    file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
  file:
    name: ./logs/spring-boot-app.log
    max-size: 100MB
    max-history: 30

Spring Boot 中的使用

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public class OrderService {
    private static final Logger log = LoggerFactory.getLogger(OrderService.class);
    // 或者使用 Lombok 注解
    // @Slf4j
    public void processOrder(String orderId) {
        log.info("Processing order: {}", orderId);
        try {
            // 业务处理
            log.debug("Order details loaded for: {}", orderId);
            // 使用MDC添加上下文信息
            MDC.put("orderId", orderId);
            log.info("Order processed successfully");
        } catch (Exception e) {
            log.error("Failed to process order: {}", orderId, e);
        } finally {
            MDC.clear();
        }
    }
}

高级使用技巧

1 使用MDC进行日志追踪

import org.slf4j.MDC;
public class RequestFilter {
    private static final Logger logger = LoggerFactory.getLogger(RequestFilter.class);
    public void handleRequest(String requestId, String userId) {
        // 设置MDC上下文
        MDC.put("requestId", requestId);
        MDC.put("userId", userId);
        try {
            logger.info("开始处理请求");
            // 业务逻辑...
            // 建议在使用MDC的代码块中使用try-with-resources
        } finally {
            // 清理MDC
            MDC.clear();
        }
    }
}

2 配置MDC输出

<!-- logback.xml 配置MDC输出 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} [%X{requestId}] [%X{userId}] - %msg%n</pattern>
    </encoder>
</appender>

3 条件日志

public class ConditionalLogging {
    private static final Logger logger = LoggerFactory.getLogger(ConditionalLogging.class);
    public void processLargeData(List<String> data) {
        // 使用 isXxxEnabled 避免不必要的字符串拼接
        if (logger.isDebugEnabled()) {
            logger.debug("Processing {} records: {}", data.size(), data);
        }
        // SLF4J 2.0+ 支持 lambda 表达式
        logger.atDebug()
              .setMessage("Processing {} records")
              .addArgument(data::size)
              .log();
    }
}

4 性能优化示例

public class PerformanceLogging {
    private static final Logger logger = LoggerFactory.getLogger(PerformanceLogging.class);
    public void optimizedLogging() {
        // 不推荐 - 即使日志级别不匹配也会执行字符串拼接
        // logger.debug("User: " + user + " with role: " + role);
        // 推荐 - 使用占位符
        logger.debug("User: {} with role: {}", user, role);
        // 或使用条件判断
        if (logger.isDebugEnabled()) {
            logger.debug("Complex object: {}", expensiveToStringMethod());
        }
        // SLF4J 2.0 推荐的lambda方式
        logger.atDebug()
              .setMessage("Complex object: {}")
              .addArgument(() -> expensiveToStringMethod())
              .log();
    }
}

常见问题解决

1 排除冲突依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-to-slf4j</artifactId>
        </exclusion>
    </exclusions>
</dependency>

2 桥接旧版日志框架

<!-- 桥接commons-logging到SLF4J -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
    <version>2.0.9</version>
</dependency>
<!-- 桥接java.util.logging到SLF4J -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jul-to-slf4j</artifactId>
    <version>2.0.9</version>
</dependency>
<!-- 桥接log4j 1.x到SLF4J -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>log4j-over-slf4j</artifactId>
    <version>2.0.9</version>
</dependency>

这些示例涵盖了SLF4J的主要使用场景和最佳实践,选择哪种方案取决于你的项目需求,对于Spring Boot项目,推荐使用SLF4J + Logback的默认配置。

抱歉,评论功能暂时关闭!