Spring Boot日志系统详解:Logback与SLF4J的默认集成
大家好呀!👋 今天我们来聊聊Spring Boot中一个超级重要但又经常被忽视的功能——日志系统!
一、日志系统的重要性
首先,咱们得明白为什么日志这么重要?🤷♂️
想象一下,你正在玩一个超级复杂的游戏🎮,突然游戏崩溃了💥,但是没有任何提示!这时候你是不是特别想知道到底哪里出了问题?😫 日志就像是程序的"日记本"📔,它记录着程序运行时的各种信息,帮助我们:
- 排查问题🔍:当程序出错时,通过日志可以快速定位问题
- 监控运行状态👀:了解程序当前的运行情况
- 分析用户行为📊:记录用户的操作轨迹
- 性能优化⚡:通过日志分析系统瓶颈
在Spring Boot中,日志系统是开箱即用的,而且默认集成了Logback和SLF4J,这俩到底是什么呢?咱们接着往下看!👇
二、SLF4J和Logback简介
1. SLF4J - 日志门面
SLF4J(Simple Logging Facade for Java)就像是日志系统的"遥控器"📱,它定义了一套统一的日志接口,但不负责具体的日志实现。这样做的好处是:
- 解耦🔗:你的代码只依赖SLF4J接口,不关心底层用哪种日志实现
- 灵活🤸:可以随时更换底层日志框架而不需要修改代码
- 统一🔄:所有日志都通过同一个接口输出
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class MyClass {// 通过SLF4J获取Loggerprivate static final Logger logger = LoggerFactory.getLogger(MyClass.class);public void doSomething() {logger.info("这是一条信息日志");logger.error("这是一条错误日志");}
}
2. Logback - 日志实现
Logback是SLF4J的"原生实现"💎,也是Spring Boot默认的日志框架。它比传统的Log4j性能更好、功能更强大:
- 速度快⚡:执行速度比Log4j快
- 配置灵活🎛️:支持XML和Groovy配置
- 自动重载🔄:修改配置文件后自动生效
- 丰富的过滤功能🔍:可以精细控制日志输出
三、Spring Boot中的默认日志配置
Spring Boot为我们做了很多自动配置工作,让我们来看看它是如何集成Logback和SLF4J的!🔧
1. 自动配置原理
当你在Spring Boot项目中添加spring-boot-starter或spring-boot-starter-web依赖时,它会自动引入:
org.springframework.bootspring-boot-starter-logging
这个starter又引入了以下依赖:
logback-classic(包含Logback和SLF4J绑定)jul-to-slf4j(将Java Util Logging重定向到SLF4J)log4j-to-slf4j(将Log4j2重定向到SLF4J)
这样,无论你使用哪种日志API,最终都会统一到SLF4J,再由Logback处理!🎯
2. 默认日志格式
Spring Boot默认的日志输出格式是这样的:
2023-03-15 14:30:45.123 INFO 12345 --- [ main] com.example.MyClass : 这是一条日志信息
分解一下各部分含义:
2023-03-15 14:30:45.123:时间戳⏰INFO:日志级别📊12345:进程ID🆔[main]:线程名🧵com.example.MyClass:类名📦这是一条日志信息:日志内容📝
3. 默认日志级别
Spring Boot默认的日志级别是INFO,也就是说:
- DEBUG🔍:不会输出
- INFOℹ️:会输出
- WARN⚠️:会输出
- ERROR❌:会输出
四、自定义日志配置
虽然Spring Boot提供了合理的默认配置,但我们通常需要根据自己的需求进行调整。🛠️
1. 通过application.properties/yml配置
最简单的配置方式是在application.properties或application.yml中设置:
# 设置全局日志级别
logging.level.root=WARN# 设置特定包的日志级别
logging.level.com.example=DEBUG# 输出到文件 (默认在项目根目录生成spring.log)
logging.file.name=myapp.log# 或者指定日志目录 (会在该目录下生成spring.log)
logging.file.path=/var/log# 自定义日志格式
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
2. 使用logback-spring.xml高级配置
对于更复杂的配置,可以创建logback-spring.xml文件放在src/main/resources目录下:
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{36}) - %msg%nlogs/myapp.loglogs/myapp-%d{yyyy-MM-dd}.%i.log10MB301GB%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
这个配置文件做了以下事情:
- 定义了一个控制台输出器(CONSOLE)🎮
- 定义了一个文件输出器(FILE)📁,可以按日期和大小滚动
- 设置了全局日志级别为INFO📊
- 为com.example包设置了DEBUG级别🔍
- 降低了Spring框架的日志级别
3. 使用Spring Profile特定配置
Logback支持根据不同的Spring Profile使用不同的配置:
这样,在开发环境可以看到更详细的日志,而在生产环境则只记录重要信息。👨💻
五、日志级别详解
日志级别就像是信息的"紧急程度"🚨,不同级别用于不同场景:
| 级别 | 描述 | 使用场景 |
|---|---|---|
| TRACE | 最详细的跟踪信息 | 开发时追踪程序每一步执行 |
| DEBUG | 调试信息 | 开发阶段排查问题 |
| INFO | 重要的运行信息 | 生产环境记录应用程序运行状态 |
| WARN | 潜在的问题,但不影响程序运行 | 不推荐的做法、即将过期的API使用等 |
| ERROR | 错误信息,影响部分功能 | 捕获的异常、业务逻辑错误等 |
| FATAL | 严重错误,导致应用程序退出 | 系统崩溃、无法恢复的错误 |
最佳实践🎯:
- 开发环境:使用DEBUG级别
- 测试环境:使用INFO级别
- 生产环境:使用WARN或ERROR级别
六、日志使用技巧
1. 正确的日志记录方式
不好的写法❌:
logger.info("用户ID: " + userId + " 购买了商品: " + productId);
好的写法✅:
logger.info("用户ID: {} 购买了商品: {}", userId, productId);
使用占位符{}的好处:
- 性能更好⚡:只有当日志级别满足时才会拼接字符串
- 可读性更强👀:日志格式更清晰
- 避免NPE🚫:自动处理null值
2. 异常日志记录
不好的写法❌:
try {// 一些代码
} catch (Exception e) {logger.error("发生错误了");
}
好的写法✅:
try {// 一些代码
} catch (Exception e) {logger.error("处理用户订单时发生错误, 用户ID: {}", userId, e);
}
记录异常时:
- 要包含上下文信息🧐(如用户ID、订单号等)
- 要把异常对象作为最后一个参数传入
- 避免只打印
e.getMessage(),会丢失堆栈信息
3. 避免过度日志
日志不是越多越好,过多的日志会:
- 影响性能🐢
- 占用磁盘空间💾
- 增加排查问题的难度🤯
应该记录✅:
- 重要的业务操作
- 异常情况
- 关键决策点
不应该记录❌:
- 循环内部的详细处理
- 敏感信息(密码、密钥等)
- 无关紧要的调试信息
七、高级日志功能
1. MDC (Mapped Diagnostic Context)
MDC就像是一个"日志的上下文背包"🎒,可以在处理一个请求期间存储一些信息,然后在日志中输出:
// 在处理请求开始时
MDC.put("requestId", UUID.randomUUID().toString());
MDC.put("userId", getCurrentUserId());// 在日志配置中
%d{yyyy-MM-dd} [%X{requestId}] [%X{userId}] %msg%n// 在处理请求结束时
MDC.clear();
这样,同一个请求的所有日志都会带上相同的requestId和userId,方便追踪!🔍
2. 日志过滤
有时候我们想过滤掉一些不重要的日志,可以自定义过滤器:
INFO%msg%n
这个过滤器会只允许INFO及以上级别的日志输出。
3. 异步日志
为了减少日志对主业务的影响,可以使用异步日志:
5120
配置说明:
queueSize:队列大小,默认为256discardingThreshold:当队列剩余容量小于这个值时,丢弃TRACE、DEBUG和INFO级别的日志appender-ref:引用的实际appender
八、常见问题与解决方案
1. 日志冲突问题
如果你的项目依赖的库使用了不同的日志框架,可能会出现冲突。Spring Boot已经帮我们解决了大部分问题,但如果遇到冲突:
- 使用
mvn dependency:tree查看依赖树🌳 - 排除冲突的日志依赖:
some.groupsome-artifactcommons-loggingcommons-logging
2. 日志文件过大
解决方案:
- 配置合理的滚动策略(如前文示例)
- 定期清理旧日志
- 使用
totalSizeCap限制日志总大小
3. 性能问题
如果日志影响性能:
- 使用异步日志
- 适当提高日志级别
- 减少不必要的日志输出
- 使用更高效的日志格式
九、Spring Boot日志最佳实践
根据我的经验,总结了一些Spring Boot日志的最佳实践:🏆
- 合理分级:生产环境用WARN/ERROR,开发环境用DEBUG
- 统一格式:团队使用相同的日志格式
- 关键信息:记录请求ID、用户ID等关键信息
- 异常处理:总是记录完整的异常堆栈
- 避免敏感信息:不要记录密码、密钥等
- 定期审查:定期检查日志配置和日志内容
- 监控报警:对ERROR日志设置报警
- 日志归档:配置合理的日志滚动和归档策略
十、总结
Spring Boot的日志系统看似简单,实则功能强大!💪 通过本文,你应该已经掌握了:
- SLF4J和Logback的基本概念和关系🤝
- Spring Boot默认日志配置和使用方法⚙️
- 如何自定义日志配置🎨
- 日志级别和使用技巧🎯
- 高级功能和常见问题解决方案🔧
记住,好的日志习惯是成为优秀开发者的重要一步!👨💻 下次写日志时,想想这篇文章,让你的日志更加专业和有用!😊
如果你有任何问题或建议,欢迎在评论区留言!💬 我会尽力解答!Happy logging! 🎉
推荐阅读文章
-
由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)
-
如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系
-
HTTP、HTTPS、Cookie 和 Session 之间的关系
-
什么是 Cookie?简单介绍与使用方法
-
什么是 Session?如何应用?
-
使用 Spring 框架构建 MVC 应用程序:初学者教程
-
有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误
-
如何理解应用 Java 多线程与并发编程?
-
把握Java泛型的艺术:协变、逆变与不可变性一网打尽
-
Java Spring 中常用的 @PostConstruct 注解使用总结
-
如何理解线程安全这个概念?
-
理解 Java 桥接方法
-
Spring 整合嵌入式 Tomcat 容器
-
Tomcat 如何加载 SpringMVC 组件
-
“在什么情况下类需要实现 Serializable,什么情况下又不需要(一)?”
-
“避免序列化灾难:掌握实现 Serializable 的真相!(二)”
-
如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)
-
解密 Redis:如何通过 IO 多路复用征服高并发挑战!
-
线程 vs 虚拟线程:深入理解及区别
-
深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别
-
10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!
-
“打破重复代码的魔咒:使用 Function 接口在 Java 8 中实现优雅重构!”
-
Java 中消除 If-else 技巧总结
-
线程池的核心参数配置(仅供参考)
-
【人工智能】聊聊Transformer,深度学习的一股清流(13)
-
Java 枚举的几个常用技巧,你可以试着用用
-
由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)
-
如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系
-
HTTP、HTTPS、Cookie 和 Session 之间的关系
-
使用 Spring 框架构建 MVC 应用程序:初学者教程
-
有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误
-
Java Spring 中常用的 @PostConstruct 注解使用总结
-
线程 vs 虚拟线程:深入理解及区别
-
深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别
-
10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!
-
探索 Lombok 的 @Builder 和 @SuperBuilder:避坑指南(一)
-
为什么用了 @Builder 反而报错?深入理解 Lombok 的“暗坑”与解决方案(二)
相关文章:
Spring Boot日志系统详解:Logback与SLF4J的默认集成
大家好呀!👋 今天我们来聊聊Spring Boot中一个超级重要但又经常被忽视的功能——日志系统! 一、日志系统的重要性 首先,咱们得明白为什么日志这么重要?🤷♂️ 想象一下,你正在玩一个超级复…...
【C++】Json-Rpc框架项目介绍(1)
项目介绍 RPC(Remote Procedure Call)即远程过程调用,是一种通过网络从远程计算机程序中请求服务而不需要了解底层网络实现细节的一种 协议 。 RPC(Remote Procedure Call)可以使用多种网络协议进行通信,如…...
Docker 部署 PostgreSQL 数据库
Docker 部署 PostgreSQL 数据库 基于 Docker 部署 PostgreSQL 数据库一、拉取 PostgreSQL 镜像二、运行 PostgreSQL 容器三、运行命令参数详解四、查看容器运行状态 基于 Docker 部署 PostgreSQL 数据库 一、拉取 PostgreSQL 镜像 首先,确保你的 Docker 环境已正确…...
用 Go 优雅地清理 HTML 并抵御 XSS——Bluemonday
1、背景与动机 只要你的服务接收并回显用户生成内容(UGC)——论坛帖子、评论、富文本邮件正文、Markdown 等——就必须考虑 XSS(Cross‑Site Scripting)攻击风险。浏览器在解析 HTML 时会执行脚本;如果不做清理&#…...
Python爬虫从入门到实战详细版教程
Python爬虫从入门到实战详细版教程 文章目录 Python爬虫从入门到实战详细版教程书籍大纲与内容概览第一部分:爬虫基础与核心技术1. 第1章:[爬虫概述](https://blog.csdn.net/qq_37360300/article/details/147431708?spm=1001.2014.3001.5501)2. 第2章:HTTP协议与Requests库…...
window上 elasticsearch v9.0 与 jmeter5.6.3版本 冲突,造成es 启动失败
[2025-04-22T11:00:22,508][ERROR][o.e.b.Elasticsearch ] [AIRUY] fatal exception while booting Elasticsearchjava.nio.file.NoSuchFileException: D:\Program Files\apache-jmeter-5.6.3\lib\logkit-2.0.jar 解决方案: 降低 es安装版本 ,选择…...
【C++初阶】第15课—模版进阶
文章目录 1. 模版参数2. 模版的特化2.1 概念2.2 函数模版特化2.3 类模板特化2.3.1 全特化2.3.2 偏特化 3. 模版的分离和编译4. 总结 1. 模版参数 模版参数分为类型形参和非类型参数之前我们写过的大量代码,都是用模版定义类的参数类型,跟在class和typena…...
黑阈免激活版:智能管理后台,优化手机性能
在使用安卓手机的过程中,许多用户会遇到手机卡顿、电池续航不足等问题。这些问题通常是由于后台运行的应用程序过多,占用大量系统资源导致的。今天,我们要介绍的 黑阈免激活版,就是这样一款由南京简域网络科技工作室开发的手机辅助…...
C++17 新特性简解
C17 新特性简解 一、核心语言特性 1. 结构化绑定(Structured Bindings) 用途:解构复合类型(如元组、结构体)为独立变量 示例: #include <iostream> #include <tuple>int main() {// 解构 st…...
神经网络的 “成长密码”:正向传播与反向传播深度解析(四)
引言 在神经网络的神秘世界里,正向传播和反向传播是驱动模型学习和进化的核心机制。它们如同神经网络的 “左右脑”,正向传播负责信息的前向流动与初步处理,反向传播则通过优化权重参数来提升模型性能,二者相辅相成,共…...
Mujoco robosuite 机器人模型
import ctypes import os# 获取当前脚本所在的目录 script_dir os.path.dirname(os.path.abspath(__file__))# 构建库文件的相对路径 lib_relative_path os.path.join(dynamic_models, UR5e, Jb.so)# 拼接成完整的路径 lib_path os.path.join(script_dir, lib_relative_path…...
在Ubuntu 18.04下编译OpenJDK 11
在Ubuntu 18.04下编译OpenJDK 11 源码下载地址: 链接: https://pan.baidu.com/s/1QAdu-B6n9KqeBakGlpBS3Q 密码: 8lho Linux下的环境要求 不同版本的jdk会要求在不同版本的Ubuntu下编译,不要用太高版本的Ubuntu或者gcc,特别是gcc…...
K8s:概念、特点、核心组件与简单应用
一、引言 在当今云计算和容器技术蓬勃发展的时代,Kubernetes(简称 K8s)已成为容器编排领域的事实标准。它为管理容器化应用提供了高效、可靠的解决方案,极大地简化了应用的部署、扩展和运维过程。无论是小型初创公司还是大型企业…...
STM32的定时器输出PWM时,死区时间(DTR)如何计算
在 STM32F429(以及所有 STM32F4 “高级定时器”)中,死区时间由 TIMx_BDTR 寄存器的 8 位 “Dead‑Time Generator” 字段 DTG[7:0] 来配置。其计算分三步: 计算死区时钟周期 tDTS TIM1 时钟源为 APB2 定时器时钟(PCL…...
STC32G12K128单片机GPIO模式SPI操作NorFlash并实现FatFS文件系统
STC32G12K128单片机GPIO模式SPI操作NorFlash并实现FatFS文件系统 NorFlash简介NorFlash操作驱动代码文件系统测试代码 NorFlash简介 NOR Flash是一种类型的非易失性存储器,它允许在不移除电源的情况下保留数据。NOR Flash的名字来源于其内部结构中使用的NOR逻辑门。…...
ClickHouse 设计与细节
1. 引言 ClickHouse 是一款备受欢迎的开源列式在线分析处理 (OLAP) 数据库管理系统,专为在海量数据集上实现高性能实时分析而设计,并具备极高的数据摄取速率 1。其在各种行业中得到了广泛应用,包括众多知名企业,例如超过半数的财…...
MySQL基础安装和学习
MySQL 是一种开源的关系型数据库管理系统(RDBMS),由瑞典公司 MySQL AB 开发,后被 Oracle 公司收购。它是一种基于客户端/服务器架构的数据库系统,广泛应用于 Web 应用开发和企业级数据管理。 MySQL 使用 SQL(Structured Query Language,结构化查询语言)作为与数据库交…...
智能体MCP 实现数据可视化分析
参考: 在线体验 https://www.doubao.com/chat/ 下载安装离线体验 WPS软件上的表格分析 云上创建 阿里mcp:https://developer.aliyun.com/article/1661198 (搜索加可视化) 案例 用cline 或者cherry studio实现 mcp server:excel-mcp-server、quickchart-mcp-server...
再看开源多模态RAG的视觉文档(OCR-Free)检索增强生成方案-VDocRAG
前期几个工作提到,基于OCR的文档解析RAG的方式进行知识库问答,受限文档结构复杂多样,各个环节的解析泛化能力较差,无法完美的对文档进行解析。因此出现了一些基于多模态大模型的RAG方案。如下: 【RAG&多模态】多模…...
生产环境大数据平台权限管理
引言:数据资产保护的生死线 在金融行业某头部企业发生的数据泄露事件中,由于权限管理漏洞导致千万级用户信息外泄,直接经济损失超过2.3亿元。这个案例揭示了生产环境大数据平台权限管理的重要性和复杂性。本文将深入探讨从权限模型设计到实施…...
深入浅出 NVIDIA CUDA 架构与并行计算技术
🐇明明跟你说过:个人主页 🏅个人专栏:《深度探秘:AI界的007》 🏅 🔖行路有良友,便是天堂🔖 目录 一、引言 1、CUDA为何重要:并行计算的时代 2、NVIDIA在…...
FPGA系列之DDS信号发生器设计(DE2-115开发板)
一、IP核 IP(Intellectual Property)原指知识产权、著作权等,在IC设计领域通常被理解为实现某种功能的设计。IP模块则是完成某种比较复杂算法或功能(如FIR滤波器、FFT、SDRAM控制器、PCIe接口、CPU核等)并且参数可修改的电路模块,…...
Rust: 从内存地址信息看内存布局
内存布局其实有几个:address(地址)、size(大小)、alignment(对齐位数,2 的自然数次幂,2,4,8…)。 今天主要从address来看内存的布局。 说明&…...
【Dv3Admin】从零搭建Git项目安装·配置·初始化
项目采用 Django 与 Vue3 技术栈构建,具备强大的后端扩展能力与现代前端交互体验。完整实现了权限管理、任务队列、WebSocket 通信、系统配置等功能,适用于构建中后台管理系统与多租户平台。 本文章内容涵盖环境搭建、虚拟环境配置、前后端部署、项目结…...
P3416-图论-法1.BFS / 法2.Floyd
这道题虽然标签有floyd但是直接bfs也能过 其实事实证明还是bfs快,因为bfs只需要遍历特定的点,但是floyd需要考虑遍历所有可能的中介点 法1.BFS 用字典存储每个点所能普及的范围,然后用对每个点bfs进行拓展 nint(input())temp[]#xmax0;yma…...
极狐GitLab 议题和史诗创建的速率限制如何设置?
极狐GitLab 是 GitLab 在中国的发行版,关于中文参考文档和资料有: 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 议题和史诗创建的速率限制 (BASIC SELF) 速率限制是为了控制新史诗和议题的创建速度。例如,如果您将限制设置为 …...
提交到Gitee仓库
文章目录 注册配置公钥创建空白的码云仓库把本地项目上传到码云对应的空白仓库中 注册 注册并激活码云账号( 注册页面地址:https://gitee.com/signup ) 可以在自己C盘/用户/用户名/.ssh 可以看到 有id_rsa.pub 以前在GitHub注册时搞过&…...
oracle中错误总结
oracle中给表起别名不能用as,用as报错 在 Oracle 数据库中,WITH 子句(即 CTE,公共表表达式)允许后续定义的子查询引用前面已经定义的 CTE,但 前面的 CTE 无法引用后面的 CTE。这种设计类似…...
纽约大学具身智能体在城市空间中的视觉导航之旅!CityWalker:从海量网络视频中学习城市导航
作者:Xinhao Liu, Jintong Li, Yicheng Jiang, Niranjan Sujay, Zhicheng Yang, Juexiao Zhang, John Abanes, Jing Zhang, Chen Feng单位:纽约大学论文标题:CityWalker: Learning Embodied Urban Navigation from Web-Scale Videos论文链接&…...
Go语言中 defer 使用场景及深度注意事项指南
文章精选推荐 1 JetBrains Ai assistant 编程工具让你的工作效率翻倍 2 Extra Icons:JetBrains IDE的图标增强神器 3 IDEA插件推荐-SequenceDiagram,自动生成时序图 4 BashSupport Pro 这个ides插件主要是用来干嘛的 ? 5 IDEA必装的插件&…...
