开心一刻

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

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

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

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

我:不太方便呀

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

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

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

前情回顾

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. 为什么魂斗罗只有128KB却能实现那么长的剧情有答案了

    PPU 首发公号:Rand_cs 本文继续讲述 NES 的基本原理,承接上文的 CPU,本文来讲述 PPU,较为复杂,慢慢来看.例子基本都是使用的魂斗罗,看完本文相信对那问题"为什么魂斗罗只 ...

  2. C#.NET AES CBC 加密

    重点: 1. KEY 和 IV 转 byte[] 时的编码. 2.要加密的字符串转 byte[] 时的编码. 3.AES 的PADDING,MODE. 4.加密后的byte[] 转字符串时的编码. 先 ...

  3. 重学前端 - react 项目第一节:创建react 项目

    重学前端 - react 项目第一节:创建react 项目 简介:之前一直使用的都是 vue 全家桶开发项目,现在在新的项目上开始使用react开发. 现在开始在重新学习一下 react 相关技术. ...

  4. AnnotationTransactionAttributeSource is only available on Java 1.5 and higher和windows同时安装jdk7和jdk8

    AnnotationTransactionAttributeSource is only available on Java 1.5 and higher和windows同时安装jdk7和jdk8 出 ...

  5. 深入理解Android View(1)

    做android其实也有一段时间了,我们每个人都会碰到一些这样或那样的问题,碰到问题了就拼命百度,可是发现,我们解决问题的能力并没有提升很多,所以我才有想总结一下我项目中所用过的相关知识,并了解一下A ...

  6. IT运维全面数字化|芯片设计行业领跑打造运维流程闭环

    在当今数字化转型的浪潮中,科技行业正经历着前所未有的变革.随着5G.人工智能.物联网等新兴技术的快速发展,企业对于高效.智能的运营模式的需求日益迫切. 芯片设计公司作为科技产业链中的关键一环,不仅要在 ...

  7. Chrome插件:​Vue.js Devtools 高效地开发和调试

    ​ 在现代前端开发中,Vue.js因其灵活性和性能优势,受到越来越多开发者的青睐.然而,随着项目规模的扩大,调试和优化变得愈发复杂.幸运的是,Vue.js Devtools的出现,为开发者提供了一套强 ...

  8. Android 中的 perfboot工具

    背景 开机首先加载bootloader,由bootloader启动kernel,然后运行init程序,有init启动Zygote,Zygote进程启动SystemServ进程,在SystemServe ...

  9. 79元国产ARM+DSP平台FFT实测分享

    T113-i国产ARM+DSP架构介绍 创龙科技SOM-TLT113是一款基于国产全志T113-i双核ARM Cortex-A7 +  HiFi4 DSP + 玄铁C906 RISC-V异构多核处理器 ...

  10. 使用EF 连接 数据库 SQLserver、MySql 实现 CodeFirst

    1.新建项目,下载Nuget安装包 创建项目需要注意几点,如果是基于 .net framework 的项目 需要选择 相应版本的 EF, 如果是跨平台则选择EF Core版本. 我这里选择的是 .ne ...