1.前言
哈喽大家好啊,今天来给大家分享的是Spring开发中日志的使用。日志在软件开发中扮演着至关重要的角色,它就像是系统运行的 “黑匣子”,记录着程序执行过程中的各种信息,帮助我们定位问题、分析系统状态,对于 Spring 开发而言,掌握日志的使用更是开发过程中的必备技能,下面我将详细为大家讲解 Spring 日志的相关内容。
2.日志使用
这里给大家提供一个日志在一个应用场景的使用:
2.1 打印日志
这是启动Spring程序时就有的日志:
2.1.1 在程序中得到日志对象
在 Spring 中,要想使用日志功能,首先得获取日志对象。一般我们会借助日志框架提供的工厂类来获取。例如,使用commons-logging框架时,可以通过LogFactory来获取日志对象:
Log log = LogFactory.getLog(YourClass.class);
AI写代码
java
运行
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OrderService {
// 通过类名初始化日志对象
private static final Logger logger =
LoggerFactory.getLogger(OrderService.class);
}
AI写代码
java
运行
这种方式也是比较常见的,LoggerFactory作为日志工厂,能够根据配置为我们创建相应的日志记录器,与具体的日志实现框架相配合,实现日志功能。
2.1.2 使用日志对象打印日志
为了方便调试,我们这里编写了这样一段程序:
package springlog.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/log")
@RestController
public class LogController {
private static Logger logger = LoggerFactory.getLogger(LogController.class);
@RequestMapping("/print")
public String print(){
System.out.println("sout打印日志");
logger.info("logger打印日志");
// logger.trace("trace");
// logger.debug("debug");
// logger.warn("warn");
// logger.debug("debug");
// logger.error("error");
return "打印日志";
}
}
AI写代码
java
运行
运行起来程序,访问本地的8080端口号下的/log/print :
再回去看日志:
可以看到日志已被打出。
2.2 日志框架介绍(了解)
2.2.1 门面模式(外观模式)
门面模式(Facade Pattern)是一种 结构型设计模式,主要用于简化复杂系统的调用方式。这里用一部分代码来解释门面模式:
核心思想:
提供一个统一的高层接口,隐藏子系统的复杂性,使客户端只需与门面交互,而无需直接调用多个底层组件。
类比现实:就像电灯的 总开关,按一次就能控制所有灯(无需逐个操作卧室、客厅、走廊的灯)。
核心代码:
package springlog.facade;
public interface Light {
void on();
void off();
}
AI写代码
java
运行
package springlog.facade;
public class FacadeClient{
private LivingRoomLight livingRoomLight = new LivingRoomLight();
private BedroomLight bedroomLight = new BedroomLight();
private HallLight hallLight = new HallLight();
public void on() {
livingRoomLight.on();;
bedroomLight.on();
hallLight.on();
}
public void off() {
livingRoomLight.off();
bedroomLight.off();
hallLight.off();
}
}
AI写代码
java
运行
package springlog.facade;
public class Main {
public static void main(String[] args) {
FacadeClient facadeClient = new FacadeClient();
facadeClient.on();
facadeClient.off();
}
}
AI写代码
java
运行
日志源码 · 爱吃烤鸡翅的酸菜鱼/springboot学习 - 码云 - 开源中国
https://gitee.com/crjs-hao/springboot/tree/master/src/main/java/springlog
代码中角色划分:
角色 对应代码 作用
子系统(Subsystem) BedroomLight、LivingRoomLight、HallLight 实际执行业务的底层组件(如具体的灯)
门面(Facade) FacadeClient 聚合子系统功能,提供简化的接口(如on()/off()一键操作所有灯)
客户端(Client) Main 类 只依赖门面,不直接操作子系统
关键设计要点:
(1) 简化接口
门面类 FacadeClient 将多个灯的开关操作封装成两个方法:
public void on() {
livingRoomLight.on();
bedroomLight.on();
hallLight.on();
}
AI写代码
java
运行
客户端只需调用 facadeClient.on(),无需关心具体哪些灯被打开。
(2) 解耦客户端与子系统
客户端(Main)仅依赖 FacadeClient,不直接操作 Light 的实现类。
如果未来灯的类需要修改(例如替换为智能灯泡),只需调整 FacadeClient,客户端代码无需变动。
(3) 符合迪米特法则(最少知识原则)
客户端不需要知道子系统内部的复杂关系(如灯的依赖、初始化顺序等),只需通过门面交互。
门面模式的优点:
优点 在本例中的体现
降低复杂度 客户端无需分别操作三个灯,只需调用门面的 on()/off()
提高可维护性 修改子系统(如增加新灯)时,只需调整门面类,不影响客户端
减少耦合 客户端代码不依赖具体灯的实现类,仅依赖门面
易于扩展 新增子系统组件(如厨房灯)时,只需在门面中整合,无需修改现有客户端逻辑
门面模式通过 封装复杂细节、提供简洁接口,实现了客户端与子系统的解耦。在需要统一管理多个关联组件时(如智能家居控制、多层系统调用),它能显著提升代码的可维护性和易用性。
2.2.2 SLF4]框架介绍
SLF4J(Simple Logging Facade for Java) 是 Java 的一个 日志门面框架(日志抽象层),它本身不提供日志实现,而是提供统一的 API,允许开发者自由选择底层日志框架(如 Logback、Log4j2、JUL 等)。
特性 说明
门面模式(Facade) 提供统一的日志接口,不依赖具体实现(类似 JDBC 驱动与数据库的关系)
兼容多种日志实现 支持 Logback、Log4j2、Java Util Logging(JUL)等作为底层实现
占位符({})功能 使用 logger.info("User: {}, Age: {}", name, age) 避免字符串拼接,提高性能
优势有哪些:
✅ 解耦:代码只依赖 SLF4J API,更换日志实现无需修改业务代码。
✅ 性能优化:{} 占位符比字符串拼接更高效(避免无效的 String 操作)。
✅ 灵活性:可自由切换日志实现,适应不同环境(如测试用 Logback,生产用 Log4j2)。
✅ 兼容性:解决 Java 生态中多种日志框架并存的问题(如 Hibernate 用 JBoss Logging,Spring 用 Commons Logging)。
2.3 日志格式的说明
2023-08-20 14:22:45.678 INFO 25484 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http)
AI写代码
java
运行
各字段含义:
日期时间:精确到毫秒
日志级别:此处为INFO
进程ID
线程名([main]表示主线程)
Logger名称(通常为类名)
日志消息
时间 + 日志级别 + 进程ID + 应用名称 + 线程名称 + 类的路径 + 日志内容
AI写代码
java
运行
2.4 日志级别
2.4.1 日志级别的分类
日志的级别从高到低依次为:FATAL、ERROR、WARN、INFO、DEBUG、TRACE
- FATAL:致命信息,表示需要立即被处理的系统级错误。
- ERROR:错误信息,级别较高的错误日志信息,但仍然不影响系统的继续运行。
- WARN:警告信息,不影响使用,但需要注意的问题。
- INFO:普通信息,用于记录应用程序正常运行时的一些信息,例如系统启动完成、请求处理完成等。
- DEBUG:调试信息,需要调试时候的关键信息打印。
- TRACE:追踪信息,比DEBUG更细粒度的信息事件(除非有特殊用意,否则请使用DEBUG级别替代)
2.4.2 日志级别的使用
测试代码:
package springlog.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/log")
@RestController
public class LogController {
private static Logger logger = LoggerFactory.getLogger(LogController.class);
@RequestMapping("/print")
public String print(){
System.out.println("sout打印日志");
logger.info("logger打印日志");
logger.trace("trace");
logger.debug("debug");
logger.warn("warn");
logger.debug("debug");
logger.error("error");
return "打印日志";
}
}
AI写代码
java
运行
在实际开发中,我们需要根据不同的场景合理选择日志级别。在开发阶段,可以适当使用debug和trace级别来获取详细的调试信息,帮助我们快速定位问题。而在生产环境中,为了减少日志对系统性能的影响,通常会将日志级别设置为info或warn及以上。例如,对于一些关键业务逻辑的正常执行情况使用info级别记录,对于可能出现的潜在问题使用warn级别提醒,而对于程序中的错误则使用error级别进行详细记录。同时,我们还可以通过配置文件动态地调整日志级别,以便在不同的运行阶段灵活地控制日志的输出量和详细程度。
2.5 日志配置
2.5.1 配置日志级别
在yml配置文件中设置日志类型:
logging:
level:
root: info
main:
java:
springlog:
controller: trace
AI写代码
java
运行
我们可以看到,切换后日志就与之前不一样了。
2.5.2 日志持久化
为什么要做日志持久化?
三大关键要点:
故障追溯:保留完整的系统运行记录
性能分析:通过历史日志分析系统瓶颈
安全审计:满足等保合规要求
配置yml文件,启动项目后刷新:
logging:
level:
root: info
main:
java:
springlog:
controller: trace
file:
name: log/log.log
AI写代码
java
运行
可以看到日志被放在包中的一个文件中。
如果采用相对路径配置:
file:
path: logger/
AI写代码
java
运行
logging.file,path 设置日志的路径。
logging.file.name 设置日志的名称,可以带绝对路径或者相对路径。
如果两个配置,同时存在,以 logging.file.name为主(即优先级高)
properties配置格式:
指定完整日志路径(优先使用)
logging.file.name=/var/log/myapp/application.log
或指定目录(生成spring.log)
logging.file.path=/var/log/myapp
AI写代码
java
运行
2.5.3 配置日志文件分制
如果我们把日志都放在一个文件中,随着项目的运行,日志文件会越来越大,所以需要对日志文件进行分割。
logging:
logback:
rollingpolicy:
单个日志文件最大体积(支持KB/MB/GB单位)
max-file-size: 100MB
保留历史日志天数(滚动删除)
max-history: 30
总日志容量上限
total-size-cap: 10GB
文件名模式(时间+序号)
file-name-pattern: "${LOG_FILE}.%d{yyyy-MM-dd}.%i.log"
AI写代码
java
运行
参数 说明 生产环境推荐值
max-file-size 触发分割的单个文件大小 100-500MB
max-history 保留旧日志文件天数 15-60天
total-size-cap 日志文件总量限制 磁盘空间的70%
file-name-pattern 滚动文件命名规则 必须包含%d(日期)和%i(序号)
2.5.4 配置日志格式
logging:
pattern:
控制台格式(带ANSI颜色)
console: "%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){cyan} %clr(%-5level){magenta} %clr(%logger{35}){blue} - %msg%n"
# 文件格式(结构化)
file: "%d{ISO8601}|%thread|%-5level|%logger{35}|%msg%n"
AI写代码
java
运行
格式符号速查表
占位符 说明 示例
%d 日期时间 %d{yyyy-MM-dd HH:mm:ss}
%thread 线程名 main
%-5level 左对齐日志级别 INFO
%logger{length} 类名缩写 c.e.s.UserService
%msg 日志消息 User login success
%n 换行符
%X{key} MDC上下文值 %X{traceId}
%clr() ANSI颜色块 %clr(INFO){blue}
3.更简单的日志输出
在开发过程中,为了简化日志输出代码,提高开发效率,我们可以借助 Lombok 提供的日志注解功能。通过添加 Lombok 依赖并使用相应的注解,能够自动生成日志记录器代码,从而减少模板化代码的编写。
3.1 添加 lombok 依赖
在maven中添加Lombok依赖:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
AI写代码
XML
3.2 输出日志
引入 Lombok 依赖后,可以通过在类上添加特定的注解来自动生成日志记录器对象。最常用的就是这个:
@Slf4j
AI写代码
java
运行
功能就相当于:
private static Logger logger = LoggerFactory.getLogger(LogController.class);
AI写代码
java
运行
测试代码:
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
public class LogController {
public void log(){
log.info("--------------要输出⽇志的内容----------------");
}
}
AI写代码
java
运行
4.总结
今天的分享到这里就结束了,喜欢的小伙伴点点赞点点关注,需要所有的源代码可以去我的gitee上就可以啦你的支持就是对我最大的鼓励,大家加油!
另外最后的最后,欢迎大家加入我的社区哦,初创社区难免经验不足,请大家多多包涵,也欢迎大家前来多多交流。