一文说透日志框架发展史及springboot日志
日志框架发展史
jdk官方 sun 公司, 开发了一个日志框架 jul ,也就是 java.util.logging ;
于是jdk官方 开发了 日志门面 JCL , jakarta Commons Logging JCL ( 不实现日志功能,整合日志的);
老程序员A 发现JCL并不好用, 离开了apatch, 独自开发了日志门面 slf4j . ( 不实现日志功能,整合日志的) 需要用 适配器、桥接器。
apatch开发了 log4j2 ,其性能比log4j高出好多倍。于是log4j淘汰。
老程序员A 又开发了logback , 性能比log4j2高出好多倍.
log4j的作者觉得jcl不好用,自己写了一个新的接口api,那么就是slf4j。关于slf4j的集成图如下所示:

所以最佳组合是slf4j 和logback,因为作者是一个。
那么如果使用slf4j(门面)+Log4j(实现) :必须加桥接器
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactld> </dependency> <dependency) <!--添加s1f4j一log4j的桥接器 <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </dependency>
import org.slf4j.Logger;
// slf4j(门面),不是具体的日志实现获得Logger日志记录器
//Logger logger = Logger.getLogger(Test.class);
//而是 门面日志器接受
Logger logger = LoggerFactory.getLogger(Test.class);
logger.info("info");如果是Jul(实现) +JCl(门面)
<!--引入JCL门面依赖--> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency>
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
\\LogFactory
Log log = LogFactory.getLog(Test.class);
log.trace('trace');JCL动态查找机制进行日志实例化,执行顺序为:commons-logging.properties---->系统环境变量------->log4j--->jul--->simplelog---->nooplog
<dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version></version> </dependency>
spring默认整合了:logback日志的集成

SpringBoot底层也是使用slf4j+logback的方式进行日志记录
SpringBoot也把其他的日志都替换成了slf4j;
log4j 适配: log4j-to-slf4j (将log4j转成slf4)
jul适配:jul-to-slf4j (将jul转成slf4)
这两个适配器都是为了适配Spring的默认日志:jcl
SpringBoot日志使用
日志级别
logging: level: root: "warn" org.springframework.web: "debug" com.lingling: "error" //包下日志等级设置
日志格式
2025-12-01 14:01:34.665 TRACE 10072 --- [ main] com.ruoyi.Application : 跟踪 2025-12-01 14:01:34.665 DEBUG 10072 --- [ main] com.ruoyi.Application : 调试 2025-12-01 14:01:34.665 INFO 10072 --- [ main] com.ruoyi.Application : 信息 2025-12-01 14:01:34.665 WARN 10072 --- [ main] com.ruoyi.Application : 警告 2025-12-01 14:01:34.665 ERROR 10072 --- [ main] com.ruoyi.Application : 异常
%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}2025-12-01 14:01:34.665
日期和时间:毫秒精度,易于排序。
%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint}
%clr 当前内容的颜色 {faint}
(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}})
括号中就是要显示的内容
%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}
${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}
${value:value2} springboot的占位符 + null条件的表达式(如果value为null 使用value2)
LOG_DATEFORMAT_PATTERN: 系统环境变量中的值, springboot底层会根据对应的配置项将值设置到对应的环境变量中
如:LOG_DATEFORMAT_PATTERN=logging.pattern.dateformat 可以在官网4.7章节中看到对应的关系。或者去源码中看
%d{-yyyy-MM-dd HH:mm:ss.SSS}
%d logbak的日期显示方式:
{-yyyy-MM-dd HH:mm:ss.SSS} 日期的格式
TRACE
日志级别:ERROR,WARN,INFO,DEBUG,或TRACE。
%clr(${LOG_LEVEL_PATTERN:-%5p})
%clr 颜色 会根据不同的日志级别输出对应的颜色
${LOG_LEVEL_PATTERN:-%5p}
%5 代表当前内容所占字符长度
p 输出日志事件的级别。
10072
进程ID。
%clr(${PID:- }){magenta}
%clr {magenta}
${PID:- } springboot的占位符 + null条件的表达式(如果value为null 使用value2)
PID 是系统环境变量中的进程ID(由系统分配)
---
一个---分离器来区分实际日志消息的开始。
[ main]
线程名称:用方括号括起来(对于控制台输出可能会被截断)。
com.ruoyi.Application
记录日志的类
: 跟踪
日志消息。
文件输出
logging.file.name
可以设置文件的名称, 如果没有设置路径会默认在项目的相对路径下(项目的根目录下)
还可以指定路径+文件名:name: D:/sawadika.log
logging.file.path
不可以指定文件名称, 必须要指定一个物理文件夹路径,会默认使用spring.log
日志迭代(轮转):比如日志文件超出了设定的大小,归档。并保留天数后可删除
如果使用自定义日志配置文件, 会使用springboot中全局配置文件里的logging相关配置失效。
结合SpringBoot提供Profile来控制日志的生效
注意:如果要使用 springProfile ,一定要将日志配置文件的文件名改成logback-spring.xml, 因为 logback.xml 会在Springboot容器加载前先被logback给加载到, 那么由于logback无法解析springProfile 将会报错:
ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]] ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProfile], current ElementPath is [[configuration][springProfile]]
<configuration>
<!--还可以引用SpringBoot全局配置文件中的配置项-->
<springProperty scope="context" name="dateformat" source="logging.pattern.dateformat" defaultValue="yyyy-MM-dd HH:mm:ss.SS"
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- 使用springProfile激活dev的配置 -->
<springProfile name="dev">
<pattern>%d{${dateformat}}} [%thread] %-5level %logger{100} ======= %msg%n</pattern>
</springProfile>
<!-- 如果不是dev 走这里 -->
<springProfile name="!dev">
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{100} ++++++ %msg%n</pattern>
</springProfile>
</encoder>
</appender>
</configuration>切换日志框架
将 logback切换成log4j2
将logback的场景启动器排除(slf4j只能运行有1个桥接器.)
添加log4j2的场景启动器
添加log4j2的配置文件
<dependencies> <dependency> <!--starter-web里面自动添加starter-logging 也就是logback的依赖--> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <!--排除starter-logging 也就是logback的依赖--> <exclusion> <artifactId>spring-boot-starter-logging</artifactId> <groupId>org.springframework.boot</groupId> </exclusion> </exclusions> </dependency> <!--Log4j2的场景启动器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency> </dependencies>
将 logback切换成log4j
要将logback 与slf4j的桥接器排除
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <artifactId>logback-classic</artifactId> <groupId>ch.qos.logback</groupId> </exclusion> </exclusions> </dependency>
添加log4j的桥接器
<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </dependency>
添加log4j的配置文件
#trace<debug<info<warn<error<fatal log4j.rootLogger=trace, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
本文原创,转载必追究版权。


