欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 创投人物 > 开源轮子 - Logback 和 Slf4j

开源轮子 - Logback 和 Slf4j

2025/5/11 14:12:44 来源:https://blog.csdn.net/qq_43350524/article/details/144634324  浏览:    关键词:开源轮子 - Logback 和 Slf4j

spring boot内置:Logback

文章目录

  • spring boot内置:Logback
    • 一:Logback强在哪?
    • 二:简单使用
    • 三:把 log4j 转成 logback
    • 四:日志门面SLF4J
      • 1:什么是SLF4J
      • 2:SLF4J 解决了什么痛点
      • 3:SLF4J 比 Log4J 强在哪

一:Logback强在哪?

  1. 非常自然地实现了 SLF4J,不需要像 Log4j 和 JUL 那样加一个适配层

在这里插入图片描述

  1. 是Spring Boot默认的[一旦某款工具库成为了默认选项,那就说明这款工具已经超过了其他竞品]
  2. 支持自动重新加载配置文件,不需要另外创建扫描线程来监视
  3. 性能大大的提升

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,就会多执行了字符串拼接的操作,白白浪费了性能。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词