本文目录导读:

在Java中实现日志管理通常有几种主流方式,下面我会从最基础的手动实现到工业级最佳实践逐步说明。
基础方案:使用 Java 内置 Logging API
这是JDK自带的,无需额外依赖,但功能相对有限。
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.logging.FileHandler;
import java.util.logging.SimpleFormatter;
public class LogExample {
private static final Logger logger = Logger.getLogger(LogExample.class.getName());
public static void main(String[] args) {
try {
// 配置日志输出到文件
FileHandler fh = new FileHandler("app.log", true);
fh.setFormatter(new SimpleFormatter());
logger.addHandler(fh);
// 设置日志级别
logger.setLevel(Level.INFO);
// 记录日志
logger.info("应用启动成功");
logger.warning("这是一个警告信息");
logger.severe("这是一个严重错误");
} catch (Exception e) {
logger.log(Level.SEVERE, "记录日志时发生错误", e);
}
}
}
主流方案:SLF4J + Logback(推荐)
这是目前Java生态中使用最广泛的组合,性能好、配置灵活。
Step 1: Maven 依赖
<dependencies>
<!-- SLF4J 门面 -->
<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>
</dependencies>
Step 2: 配置文件 logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 定义日志输出格式 -->
<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>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 文件输出 - 按天滚动 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/application.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/application.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- 文件输出 - 按大小和数量滚动 -->
<appender name="FILE_SIZE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/app-size.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>logs/app-size.%i.log</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>10</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>10MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- 设置日志级别 -->
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
<!-- 可以为特定包设置不同级别 -->
<logger name="com.example" level="DEBUG" additivity="false">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</logger>
</configuration>
Step 3: 在代码中使用
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) {
logger.info("开始创建用户: {}", username);
try {
// 业务逻辑
logger.debug("用户创建参数: username={}", username);
// 使用占位符避免字符串拼接性能开销
logger.info("用户创建成功: username={}", username);
} catch (Exception e) {
logger.error("创建用户失败: username={}", username, e);
}
}
}
Spring Boot 集成方案
如果使用Spring Boot,配置更简单:
application.yml 配置
logging:
level:
root: INFO
com.example: DEBUG
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
file:
name: logs/spring-boot-app.log
max-size: 10MB
max-history: 30
日志管理最佳实践
1 日志分级原则
// TRACE - 最详细的调试信息(生产环境通常关闭)
logger.trace("数据库查询SQL: {}", sql);
// DEBUG - 开发调试信息(开发环境开启)
logger.debug("用户查询参数: {}", params);
// INFO - 重要业务节点(生产环境开启)
logger.info("订单创建成功: orderId={}", orderId);
// WARN - 潜在问题但不致命
logger.warn("数据库连接超时,尝试重连");
// ERROR - 严重错误需要处理
logger.error("系统异常", exception);
2 合理使用占位符
// 错误:字符串拼接(即使日志级别不输出也会执行)
logger.debug("用户: " + username + "登录");
// 正确:使用占位符(只在需要输出时计算)
logger.debug("用户: {} 登录", username);
3 捕获异常时记录完整堆栈
// 错误:只记录异常信息,丢失堆栈
logger.error("发生错误: " + e.getMessage());
// 正确:传入异常对象
logger.error("处理订单失败", e);
4 避免记录敏感信息
// 不要记录密码、身份证号等敏感信息
logger.info("用户登录: {}", maskSensitiveInfo(password));
完整实战示例
一个完整的日志管理工具类:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
public class LogManager {
// 获取日志记录器
public static Logger getLogger(Class<?> clazz) {
return LoggerFactory.getLogger(clazz);
}
// 带上下文的日志(用于链路追踪)
public static void logWithContext(Class<?> clazz, String level,
String message, Object... params) {
Logger logger = getLogger(clazz);
// 添加请求追踪ID
MDC.put("traceId", generateTraceId());
MDC.put("userId", getCurrentUserId());
try {
switch (level.toUpperCase()) {
case "DEBUG":
logger.debug(message, params);
break;
case "INFO":
logger.info(message, params);
break;
case "WARN":
logger.warn(message, params);
break;
case "ERROR":
logger.error(message, params);
break;
default:
logger.info(message, params);
}
} finally {
// 清理上下文
MDC.clear();
}
}
private static String generateTraceId() {
return UUID.randomUUID().toString().replace("-", "");
}
private static String getCurrentUserId() {
// 从安全上下文中获取用户ID
return SecurityContextHolder.getContext()
.getAuthentication().getName();
}
}
| 方案 | 适用场景 | 推荐度 |
|---|---|---|
| Java Logging API | 简单工具类 | |
| SLF4J + Logback | 企业级应用 | |
| Spring Boot 默认 | Spring项目 | |
| Log4j2 | 高性能场景 |
核心建议:
- 始终使用SLF4J作为门面,方便切换实现
- 生产环境合理设置日志级别(通常INFO以上)
- 文件日志必须配置滚动策略,防止磁盘满
- 使用占位符而非字符串拼接
- 记录异常时传入异常对象获取完整堆栈