开心一刻

一大早,她就发消息质问我

她:你给我老实交代,昨晚去哪鬼混了?

我:没有,就哥几个喝了点酒

她:那我给你打了那么多视频,为什么不接?

我:不太方便呀

她:我不信,和你哥们儿喝酒有啥不方便接视频的?

她:你肯定有别的女人了!

我:你老公就坐在我旁边,我敢接?

前情回顾

SpringBoot2.7还是任性的,就是不支持Logback1.3,你能奈他何 讲了很多,总结下来就两点

  1. SpringBoot 2.7.x 默认依赖 Logback 1.2.x,不支持 Logback 1.3.x

    如果强行将 Logback 升级到 1.3.x,启动会报异常

    Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/impl/StaticLoggerBinder
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.getLoggerContext(LogbackLoggingSystem.java:304)
    at org.springframework.boot.logging.logback.LogbackLoggingSystem.beforeInitialize(LogbackLoggingSystem.java:118)
    at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationStartingEvent(LoggingApplicationListener.java:238)
    at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:220)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:178)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:171)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:145)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:133)
    at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:79)
    at org.springframework.boot.SpringApplicationRunListeners.lambda$starting$0(SpringApplicationRunListeners.java:56)
    at java.util.ArrayList.forEach(ArrayList.java:1249)
    at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:120)
    at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:56)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:299)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1289)
    at com.qsl.Application.main(Application.java:15)
    Caused by: java.lang.ClassNotFoundException: org.slf4j.impl.StaticLoggerBinder
    at 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)
    ... 17 more

    原因也分析过了

    spring-boot-2.7.18 依赖 org.slf4j.impl.StaticLoggerBinder,而 logback 1.3.x 没有该类

  2. SpringBoot 2.7.x 支持 Logback 1.3.x 也不是没办法,但有一些限制,同时也存在一些未知的风险

    关于未知的风险,相信大家都能理解,为什么了,这就好比从 JDK8 升级到 JDK 11,你们为什么不敢升,一个道理,因为大版本的升级,变动点往往比较多,甚至会移除掉低版本的一些内容,编译期报错还算直观的(我们可以根据报错调整代码),如果是运行期报错那就头疼了,上了生产就算事故了,这锅你敢背吗?
    所以大版本的升级,意味着我们不但要修复编译期的错,还要进行全方位的测试,尽可能的覆盖所有场景,以排除运行期可能存在的任何异常。业务简单还好,如果业务非常庞大,这个全量测试是要花大量时间的,不仅开发会口吐芬芳,测试也会 mmp
    Upgrade to SLF4J 2.0 and Logback 1.4 进行了一些讨论,wilkinsona(Spring Boot 目前 Contributor 榜一)就提到了一些风险点

    里面讨论了很多,Logback 的 Contributor 榜一大哥 ceki 也在里面进行了很多说明与答疑,感兴趣的可以详细看看
    总之就是:通过调整配置,SpringBoot 2.7.x 可以支持 Logback 1.3.x,但风险需要我们自己承担

换个角度想想,我们应该是能理解 Spring Boot 官方的

  1. Logback 不是那么熟,只能通过 Logback 官方说明知道变动点(能保证事无巨细列全了?),若变动点太多,不可能每个点都去核实
  2. Spring Boot 那么庞大,集成了那么多功能,怕是榜一大哥也不能熟记所有细节(我们敢保证对我们负责的项目的所有细节都了如指掌吗),所以也没法评估升级到 Logback 1.3.x 会有哪些点受影响

所以求稳,Spring Boot 2.x.x 不打算集成 Logback 1.3.x
但是,如果我们也任性一回,非要强扭这个瓜,Spring Boot 是不是也不能奈我们何?

霸王硬上弓

参考这个,我们来配置下

  1. 关闭 Spring BootLoggingSystem

    @SpringBootApplication
    public class Application { public static void main(String[] args) {
    System.setProperty("org.springframework.boot.logging.LoggingSystem", "none");
    SpringApplication.run(Application.class, args);
    }
    }
  2. 配置文件用 logback.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
    <property name="LOG_FILE" value="/logs/spring-boot-2_7_18.log"/>
    <property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS}|%level|%t|%line|%-40.40logger{39}:%msg%n"/> <!-- 按照每天生成日志文件-->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
    <pattern>${FILE_LOG_PATTERN}</pattern>
    </encoder>
    <file>${LOG_FILE}</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.zip</fileNamePattern>
    <maxHistory>30</maxHistory>
    </rollingPolicy>
    </appender> <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
    <pattern>${FILE_LOG_PATTERN}}</pattern>
    </encoder>
    </appender> <root level="${loglevel:-INFO}">
    <appender-ref ref="STDOUT" />
    <appender-ref ref="FILE" />
    </root>
    </configuration>

启动确实正常了,我们加点简单的业务日志,发现日志也输出正常

2024-07-26 16:46:48.609|INFO|http-nio-8080-exec-1|525|o.s.web.servlet.DispatcherServlet       :Initializing Servlet 'dispatcherServlet'
2024-07-26 16:46:48.610|INFO|http-nio-8080-exec-1|547|o.s.web.servlet.DispatcherServlet :Completed initialization in 0 ms
2024-07-26 16:46:48.632|INFO|http-nio-8080-exec-1|23|com.qsl.web.TestWeb :hello接口入参:青石路
2024-07-26 16:46:50.033|INFO|http-nio-8080-exec-3|23|com.qsl.web.TestWeb :hello接口入参:青石路
2024-07-26 16:46:50.612|INFO|http-nio-8080-exec-4|23|com.qsl.web.TestWeb :hello接口入参:青石路
2024-07-26 16:46:51.150|INFO|http-nio-8080-exec-5|23|com.qsl.web.TestWeb :hello接口入参:青石路
2024-07-26 16:46:51.698|INFO|http-nio-8080-exec-6|23|com.qsl.web.TestWeb :hello接口入参:青石路
2024-07-26 16:46:52.203|INFO|http-nio-8080-exec-7|23|com.qsl.web.TestWeb :hello接口入参:青石路

日志文件写入也正常

这不仅解渴,还很甜呀

但不要甜的太早,这仅仅只是一个 demospring-boot-2_7_18,没有业务代码,简单的不能再简单了,你们要是以此来判断甜与不甜,那就大错特错了;应用到项目中,不但要保证能够正常启动,还要保证已有的所有业务能够正常运行,至于计划中的业务,那就将来再说,谁知道明天和意外哪个先来,认真过好当下!
初步尝试,是可行的,所以你们大胆的去试吧,但要做好全方位的业务测试

wilkinsona 提到了,关闭 Spring BootLoggingSystem 后,用的是 Logback 的默认配置,配置文件必须是 logback.xml 而不能是 logback-spring.xml;虽然榜一大哥的话很权威,但我们主打一个任性,就想来试试 logback-spring.xml,会有什么样的结果,直接将 logback.xml 改名成 logback-spring.xml,能启动起来,但有一堆 debug 日志,重点是

日志没有写入文件

wilkinsona 诚不欺我!

原理分析

关闭了 Spring BootLoggingSystem 后,日志相关的全权交给 Logback,而关于 Logback 的配置文件加载,我是写过一篇详解的:从源码来理解slf4j的绑定,以及logback对配置文件的加载,直接跳到总结部分,有这么一段

编译期间,完成slf4j的绑定以及logback配置文件的加载。slf4j会在classpath中寻找org/slf4j/impl/StaticLoggerBinder.class(会在具体的日志框架如log4j、logback等中存在),找到并完成绑定;同时,logback也会在classpath中寻找配置文件,先找logback.configurationFile、没有则找logback.groovy,若logback.groovy也没有,则找logback-test.xml,若logback-test.xml还是没有,则找logback.xml,若连logback.xml也没有,那么说明没有配置logback的配置文件,那么logback则会启用默认的配置(日志信息只会打印在控制台)

虽说 Logback1.1.17,而不是 1.3.14,但对配置文件的加载应该是没变的

大家注意看我的措辞:应该,这样即使变了,你们也不能说我,因为我说的是应该

保险起见,你们应该去看下 1.3.14 的源码!

这也是为什么配置文件是 logback.xml 的时候,日志能正常写入文件,而是 logback-spring.xml 时候,日志不能写入日志文件的原因,因为 Logback 不认 logback-spring.xmlSpring Boot 才认!
至于 Spring Boot LoggingSystem 嘛,等我掌握了再来和你们聊,一定要等我哟

总结

Spring Boot 2.x.x 默认依赖 Logback 1.2.x,不支持 Logback 1.3.x,但是通过设置

System.setProperty("org.springframework.boot.logging.LoggingSystem", "none");

启动时不报错的,再结合 logback.xml,日志是能够正常写入日志文件的;但是保险起见,还是不推荐升级到 Logback 1.3.x

能不动就不要动,改好没绩效,改出问题要背锅,吃力不讨好,又不是不能跑

如果一定要升级,那就做好全量测试,把所有业务场景都覆盖到

SpringBoot2.7 霸王硬上弓 Logback1.3 → 不甜但解渴的更多相关文章

  1. iPhone8、Note8、Mate10硬上面部识别:是潮流还是无奈

    ​ 对于手机厂商来说,时不时抛出几个全新概念当噱头来引起业界和大众的关注,已经成为了必然套路.其中有很多改变智能手机发展进程的技术--双摄像头.指纹识别.快充等,但也有很多纯粹来凑数,看似新潮却始终没 ...

  2. SpringBoot2.0(三) 文件上传

    SpringBoot中发起文件上传示例: /** * 文件上传 * @param multipartFile * @param path * @return */ @RequestMapping(va ...

  3. SpringBoot2.x设置文件上传文件的大小

    The field file exceeds its maximum permitted size of 1048576 bytes spring: # 设置文件上传文件大小 servlet: mul ...

  4. 【转】成功在AMD主机上用虚拟机安装原版雪豹

    转载地址:http://www.jzh.me/archives/205.html/comment-page-1 一直都很想安装苹果的系统,当雪豹出来的时候就更加想了,但是自己的机器是AMD的,而且还是 ...

  5. Python之路,Day7 - Python基础7 面向对象

    本节内容:   面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法.     引子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战> ...

  6. Python之路第一课Day6--随堂笔记(面向对象 )

    本节内容: 1. 面向对象编程介绍 2. 为什么要用面向对象进行开发? 3. 面向对象的特性:封装.继承.多态 4. 类.方法   一.面向过程 VS 面向对象  1. 编程范式 编程是 程序 员 用 ...

  7. EF7 Code First Only-所引发的一些“臆想”

    At TechEd North America we were excited to announce our plans for EF7, and even demo some very early ...

  8. python之面向对象与构造函数

    一.面向对象介绍 不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路, 大多数语言只支持一种编程范式, 当然也有些语言可以同时支持多种编程范式. 两种最重要的编程范式分别是面向过程编程 ...

  9. Java类WebServer及中间件拿webshell方法总结

    0.序 原文名称:Tomcat.Weblogic.JBoss.GlassFish.Resin.Websphere弱口令及拿webshell方法总结 原文from:http://www.hack80.c ...

  10. python走起之第六话

    面向过程 VS 面向对象 编程范式 编程是 程序 员 用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程 , 一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓条条大 ...

随机推荐

  1. 一分钟部署prometheus&grafana全方面监控SpringBoot项目

    0x01 创建目录 找一个你喜欢的地方,创建项目根目录 example: [root@demo-78 ~]# mkdir /data/prometheus 0x02 创建配置文件 进入到项目根目录: ...

  2. AutoLayout与UIbutton

    1.UIButton贴近右边,高度固定,宽度跟随标题变化 class TestButton: UIButton { } class ViewController: UIViewController { ...

  3. jquery中封装了三种ajax请求方式

          // jQuery中封装了3种 ajax 请求方式         // 1, get请求方式         // 2, post请求方式         // 3, 综合请求方式    ...

  4. LINQ to Entities does not recognize the method 'System.String ToString()' method

    LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method ca ...

  5. 点击li 该li变色

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  6. Redis的特点什么是?

    a.支持多种数据结构,如 string(字符串). list(双向链表).dict(hash表).set(集合).zset(排序set).hyperloglog(基数估算) b.支持持久化操作,可以进 ...

  7. 增补博客 第六篇 python 电子算盘

    珠算测试器 题目描述]设计一个珠算测试器,要求能够完成珠算加减法的测试.具体的要求功能如下:(1)用户启动测试,输入用户名后系统随机生成特定数目的加减法测试题:(2) 要求测试使用表盘式或数字时秒表进 ...

  8. CAT监控指标

    CAT监控指标 CAT 是基于 Java 开发的实时应用监控平台.官方文档:https://github.com/dianping/cat CAT提供以下几种报表:Transaction报表 一段代码 ...

  9. 05-Python函数

    函数定义与调用 函数由以下几个部分组成: 函数名 函数参数 函数体 返回值 定义一个函数: def showMyName(name): #定义函数 print(name) showMyName(&qu ...

  10. 安卓内核编译:关闭"error, forbidden warning"

    安卓内核编译:关闭error, forbidden warning 背景 最近在编译Android kernel时,遇到error, forbidden warning, 导致编译中断,大大降低了de ...