Spring Boot - 内置日志
# Spring Boot - 内置日志
# 1. Spring Boot日志概述
在专业Java开发中,使用System.out.println()进行调试是不规范的做法,应该使用标准的日志系统记录信息。Spring Boot内置了强大的日志功能,它具有以下特点:
- Spring框架内部使用
commons-logging
作为日志接口,但底层实现是开放的,可以对接多种日志框架 - Spring 5以后,
commons-logging
已被Spring团队重写并内置 - Spring支持多种日志实现:JUL(java.util.logging)、Log4j2和Logback,其中Logback是Spring Boot的默认实现
- Spring Boot不仅提供了控制台日志输出,还支持文件输出配置
- 尽管Java生态中存在多种日志框架,但Spring Boot默认配置已经能满足大多数需求
Spring Boot日志系统自动配置的原理:
- 每个Spring Boot starter依赖都引入了核心场景
spring-boot-starter
- 核心场景引入了日志功能模块
spring-boot-starter-logging
- 默认组合为
logback + slf4j
- 日志系统在应用启动早期就需要初始化,因此不是通过常规的
xxxAutoConfiguration
配置,而是通过ApplicationListener
监听器机制 - 所有日志配置都可通过
logging.*
前缀的配置项进行自定义
# 2. Spring Boot日志格式
Spring Boot默认日志输出格式示例:
2023-03-31T13:56:17.511+08:00 INFO 4944 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2023-03-31T13:56:17.511+08:00 INFO 4944 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.7]
2
默认日志格式组成部分:
- 时间和日期:精确到毫秒级别
- 日志级别:ERROR、WARN、INFO、DEBUG或TRACE
- 进程ID:当前应用的进程ID
- 分隔符:
---
用于分隔元数据和日志内容 - 线程名称:使用
[]
包围,如[main]
- Logger名称:通常是生成日志的类名
- 日志内容:实际的日志消息
注意:Logback没有FATAL级别,对应的是ERROR级别。
默认日志格式的模式定义:
%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}}){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}
# 自定义日志格式
你可以在application.yml
中修改默认日志格式:
logging:
pattern:
# 自定义控制台日志格式
console: "%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{15} ===> %msg%n"
2
3
4
也可以单独修改日期格式:
logging:
pattern:
# 仅修改日期格式部分
dateformat: yyyy-MM-dd HH:mm:ss.SSS
2
3
4
# 3. 在项目中使用日志
# 方式一:直接使用LoggerFactory
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class UserService {
// 创建日志对象,通常传入当前类
private final Logger logger = LoggerFactory.getLogger(getClass());
public void createUser(String username) {
// 使用不同级别记录日志
logger.debug("尝试创建用户: {}", username); // 参数化日志消息,避免字符串拼接
logger.info("用户创建成功: {}", username);
try {
// 业务逻辑...
} catch (Exception e) {
// 记录异常,自动包含堆栈信息
logger.error("创建用户时发生错误: {}", username, e);
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 方式二:使用Lombok的@Slf4j注解(推荐)
首先添加Lombok依赖:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
2
3
4
然后使用@Slf4j
注解简化日志对象创建:
import lombok.extern.slf4j.Slf4j;
@Slf4j // 自动创建log变量,等同于 private static final Logger log = LoggerFactory.getLogger(UserService.class);
class UserService {
public void createUser(String username) {
// 直接使用log对象记录日志
log.debug("尝试创建用户: {}", username);
log.info("用户创建成功: {}", username);
try {
// 业务逻辑...
} catch (Exception e) {
log.error("创建用户时发生错误: {}", username, e);
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 4. 日志级别配置与使用
日志级别从低到高:
- ALL: 输出所有级别的日志
- TRACE: 追踪框架内部详细流程,通常只在排查框架问题时使用
- DEBUG: 开发调试过程中的详细信息
- INFO: 关键业务流程、应用状态等重要信息(默认级别)
- WARN: 警告信息,如配置过时、性能问题等
- ERROR: 业务错误、异常信息
- FATAL: 导致应用崩溃的致命错误
- OFF: 关闭所有日志记录
重要规则:日志只会输出当前级别及更高级别的信息。例如,设置为INFO级别时,会输出INFO、WARN、ERROR和FATAL级别的日志,而不会输出DEBUG和TRACE级别的日志。
配置日志级别
在application.yml
中配置特定包的日志级别:
logging:
level:
# 整个应用的根日志级别
root: warn
# 为特定包路径配置日志级别
com.myapp.service: debug
com.myapp.controller: info
org.springframework.web: info
# 设置Hibernate SQL日志,查看生成的SQL语句
org.hibernate.SQL: debug
2
3
4
5
6
7
8
9
10
# 5. 日志分组:简化多包配置
当需要为多个相关的包配置相同的日志级别时,可以使用日志分组功能:
logging:
# 定义日志分组
group:
# 自定义分组名称
controller: com.myapp.controller, com.myapp.api, com.myapp.rest
# 数据访问层分组
dao: com.myapp.repository, com.myapp.dao, com.myapp.mapper
# 为分组设置日志级别
level:
controller: info # 控制器相关包使用info级别
dao: debug # 数据访问层包使用debug级别
2
3
4
5
6
7
8
9
10
11
12
# Spring Boot预定义的日志分组
Spring Boot为常用场景预定义了一些日志分组:
logging:
level:
# 显示web请求相关日志
web: debug
# 显示SQL查询相关日志
sql: debug
2
3
4
5
6
# 6. 日志输出到文件
默认情况下,Spring Boot日志只输出到控制台。如需同时保存到文件,可配置:
# 配置日志文件
logging:
file:
# 方式1:指定日志文件完整路径
name: D:\\logs\\myapp.log
# 方式2:仅指定目录,使用默认文件名spring.log
# path: D:\\logs
2
3
4
5
6
7
# 日志文件配置规则
logging.file.name | logging.file.path | 效果 |
---|---|---|
未设置 | 未设置 | 只输出到控制台 |
设置路径文件名 | 未设置 | 日志写入指定的文件 |
未设置 | 设置目录 | 日志写入指定目录下的spring.log文件 |
同时设置 | 同时设置 | 使用name的配置,忽略path |
示例代码:
logging:
file:
# 完整的文件路径配置,会在D盘logs目录下创建myapp.log文件
name: D:\\logs\\myapp.log
# 可选:配置日志文件内容格式(与控制台格式区分)
pattern:
file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"
2
3
4
5
6
7
8
# 7. 日志文件归档与滚动切割
为防止日志文件无限增长占满磁盘,Spring Boot提供了日志滚动和归档功能:
logging:
file:
name: D:\\logs\\myapp.log
# 日志滚动策略配置
logback:
rollingpolicy:
# 归档文件名格式,使用日期和索引
file-name-pattern: D:\\logs\\archived\\myapp.%d{yyyy-MM-dd}.%i.log.gz
# 每个日志文件达到此大小时滚动切割
max-file-size: 10MB
# 保留的归档文件最大数量/天数
max-history: 30
# 所有日志文件总大小上限
total-size-cap: 2GB
# 应用启动时是否清理历史日志(一般设为false)
clean-history-on-start: false
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
这些配置的效果:
- 当日志文件达到10MB时自动切割成新文件
- 归档文件按日期和索引命名并压缩(例如:myapp.2023-05-01.0.log.gz)
- 最多保留30天的归档日志
- 所有日志文件总大小不超过2GB,超过时删除最旧的文件
# 8. 高级自定义配置
虽然Spring Boot的默认配置能满足大多数需求,但对于复杂场景,可以使用日志框架自己的配置文件:
日志系统 | 配置文件路径 |
---|---|
Logback | logback-spring.xml、logback-spring.groovy、logback.xml |
Log4j2 | log4j2-spring.xml、log4j2.xml |
JUL (Java Util Logging) | logging.properties |
建议:优先使用带有-spring后缀的配置文件(如logback-spring.xml),这样Spring可以完全控制日志初始化过程。
# Logback高级配置示例(logback-spring.xml)
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 引入Spring Boot默认的基础配置 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<!-- 定义变量,便于统一配置和修改 -->
<property name="LOG_HOME" value="D:\\logs"/>
<property name="APP_NAME" value="myapp"/>
<!-- 控制台输出配置 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- 带有颜色的日志格式 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) [%thread] %cyan(%logger{15}) : %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 记录所有日志到文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 日志文件路径 -->
<file>${LOG_HOME}/${APP_NAME}.log</file>
<!-- 日志滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 按日期和大小滚动的文件名格式 -->
<fileNamePattern>${LOG_HOME}/archived/${APP_NAME}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!-- 单个文件大小上限 -->
<maxFileSize>10MB</maxFileSize>
<!-- 保留天数 -->
<maxHistory>30</maxHistory>
<!-- 日志文件总大小上限 -->
<totalSizeCap>2GB</totalSizeCap>
</rollingPolicy>
<encoder>
<!-- 纯文本格式,不包含ANSI颜色编码 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 单独的错误日志文件 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/${APP_NAME}-error.log</file>
<!-- 只记录ERROR级别日志 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/archived/${APP_NAME}-error.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 配置不同包的日志级别 -->
<logger name="com.myapp.service" level="INFO"/>
<logger name="com.myapp.repository" level="DEBUG"/>
<!-- SQL语句日志(不向上级传递) -->
<logger name="org.hibernate.SQL" level="DEBUG" additivity="false">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</logger>
<!-- 根日志配置 -->
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="ERROR_FILE"/>
</root>
</configuration>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# 9. 切换日志框架
Spring Boot默认使用Logback,但也支持切换到其他日志框架,如Log4j2:
<dependencies>
<!-- Web依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 排除默认日志依赖 -->
<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依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
</dependencies>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Log4j2支持YAML和JSON格式的配置文件,需额外添加依赖:
<!-- 支持YAML格式的Log4j2配置 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
</dependency>
2
3
4
5
6
7
8
9
对应的配置文件名:
- YAML格式:
log4j2.yaml
或log4j2.yml
- JSON格式:
log4j2.json
或log4j2.jsn
# 10. 日志系统最佳实践
依赖管理:导入第三方框架时,先排除其自带的日志依赖,使用Spring Boot统一管理的日志系统
<dependency> <groupId>com.example</groupId> <artifactId>some-library</artifactId> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency>
1
2
3
4
5
6
7
8
9
10配置优先级:
- 首选使用
application.properties/yml
配置简单的日志行为 - 需要复杂配置时,使用日志框架自己的配置文件(如
logback-spring.xml
) - 优先使用带
-spring
后缀的日志配置文件,便于Spring控制日志初始化
- 首选使用
日志级别使用:
- 开发环境:核心包使用DEBUG级别,第三方库使用INFO级别
- 测试环境:主要包使用INFO级别,可疑模块使用DEBUG级别
- 生产环境:全局使用WARN级别,核心业务使用INFO级别
专业集成:集成ELK(Elasticsearch, Logstash, Kibana)等日志分析系统时,只需修改日志配置文件,无需更改应用代码
编码规范:
- 始终使用SLF4J API记录日志:
import org.slf4j.Logger;
- 避免使用
System.out.println()
或其他日志API - 使用参数化日志消息:
log.info("User {} logged in", username)
而非log.info("User " + username + " logged in")
- 异常日志记录:
log.error("操作失败", exception)
,确保包含完整堆栈
- 始终使用SLF4J API记录日志:
日志内容安全:
- 不记录敏感信息(密码、令牌、完整信用卡号等)
- 考虑日志脱敏需求,实现自定义的Logback编码器