好的,在 Spring Boot 中实现一个完整、灵活且生产可用的日志系统,不仅仅是引入依赖那么简单。它需要结合 Spring Boot 的约定、日志框架的特性以及良好的实践。
本文将提供一个从基础配置到高级定制的完整指南,包含完整的代码示例和解释。
我们将使用 SLF4J 作为门面(Facade),其默认实现为 Logback,因为 Spring Boot 的 starter 已经为我们默认集成了它们,无需额外引入依赖。
![图片[1]_SpringBoot实现日志系统的完整代码_知途无界](https://zhituwujie.com/wp-content/uploads/2026/01/d2b5ca33bd20260124110449-1024x495.png)
1. 基础:Spring Boot 默认日志配置
Spring Boot 默认使用 Logback,并通过 spring-boot-starter-logging 自动配置。你无需做任何事即可开始使用日志。
1.1 最简单的日志记录
在任何 Spring Bean(如 @Component, @Service, @Controller)中,你都可以直接注入 Logger 并使用。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public class MyService {
// 1. 定义一个静态的 Logger 对象,参数为当前类的 Class
private static final Logger logger = LoggerFactory.getLogger(MyService.class);
public void doSomething() {
// 2. 使用不同级别的方法记录日志
logger.trace("This is a TRACE level message.");
logger.debug("This is a DEBUG level message.");
logger.info("This is an INFO level message."); // 默认级别
logger.warn("This is a WARN level message.");
logger.error("This is an ERROR level message.");
String userName = "Alice";
Integer userId = 123;
// 3. 使用占位符 {} 来避免字符串拼接,性能更好
logger.info("User {} with ID {} has logged in.", userName, userId);
try {
// Some risky operation
1 / 0;
} catch (Exception e) {
// 4. 记录异常堆栈信息,第二个参数是 Throwable
logger.error("An unexpected error occurred while processing the request.", e);
}
}
}
1.2 日志级别(Log Level)
- TRACE < DEBUG < INFO < WARN < ERROR < FATAL (SLF4J/Logback 无 FATAL)
- Spring Boot 默认日志级别是 INFO。这意味着
DEBUG和TRACE级别的日志不会被打印。 - 你可以在
application.properties中轻松调整特定包的日志级别。
2. 核心配置:application.properties / application.yml
这是最常用的配置方式,适合大多数场景。
2.1 配置日志级别
# application.properties
# 设置根日志级别为 INFO
logging.level.root=INFO
# 设置特定包的日志级别为 DEBUG,便于调试
logging.level.com.yourcompany.yourapp.service=DEBUG
logging.level.org.springframework.web=INFO
logging.level.org.hibernate.SQL=DEBUG # 打印 Hibernate 生成的 SQL 语句
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE # 打印 SQL 参数
# 设置特定类的日志级别
logging.level.com.yourcompany.yourapp.SomeImportantClass=TRACE
# application.yml
logging:
level:
root: INFO
com.yourcompany.yourapp.service: DEBUG
org.springframework.web: INFO
org.hibernate.SQL: DEBUG
org.hibernate.type.descriptor.sql.BasicBinder: TRACE
2.2 配置日志输出
# application.properties
# 日志文件输出
logging.file.name=logs/my-app.log # 指定日志文件名,会在项目根目录下创建 logs 文件夹
# 或者
logging.file.path=./logs # 指定日志目录,默认文件名为 spring.log
# 日志格式
# 控制台日志格式
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
# 文件日志格式
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
# 日志文件大小与归档策略
# 单个文件最大 10MB,最多保留 30 个归档文件,总大小约 300MB
logging.logback.rollingpolicy.max-file-size=10MB
logging.logback.rollingpolicy.max-history=30
logging.logback.rollingpolicy.total-size-cap=300MB
# 使用基于时间的归档策略(例如:my-app-2023-10-27.0.gz)
logging.logback.rollingpolicy.file-name-pattern=logs/my-app-%d{yyyy-MM-dd}.%i.gz
3. 高级定制:使用 logback-spring.xml
当 application.properties 的配置无法满足需求时(例如:更复杂的归档策略、不同的环境使用不同的配置、异步日志等),我们需要创建 Logback 的 XML 配置文件。
命名约定:logback-spring.xml (推荐) 优于 logback.xml。因为 logback-spring.xml 可以利用 Spring Boot 的 profile 功能,实现环境隔离。
文件位置:src/main/resources/logback-spring.xml
3.1 完整的 logback-spring.xml 示例
这个配置文件包含了环境隔离、按天滚动、异步日志等高级特性。
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">
<!-- 1. 定义变量 -->
<property name="LOG_PATH" value="./logs" />
<property name="LOG_FILE" value="my-app" />
<property name="LOG_CHARSET" value="UTF-8" />
<!-- 2. 定义 Appender (输出目的地) -->
<!-- 2.1 控制台 Appender -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!-- 使用 Spring Boot 风格的默认格式 -->
<pattern>${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}</pattern>
<charset>${LOG_CHARSET}</charset>
</encoder>
<!-- 过滤器,只输出 INFO 及以上级别到控制台 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
</appender>
<!-- 2.2 滚动文件 Appender (INFO 级别) -->
<appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/${LOG_FILE}-info.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
<charset>${LOG_CHARSET}</charset>
</encoder>
<!-- 基于时间和大小的滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/archive/${LOG_FILE}-info.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
<maxFileSize>10MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<!-- 过滤器,只接受 INFO 级别的日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 2.3 滚动文件 Appender (ERROR 级别) -->
<appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/${LOG_FILE}-error.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
<charset>${LOG_CHARSET}</charset>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/archive/${LOG_FILE}-error.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
<maxFileSize>10MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<!-- 过滤器,只接受 ERROR 级别的日志 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 2.4 异步 Appender (提高性能) -->
<!-- 注意:AsyncAppender 应包装在其他 appender 外面 -->
<appender name="ASYNC_FILE_INFO" class="ch.qos.logback.classic.AsyncAppender">
<queueSize>512</queueSize> <!-- 队列大小 -->
<discardingThreshold>0</discardingThreshold> <!-- 不丢失任何日志 -->
<appender-ref ref="FILE_INFO" />
</appender>
<appender name="ASYNC_FILE_ERROR" class="ch.qos.logback.classic.AsyncAppender">
<queueSize>512</queueSize>
<discardingThreshold>0</discardingThreshold>
<appender-ref ref="FILE_ERROR" />
</appender>
<!-- 3. 根据 Spring Profile 激活不同的配置 -->
<springProfile name="dev">
<!-- 开发环境:只输出到控制台 -->
<root level="DEBUG">
<appender-ref ref="CONSOLE" />
</root>
</springProfile>
<springProfile name="prod">
<!-- 生产环境:输出到文件和控制台,使用异步 -->
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="ASYNC_FILE_INFO" />
<appender-ref ref="ASYNC_FILE_ERROR" />
</root>
</springProfile>
<!-- 4. 可以为特定包或类单独设置级别和 Appender -->
<logger name="com.yourcompany.yourapp.repository" level="DEBUG" additivity="false">
<appender-ref ref="CONSOLE"/>
</logger>
</configuration>
3.2 关键点解释
- **
<configuration scan="true">**:允许 Logback 在运行时扫描配置文件的变化并自动重新加载。 - **
<springProfile>**:这是logback-spring.xml独有的功能。只有当spring.profiles.active匹配时,里面的配置才会生效。例如,在application-prod.properties中设置spring.profiles.active=prod。 - Appender Filter:使用
LevelFilter可以精确控制 Appender 接收哪个级别的日志。ThresholdFilter则接收一个阈值以上的所有级别。 - 异步 Appender (
AsyncAppender):将日志事件放入一个队列,由另一个线程异步地进行 I/O 操作,极大地提升了应用性能,特别是在高并发场景下。 - **
<additivity="false">**:阻止日志事件向上级(root logger)传递,避免重复打印。
4. 最佳实践与建议
- 使用 SLF4J 门面:不要在代码中直接使用
Logback的类(如ch.qos.logback.classic.Logger),始终使用org.slf4j.Logger和LoggerFactory。这保证了日志实现的灵活性。 - **使用占位符
{}**:避免字符串拼接,如logger.debug("User " + name),因为当日志级别不满足时,字符串拼接操作依然会发生。使用logger.debug("User {}", name)则不会。 - 合理的日志级别:
ERROR: 系统异常、影响核心业务流程的错误。WARN: 不影响主流程的警告,如重试、降级、参数校验失败等。INFO: 重要的业务流程节点、服务启停、用户登录登出等。DEBUG: 详细的调试信息,如方法的输入输出、SQL 执行详情。TRACE: 最详细的跟踪信息,如循环内部的每一步。
- 生产环境配置:
- 使用
logback-spring.xml进行精细化配置。 - 务必配置日志文件滚动,防止磁盘被写满。
- 考虑使用异步日志 (
AsyncAppender) 提升性能。 - 将不同级别的日志分离到不同文件,便于问题排查(如只看
error.log)。 - 定期监控日志文件大小和磁盘空间。
- 使用
- 安全:切勿在日志中记录敏感信息,如密码、身份证号、银行卡号等。
通过以上步骤,你就可以在 Spring Boot 中构建一个强大、灵活且符合生产标准的日志系统。



















暂无评论内容