开源轮子 - Logback 和 Slf4j
spring boot内置:Logback
文章目录
- spring boot内置:Logback
- 一:Logback强在哪?
- 二:简单使用
- 三:把 log4j 转成 logback
- 四:日志门面SLF4J
- 1:什么是SLF4J
- 2:SLF4J 解决了什么痛点
- 3:SLF4J 比 Log4J 强在哪
一:Logback强在哪?
- 非常自然地实现了 SLF4J,不需要像 Log4j 和 JUL 那样加一个适配层

- 是Spring Boot默认的[一旦某款工具库成为了默认选项,那就说明这款工具已经超过了其他竞品]
- 支持自动重新加载配置文件,不需要另外创建扫描线程来监视
- 性能大大的提升
logback手册:https://github.com/itwanger/logback-chinese-manual
二:简单使用
<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version>
</dependency>
Maven 会自动导入另外两个依赖:

package org.example.open_source.log;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** <p>* 功能描述:logback demo test* </p>** @author cui haida* @date 2024/04/05/21:02*/
public class LogbackDemo {static Logger logger = LoggerFactory.getLogger(LogbackDemo.class);public static void main(String[] args) {logger.info("info");logger.debug("debug");logger.error("error");logger.warn("warn");}
}

Logger 和 LoggerFactory 都来自 SLF4J,所以如果项目是从 Log4j + SLF4J 切换到 Logback 的话,此时的代码是零改动的。
在没有配置文件的情况下,一切都是默认的,Logback 的日志信息会输出到控制台。
可以通过 StatusPrinter 来打印 Logback 的内部信息:
LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory();
StatusPrinter.print(lc);

一般来说,我们会在本地环境中配置 logback-test.xml,在生产环境下配置 logback.xml。
<configuration debug="true"><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><!-- encoder将日志变成字节数组并转到输出流 --><encoder><!-- pattern指定格式,各个参数的意义见下图 --><pattern>%d{HH:mm:ss.SSS} %relative [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><root level="debug"><appender-ref ref="STDOUT" /></root>
</configuration>
Logback 的配置文件非常灵活
最基本的结构为 <configuration> 元素,包含 0 或多个 <appender> 元素,其后跟 0 或多个 <logger> 元素,其后再跟最多只能存在一个的 <root> 元素。
appender

root
只支持一个属性——level,值可以为:TRACE、DEBUG、INFO、WARN、ERROR、ALL、OFF。
appender-ref 用来指定具体的 appender
查看内部状态信息
可以在代码中通过 StatusPrinter 来打印 Logback 内部状态信息
也可以通过在 configuration 上开启 debug 来打印内部状态信息
自动重载配置
之前提到 Logback 很强的一个功能就是支持自动重载配置,那想要启用这个功能也非常简单,只需要在 configuration 元素上添加 scan=true 即可。
<configuration scan="true">//...
</configuration>
默认情况下,扫描的时间间隔是一分钟一次。
如果想要调整时间间隔,可以通过 scanPeriod 属性进行调整,单位可以是毫秒(milliseconds)、秒(seconds)、分钟(minutes)或者小时(hours)。
下面这个示例指定的时间间隔是 30 秒:
<configuration scan="true" scanPeriod="30 seconds">...
</configuration>
注意:如果指定了时间间隔,没有指定时间单位,默认的时间单位为毫秒。
当设置 scan=true 后,Logback 会起一个 ReconfigureOnChangeTask 的任务来监视配置文件的变化。
三:把 log4j 转成 logback
如果你的项目以前用的 Log4j,那么可以通过下面这个网址把 log4j.properties 转成 logback-test.xml:
http://logback.qos.ch/translator/

将之前的那个log4j.peoperties拿到之后,将会转成下面的xml
<?xml version="1.0" encoding="UTF-8"?><!-- Built in 2024-04-05 01:26 by logback-translator -->
<!-- -->
<!-- For sponsoring SLF4J/logback/reload4j projects see -->
<!-- https://github.com/sponsors/qos-ch -->
<!-- -->
<!-- Contact sales(at)qos.ch about licensing this tool or -->
<!-- custom development.-->
<configuration><appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"><Target>System.out</Target><encoder><!-- 问题1:Logback 中没有 %l --><pattern>[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n</pattern></encoder></appender><!-- 问题2,滚动策略? --><appender name="D" class="ch.qos.logback.core.rolling.RollingFileAppender"><!--See http://logback.qos.ch/manual/appenders.html#RollingFileAppender--><!--and http://logback.qos.ch/manual/appenders.html#TimeBasedRollingPolicy--><!--for further documentation--><Append>true</Append><File>debug.log</File><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n</pattern></encoder><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>DEBUG</level></filter></appender><appender name="E" class="ch.qos.logback.core.rolling.RollingFileAppender"><!--See http://logback.qos.ch/manual/appenders.html#RollingFileAppender--><!--and http://logback.qos.ch/manual/appenders.html#TimeBasedRollingPolicy--><!--for further documentation--><Append>true</Append><File>error.log</File><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n</pattern></encoder><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>ERROR</level></filter></appender><root level="debug"><appender-ref ref="stdout"/><appender-ref ref="D"/><appender-ref ref="E"/></root>
</configuration>
来看下面这个 RollingFileAppender 配置:
<appender name="D" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>debug.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 按天滚动 --><fileNamePattern>debug.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 保存 30 天的历史记录,最大大小为 30GB --><maxHistory>30</maxHistory><totalSizeCap>3GB</totalSizeCap></rollingPolicy><encoder><pattern>%relative [%thread] %level %logger{35} - %msg%n</pattern></encoder>
</appender>
基于按天滚动的文件策略,最多保留 30 天,最大大小为 30G。
SizeAndTimeBasedRollingPolicy 比 TimeBasedRollingPolicy 多了一个日志文件大小设定的属性:maxFileSize,其他完全一样。
基于我们对 RollingPolicy 的了解,可以把 logback-test.xml 的内容调整为以下内容:
<configuration><appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"><Target>System.out</Target><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] %level %logger{36} - %msg%n</pattern></encoder></appender><appender name="D" class="ch.qos.logback.core.rolling.RollingFileAppender"><Append>true</Append><File>debug.log</File><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 按天轮转 --><fileNamePattern>debug.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 保存 30 天的历史记录,最大大小为 30GB --><maxHistory>30</maxHistory><totalSizeCap>3GB</totalSizeCap></rollingPolicy><encoder><pattern>%relative [%thread] %-5level %logger{35} - %msg%n</pattern></encoder></appender><appender name="E" class="ch.qos.logback.core.rolling.RollingFileAppender"><File>error.log</File><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 按天轮转 --><fileNamePattern>error.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 保存 30 天的历史记录,最大大小为 30GB --><maxHistory>30</maxHistory><totalSizeCap>3GB</totalSizeCap></rollingPolicy><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n</pattern></encoder><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>ERROR</level></filter></appender><root level="debug"><appender-ref ref="stdout"/><appender-ref ref="D"/><appender-ref ref="E"/></root>
</configuration>
四:日志门面SLF4J
1:什么是SLF4J
SLF4J 是 Simple Logging Facade for Java 的缩写(for≈4),也就是简易的日志门面
以外观模式(Facade pattern,一种设计模式,为子系统中的一组接口提供一个统一的高层接口,使得子系统更容易使用)实现
支持 java.util.logging、Log4J 和 Logback。
SLF4J 的作者就是 Log4J 和 Logback 的作者


2:SLF4J 解决了什么痛点
春秋战国的时候,每个国家都有自己的货币,用别国的货币也不合适,对吧?那在发生贸易的时候就比较麻烦了,货币不统一,就没法直接交易,因为货币可能不等价。
那秦始皇统一六国后,就推出了新的货币政策,全国都用一种货币,那之前的问题就解决掉了。
你看,同样的道理,日志系统有 JUL、JCL,Ceki Gulcu 自己又写了 2 种,Log4j 和 Logback
各有各的优缺点,再加上使用者千千万,萝卜白菜各有所爱,这就导致不同的应用可能会用不同的日志系统。
假设我们正在开发一套系统,打算用 SLF4J 作为门面,Log4j 作为日志系统
我们在项目中使用了 A 框架,而 A 框架的门面是 JCL,日志系统是 JUL,那就相等于要维护两套日志系统,对吧?

这就难受了!
Ceki Gulcu 想到了这个问题,并且帮我们解决了!来看 SLF4J 官网给出的解决方案。

- 使用
jcl-over-slf4j.jar替换 commons-logging.jar - 引入
jul-to-slf4j.jar
3:SLF4J 比 Log4J 强在哪
SLF4J 除了解决掉以上的痛点,帮助我们的应用程序独立于任何特定的日志系统,还有一个非常牛逼的功能,那就是 SLF4J 在打印日志的时候使用了占位符 {},
它有点类似于 String 类的 format() 方法(使用 %s 等填充参数),但更加便捷,这在很大程度上提高了程序的性能。
众所周知,字符串是不可变的,字符串拼接会创建很多不必要的字符串对象,极大的消耗了内存空间。但 Log4J 在打印带参数的日志时,只能使用字符串拼接的方式:
String name = "张三";
int age = 18;
logger.debug(name + ",年纪:" + age + ",hello world");
非常笨重,但加入了 SLF4J 后,这个问题迎刃而解。我们来看一下在 Log4j 项目中加入 SLF4J 的详细的步骤。
第一步,把 log4j 的依赖替换为 slf4j-log4j12(Maven 会自动引入 slf4j-api.jar 和 log4j.jar):
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.25</version>
</dependency>
第二步,在 resources 目录下创建 log4j.properties 文件
# config rootLogger
log4j.rootLogger = debug,stdout,D,E# config logger stdout
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n# config logger debug
# if the log level is debug, the log will be output to debug.log
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = debug.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n# config logger error
# if the log level is error, the log will be output to error.log
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
第三步,新建测试类:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** @author cuihaida*/
public class Log4jSLF4JDemo {private static final Logger logger = LoggerFactory.getLogger(Log4jSLF4JDemo.class);public static void main(String[] args) {logger.debug("{},hello world","张三");}
}
看到了吧,使用占位符要比“+”操作符方便的多。并且此时不再需要 isDebugEnabled() 先进行判断,debug() 方法会在字符串拼接之前执行。
如果只是 Log4J 的话,会先进行字符串拼接,再执行 debug() 方法
这也就意味着,如果日志系统的级别不是 DEBUG,就会多执行了字符串拼接的操作,白白浪费了性能。
相关文章:
开源轮子 - Logback 和 Slf4j
spring boot内置:Logback 文章目录 spring boot内置:Logback一:Logback强在哪?二:简单使用三:把 log4j 转成 logback四:日志门面SLF4J1:什么是SLF4J2:SLF4J 解决了什么痛…...
内部知识库的未来展望:技术融合与用户体验的双重升级
在当今数字化飞速发展的时代,企业内部知识库作为知识管理的关键载体,正站在变革的十字路口,即将迎来技术融合与用户体验双重升级的崭新时代,这一系列变化将深度重塑企业知识管理的格局。 一、技术融合:开启知识管理新…...
【Linux系列】Shell 命令:`echo ““ > img.sh`及其应用
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
【RAG实战】语言模型基础
语言模型赋予了计算机理解和生成人类语言的能力。它结合了统计学原理和深度神经网络技术,通过对大量的样本数据进行复杂的概率分布分析来学习语言结构的内在模式和相关性。具体地,语言模型可根据上下文中已出现的词序列,使用概率推断来预测接…...
【MySQL】7.0 入门学习(七)——MySQL基本指令:帮助、清除输入、查询等
1.0 help ? 帮助指令,查询某个指令的解释、用法、说明等。详情参考博文: 【数据库】6.0 MySQL入门学习(六)——MySQL启动与停止、官方手册、文档查询 https://www.cnblogs.com/xiaofu007/p/10301005.html 2.0 在cmd命…...
我的 2024 年终总结
2024 年,我离开了待了两年的互联网公司,来到了一家聚焦教育机器人和激光切割机的公司,没错,是一家硬件公司,从未接触过的领域,但这还不是我今年最重要的里程碑事件 5 月份的时候,正式提出了离职…...
STM32CUBEMX+STM32H743ZIT6+IAP+UART在线升级初始化和代码解析
1、STM32H7带的ITCM,DTCM,AXI SRAM,SRAM1,SRAM2,SRAM3,SRAM4和备份SRAM五块。 其中, ①TCM区包括ITCM和DTCM,这两个是直连CPU的。 速率与CPU一致,最高能到480MHz。 DTCM地…...
半连接转内连接 | OceanBase SQL 查询改写
查询优化器是关系型数据库系统的核心模块,是数据库内核开发的重点和难点,也是衡量整个数据库系统成熟度的“试金石”。为了帮助大家更好地理解 OceanBase 查询优化器,我们撰写了查询改写系列文章,带大家更好地掌握查询改写的精髓&…...
Git使用经历
目录 1、先创建文件夹 2、仓库初始化 3、配置gitee用户名和密码 4、克隆指定仓库的中指定分支到本地仓库 5、查看当前所在分支、切换分支 6、查看状态,判断是否有修改 7、把更新的内容添加到缓存区 8、把缓存区的数据提交 9、把数据推送到远程仓库 10、把…...
永磁同步电机控制算法-自适应带宽LADRC转速控制器
一、原理介绍 设计了自适应带宽 LADRC 控制方法,继承了 LADRC 优点的同时,加入自适应带宽控制,提出运用 Softsign 函数设计带宽自适应函数,根据电机转速自动调节控制带宽,解决了永磁同步电机在复杂且多变的环境下受到…...
基于springboot+vue实现的博物馆游客预约系统 (源码+L文+ppt)4-127
摘 要 旅游行业的快速发展使得博物馆游客预约系统成为了一个必不可少的工具。基于Java的博物馆游客预约系统旨在提供高效、准确和便捷的适用博物馆游客预约服务。本文讲述了基于java语言开发,后台数据库选择MySQL进行数据的存储。该软件的主要功能是进行博物馆游客…...
LeetCode 1705.吃苹果的最大数目:贪心(优先队列) - 清晰题解
【LetMeFly】1705.吃苹果的最大数目:贪心(优先队列) - 清晰题解 力扣题目链接:https://leetcode.cn/problems/maximum-number-of-eaten-apples/ 有一棵特殊的苹果树,一连 n 天,每天都可以长出若干个苹果。在第 i 天,…...
vim多窗格
vim打开文件分为三个阶段:buffer、window与tab buffer就是在同一个界面打开的文件window就是使用水平分割与垂直分割的窗口tab则是可以是上述两者的总集合 buffer :e filename在已打开文件的界面中再打开一个新文件,显示这个新文件,原文件被隐…...
ubuntu paddle ocr 部署bug问题解决
ubuntu paddle ocr 部署会出现异常报错。 尝试安装以下版本: pip install paddlepaddle2.5.2 -i https://pypi.tuna.tsinghua.edu.cn/simpl 助力快速掌握数据集的信息和使用方式。 数据可以如此美好!...
OpenFeign快速入门 示例:黑马商城
使用起因 之前我们利用了Nacos实现了服务的治理,利用RestTemplate实现了服务的远程调用。这样一来购物车虽然通过远程调用实现了调用商品服务的方法,但是远程调用的代码太复杂了: 解决方法 并且这种调用方式比较复杂,一会儿远程调用,一会儿本地调用。 因…...
【C++】ceil 和 floor 函数的实现与分析
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯ceil 和 floor 函数的基础介绍1. ceil 函数定义与功能示例代码输出结果功能分析使用场景 2. floor 函数定义与功能示例代码输出结果功能分析使用场景 💯自行实现…...
zabbix监控山石系列Hillstone配置模版(适用于zabbix6及以上)
监控项: 触发器: 监控数据:...
在瑞芯微RK3588平台上使用RKNN部署YOLOv8Pose模型的C++实战指南
在人工智能和计算机视觉领域,人体姿态估计是一项极具挑战性的任务,它对于理解人类行为、增强人机交互等方面具有重要意义。YOLOv8Pose作为YOLO系列中的新成员,以其高效和准确性在人体姿态估计任务中脱颖而出。本文将详细介绍如何在瑞芯微RK3588平台上,使用RKNN(Rockchip N…...
CTFHub disable_functions通关
LD_PRELOAD 来到首页发现有一句话直接就可以用蚁剑连接 根目录里有/flag但是不能看;命令也被ban了就需要绕过了 绕过工具在插件市场就可以下载 如果进不去的话 项目地址: #本地仓库;插件存放 antSword\antData\plugins 绕过选择 上传后我们点进去可以看到多了一个绕过的文件;…...
Chromium GN 目标指南 - view_example 计数器示例 (七)
1. 引言 在前面的文章中,我们学习了如何在 views_examples 中添加自定义 Button 示例。在本篇文章中,我们将继续探索 Views 框架的应用,创建一个简单的计数器示例,以学习如何使用 Label 和 Button 控件进行交互,以及如…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
