首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

SpringBoot2.7 霸王硬上弓 Logback1.3 → 不甜但解渴

编程知识
2024年07月30日 07:37

开心一刻

一大早,她就发消息质问我
她:你给我老实交代,昨晚去哪鬼混了?
我:没有,就哥几个喝了点酒
她:那我给你打了那么多视频,为什么不接?
我:不太方便呀
她:我不信,和你哥们儿喝酒有啥不方便接视频的?
她:你肯定有别的女人了!
我:你老公就坐在我旁边,我敢接?

不敢接

前情回顾

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 榜一)就提到了一些风险点

    风险点1

    里面讨论了很多,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 是不是也不能奈我们何?

不甜但解渴

霸王硬上弓

springboot2.7集成Logback1.3

参考这个,我们来配置下

  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">
            <encoder>
                <pattern>${FILE_LOG_PATTERN}</pattern>
            </encoder>
            <file>${LOG_FILE}</file>
            <rollingPolicy>
                <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.zip</fileNamePattern>
                <maxHistory>30</maxHistory>
            </rollingPolicy>
        </appender>
    
        <!-- 控制台输出 -->
        <appender name="STDOUT">
            <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

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

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

From:https://www.cnblogs.com/youzhibing/p/18327941
本文地址: http://shuzixingkong.net/article/577
0评论
提交 加载更多评论
其他文章 机器学习:详解是否要使用端到端的深度学习?(Whether to use end-to-end learning?)
详解是否要使用端到端的深度学习? 假设正在搭建一个机器学习系统,要决定是否使用端对端方法,来看看端到端深度学习的一些优缺点,这样就可以根据一些准则,判断的应用程序是否有希望使用端到端方法。 这里是应用端到端学习的一些好处,首先端到端学习真的只是让数据说话。所以如果有足够多的\((x,y)\)数据,那
机器学习:详解是否要使用端到端的深度学习?(Whether to use end-to-end learning?) 机器学习:详解是否要使用端到端的深度学习?(Whether to use end-to-end learning?) 机器学习:详解是否要使用端到端的深度学习?(Whether to use end-to-end learning?)
全网最适合入门的面向对象编程教程:27 类和对象的Python实现-Python中异常层级与自定义异常类的实现
本文主要介绍了在使用Python进行面向对象编程时,异常的层级和如何使用继承关系完成自定义自己项目中异常类,并以传感器数据采集为例进行讲解。
全网最适合入门的面向对象编程教程:27 类和对象的Python实现-Python中异常层级与自定义异常类的实现 全网最适合入门的面向对象编程教程:27 类和对象的Python实现-Python中异常层级与自定义异常类的实现 全网最适合入门的面向对象编程教程:27 类和对象的Python实现-Python中异常层级与自定义异常类的实现
【JavaScript】前端算法题(重建二叉树、反向输出链表每个节点)
前言 今天复习了一些前端算法题,写到一两道比较有意思的题:重建二叉树、反向输出链表每个节点 题目 重建二叉树: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列 {1,2,4,7,3,5,6,8} 和中序遍历序列 {
痞子衡嵌入式:MCUXpresso IDE下在线联合调试i.MXRT1170双核工程的三种方法
大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是MCUXpresso IDE下在线联合调试i.MXRT1170双核工程的三种方法。 两年前痞子衡写过一篇《i.MXRT1170下在线联合调试双核工程的三种方法(IAR篇)》,那篇文章详细介绍了 IAR 下调试 RT1170 双核工程的几
痞子衡嵌入式:MCUXpresso IDE下在线联合调试i.MXRT1170双核工程的三种方法 痞子衡嵌入式:MCUXpresso IDE下在线联合调试i.MXRT1170双核工程的三种方法 痞子衡嵌入式:MCUXpresso IDE下在线联合调试i.MXRT1170双核工程的三种方法
云原生 .NET Aspire 8.1 新增对 构建容器、编排 Python的支持
.NET Aspire 用于云原生应用开发,提供用于构建、测试和部署分布式应用的框架,这些应用通常利用微服务、容器、无服务器体系结构等云构造。2024年7月23日宣布的新 8.1 版本是该平台自 5 月正式发布以来的第一次重大更新,Microsoft 对 .NET Aspire 的第一个重大更新As
云原生 .NET Aspire 8.1 新增对 构建容器、编排 Python的支持
文件系统(十一):Linux Squashfs只读文件系统介绍
liwen01 2024.07.21 前言 嵌入式Linux系统中,squashfs文件系统使用非常广泛。它主要的特性是只读,文件压缩比例高。对于flash空间紧张的系统,可以将一些不需要修改的资源打包成压缩的只读文件系统格式,从而达到节省空间的目的。 另外还有个特性就是它可以分块解压缩,使用数据会
文件系统(十一):Linux Squashfs只读文件系统介绍 文件系统(十一):Linux Squashfs只读文件系统介绍 文件系统(十一):Linux Squashfs只读文件系统介绍
优化 GitHub 体验的浏览器插件「GitHub 热点速览」
说回本周的开源热搜项目,第一个开源项目是推荐给 GitHub 产品经理的 refined-github,这是一个来自“民间”的优化 GitHub 使用体验的浏览器插件。一体化的令牌管理平台 Infisical,能够有效地防止令牌和密钥信息泄漏。友好的联邦学习框架 Flower,开箱即用对新手友好。
优化 GitHub 体验的浏览器插件「GitHub 热点速览」 优化 GitHub 体验的浏览器插件「GitHub 热点速览」 优化 GitHub 体验的浏览器插件「GitHub 热点速览」
springboot 3.x MultipartFile 参数总是为空 参数传递不进来
场景: 在写一个统一文件上传的时候,MultipartFile参数一直传递不进来,一直为空。 排错方法: 我先是将业务简化,使用api文档进行测试,测试是前端问题还是后端问题。 简化后业务: 用apifox文档测试之后,还是显示报错 { &quot;code&quot;: 500, &quot;me
springboot 3.x MultipartFile 参数总是为空 参数传递不进来