Chapter3: SpringBoot与日志
迪丽瓦拉
2025-05-30 09:19:11
0

尚硅谷SpringBoot顶尖教程

1. 详解日志框架

日框架的来龙去脉: https://mp.weixin.qq.com/s/O3wlg8WwQ9c4DXzjC0Zc4w

市面上的日志框架:

  • JUL(Java Util Logging)
  • JCL (Jakarta Commons Logging)
  • Jboss-logging
  • logback
  • log4j、log4j2
  • slf4j (Simple Logging Facade For Java)….

上面的日志框架又可以分为日志门面(日志的抽象层)和日志实现.

日志门面(抽象层)日志实现
JCL (Jakarta Commons Logging), slf4j (Simple Logging Facade For Java) , Jboss-logginglog4j, JUL(Java Util Logging), log4j2, logback

我们在项目中选择日志框架落地只需要从左边选择一个日志抽象层, 从右边选择一个日志实现.

SpringBoot默认使用的日志框架是: Slf4j + logback

但是SpringBoot底层依赖的是Spring框架, Spring框架默认使用JCL(Jakarta Commons Logging)

1.1 slf4j到其他日志实现

如果选择了slf4j的日志抽象层, 就只需要通过导入slf4j-日志实现的桥接包, 让slf4j支持多种日志实现框架的接入.
在这里插入图片描述
在这里插入图片描述

官方适配图:http://www.slf4j.org/images/concrete-bindings.png, 提供了slf4j + logback, slf4j + log4j , slf4j + jul, slf4j + simple的日志实现方案, slf4j桥接到其他日志实现框架方案如下:

slf4j-其他日志实现上图的方案梳理:

  • slf4j ➡logback : 不用使用桥接包, 因为logback就是slf4j的日志实现框架, 导入logback相关的jar即可.
  • slf4j ➡ log4j : 使用 slf4j-log4j12.jar桥接
  • slf4j ➡ jul : 使用slf4j-jdk14.jar桥接
  • slf4j ➡ simple : 不用使用桥接包, 如果类加载器找不到日志实现, 就会使用默认的日志实现slf4j-simple.jar

1.2 其他日志实现到slf4j

SpringBoot项目中, 整合的各个框架使用的日志框架都不一样, 比如 :

SpringBoot(slf4j+logback), Spring(jcl), Hibernate(jboss-logging)…, 那么如何让它们统一使用slf4j输出日志记录呢?

官方也给我们提供了解决方案, 可以将各个日志实现框架桥接到slf4j.
在这里插入图片描述

官方适配图: http://www.slf4j.org/images/legacy.png

日志实现-slf4j

上图方案梳理:

  • JCL ➡ slf4j的桥梁: jcl-over-slf4j.jar
  • JUL ➡ slf4j的桥梁: jul-to-slf4j.jar
  • log4j ➡ slf4j的桥梁: log4j-over-slf4j.jar

2. 日志框架的项目实践

2.1 SpringBoot日志关系

SpringBoot的父依赖中自动导入了spring-boot-starter-logging作为日志的启动配置, 它依赖了logback-classic, jcl-over-slf4j, jul-to-slf4j, log4j-over-slf4j桥接包, 将各个框架的日志实现统一桥接到slf4j + logback实现, 这就是SpringBoot默认使用slf4j + logback日志实现的原因.

org.springframework.bootspring-boot-starter-logging

在这里插入图片描述

SpringBoot底层是使用slf4j+logback的方式进行日志记录, SpringBoot把其他的日志都替换成了slf4j。步骤如下:

  • 将系统中其他日志框架先排除出去;
  • 用中间包来替换原有的日志框架;
  • 再导入slf4j其他的实现;

在这里插入图片描述

上图中可以看到确认导入了其他日志实现框架桥接到slf4j的中间转换包, 我们打开jcl-over-slf4j.jar中的日志工厂类LogFactory, 可以看到里面其实是使用slf4j的日志工厂类SLF4JLogFactory进行了狸猫换太子的操作。
在这里插入图片描述

所以,如果要引入其他日志框架, 就一定要把目前使用的日志框架依赖移除掉。比如: Spring框架用的是commons-logging,SpringBoot将它排除掉了,使用整合后的日志框架。

org.springframeworkspring-corecommons-loggingcommons-logging  

SpringBoot能自动适配所有的日志框架,而且底层使用slf4j+logback的方式记录日志,引入其他框架的时候,只需要把这个框架依赖的原有日志框架排除掉。

2.2 日志框架使用

logging.filelogging.pathfor ExampleDescription
只在控制台输出
指定文件名my.log输出日志到my.log文件
指定目录/var/log输出到指定目录的spring.log文件中

logging.file与logging.path二选一进行配置.

logging.path 指定路径/var/log在linux系统磁盘中是相对于根目录。

(1) 指定日志配置文件

在classpath类路径下放上每个日志框架自己的配置文件即可;SpringBoot就不会去使用它默认的配置了。配置文件对照如下:

日志框架定制化配置文件
logbacklogback-spring.xml, logback-spring.groovy, logback.xml , logback.groovy
log4j2log4j2-spring.xml, log4j.xml
jul (java util logging)logging.properties

logback.xml 直接被日志框架识别,绕过SpringBoot,无法使用Spring的高级功能。
logback-spring.xml 日志框架不直接加载日志配置项,由SpringBoot解析日志配置,可以SpringBoot的高级功能Profile.








推荐使用 logback-spring.xml , log4j2-spring.xml方式的配置文件.

(2) 在SpringBoot全局配置文件中配置日志属性值:

## logging.file与logging.path二选一
# 在当前C盘路径下创建/spring/log目录, 使用spring.log作为默认日志文件
logging.path=C:/spring/log
# 指定日志输出文件
#logging.file=C:/spring/log/springboot.log# 指定日志输出级别
logging.level.com.aiguigu=debug
logging.level.org.springframework.jdbc=debug
logging.level.root=info## 指定控制台输出的日志格式
logging.pattern.console=[%d{yyyy-MM-dd' 'HH:mm:ss.sss}] [%C] [%t] [%L] [%-5p] %m%n
# 指定文件输出的日志格式
logging.pattern.file=[%d{yyyy-MM-dd' 'HH:mm:ss.sss}] [%C] [%t] [%L] [%-5p] %m%n

(3) 编写测试类, 执行单元测试

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// import ....
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTest {Logger logger = LoggerFactory.getLogger(this.getClass());@Testpublic void testLogger() {/*** 日志级别,SpringBoot默认的是info级别* 由低到高 trace

控制台测试日志:

[2023-03-16 22:13:15.015] [org.springframework.boot.StartupInfoLogger] [main] [57] [INFO ] Started MyTest in 9.347 seconds (JVM running for 10.341)
[2023-03-16 22:13:15.015] [com.aiguigu.spriingboot02config.MyTest] [main] [42] [DEBUG] 这是debug日志...
[2023-03-16 22:13:15.015] [com.aiguigu.spriingboot02config.MyTest] [main] [43] [INFO ] 这是info日志...
[2023-03-16 22:13:15.015] [com.aiguigu.spriingboot02config.MyTest] [main] [44] [WARN ] 这是warn日志...
[2023-03-16 22:13:15.015] [com.aiguigu.spriingboot02config.MyTest] [main] [45] [ERROR] 这是error日志...

C盘目录下的日志:
在这里插入图片描述

logging.file=C:/spring/log/springboot.log指定日志输出文件测试结果:
在这里插入图片描述

2.3 切换日志框架

将logback日志框架切换成log4j。切换到slf4j+log4j日志框架步骤:

  • 排除 logback-classic日志框架依赖的jar, 排除其他日志框架的桥接包;

  • 添加log4j日志框架依赖的jar;

从下面slf4j+log4j适配图中可以发现, 需要剔除jcl-over-slf4j.jar, jul-to-slf4j.jar ; 添加slf4j-log412.jar, log4j.jar
在这里插入图片描述

实操步骤:

排除logback-classic日志框架的依赖
在这里插入图片描述

导入slf4j-log4j12依赖,相关的依赖也一起导入了
在这里插入图片描述

pom.xml文件中的体现:

org.springframework.bootspring-boot-starter-weblogback-classicch.qos.logbackjul-to-slf4jorg.slf4jlog4j-over-slf4jorg.slf4jjcl-over-slf4jorg.slf4j

org.slf4jslf4j-log4j12

在recources目录下添加log4j.properties配置文件,该配置文件将被log4j日志框架识别
在这里插入图片描述
再次执行单元测试, 控制台输出日志报错了

java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactoryat org.springframework.test.context.junit4.SpringJUnit4ClassRunner.(SpringJUnit4ClassRunner.java:96)
// ......
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactoryat java.net.URLClassLoader.findClass(URLClassLoader.java:381)at java.lang.ClassLoader.loadClass(ClassLoader.java:424)at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)at java.lang.ClassLoader.loadClass(ClassLoader.java:357)... 16 more

经过分析, log4j日志实现可能依赖了appache的jcl日志框架的LogFactory类, 所以我们将上面排除的jcl-over-slf4j取消排除, 重新运行后控制台是按照log4j.properties配置的日志格式打印日志, 至此日志框架从slf4j + logback 切换到 slf4j + log4j成功.

2023-03-16 22:45:56  [ main:10895 ] - [ INFO ]  Started MyTest in 10.576 seconds (JVM running for 11.532)
2023-03-16 22:45:56  [ main:10953 ] - [ INFO ]  这是info日志...
2023-03-16 22:45:56  [ main:10953 ] - [ WARN ]  这是warn日志...
2023-03-16 22:45:56  [ main:10953 ] - [ ERROR ]  这是error日志...

2.4 切换日志组件启动器

spring-boot-starter-logging切换成spring-boot-starter-log4j2, 从而实现slf4j+log4j2日志框架组合; 首先排除spring-boot-starter-logging

org.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-logging

再添加spring-boot-starter-log4j2的依赖

org.springframework.bootspring-boot-starter-log4j2

Ctrl + Alt + U 查看依赖分析图, 自动导入了中间转换的依赖包 log4j-slf4j-impl
在这里插入图片描述

如果没有配置,系统会读取默认的spring-boot-{version}.RELEASE.jar的logging包下面的默认xml配置。
在这里插入图片描述
在resources目录下添加log4j2-spring.xml的日志配置文件:
在这里插入图片描述
启动应用,查看启动日志,已经切换到log4j2日志框架配置的日志格式了。

[20:09:50:068] [DEBUG] - com.aiguigu.spriingboot02config.MyTest.testLogger(MyTest.java:42) - 这是debug日志...
[20:09:50:068] [INFO] - com.aiguigu.spriingboot02config.MyTest.testLogger(MyTest.java:43) - 这是info日志...
[20:09:50:069] [WARN] - com.aiguigu.spriingboot02config.MyTest.testLogger(MyTest.java:44) - 这是warn日志...
[20:09:50:069] [ERROR] - com.aiguigu.spriingboot02config.MyTest.testLogger(MyTest.java:45) - 这是error日志...

相关内容