slf4j和log4j、log4j2、logback

前言

最近Apache Log4j出现了“核弹级”漏洞,趁着这个机会参考各类博客,梳理清楚java中主流的日志框架和之间的关系

log发展历史

最开始,大家都是使用System.out.println控制台打印来检查程序输出是否符合自己的预期,该方式比较原始,无法自动区分日志的类型,很难应用到生产系统中;

从JDK1.4开始提供java.util.logging日志框架来打印日志,但大佬觉得JUL太难用了,于是手撸了个log4j,后来log4j发现了安全漏洞,加上代码结构问题难以维护,于是从1.2就停止更新log4j,并重新撸了个log4j2,再后来,大佬又撸了一个性能更高、功能更全的logback。

大佬构建了log的世界,创造了最常见的日志框架:log4j、log4j2、logback

常见日志框架的使用方式

log4j

  • 测试代码
import org.apache.log4j.Logger;

public class Log4jDemo {
    public static void main(String[] args) {
        // 使用log4j,依赖log4j.jar
        // log4j不提供默认配置,需要在适当位置添加log4j.properties或log4j.xml,否则会出现“No appenders could be found for logger”告警信息
        // 参考:https://blog.csdn.net/qq_37502106/article/details/86659947
        Logger logger_log4j = Logger.getLogger(Log4jDemo.class);
        logger_log4j.info("Hello World");
    }
}
  • log4j.properties配置
log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

log4j2

  • 测试代码
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Log4j2Demo {
    public static void main(String[] args) {
        // 使用log4j2,需要log4j-api.jar、log4j-core.jar
        // log4j2存在默认的配置,ERROR级别,输出到console上
        // https://www.jianshu.com/p/a344409cf08a
        // log4j2可以使用log4j2.xml、yml、jsn等多中配置文件格式
        Logger logger_log4j2 = LogManager.getLogger(Log4j2Demo.class);
        logger_log4j2.error("Hello World");
    }
}
  • log4j2.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorInterval="5">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>
    </Appenders>
    <Loggers>
        <Logger name="org.apache.logging.log4j" level="ERROR" additivity="true">
            <AppenderRef ref="File" />
        </Logger>
        <Root level="INFO">
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
</Configuration>

logback

  • 测试代码
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LogBackDemo {
    public static void main(String[] args) {
        // https://blog.csdn.net/u011493218/article/details/82997000
        // 按照相关博客内容,可以不用配置logback.xml,会使用默认配置打印在console中,实际情况是
        // 只有使用slf4j的方式,才能进行自动配置,否则不会
        // 具体类调用为:StaticLoggerBinder --> ContextInitializer.autoConfig --> BasicConfigurator

        // 下列方式即使配置了logback.xml也不能打印出日志;
        // Logger logger_logback = new LoggerContext().getLogger(LogBackDemo.class);
        // logger_logback.info("Hello World!");

        // logback必须和slf4j一起使用
        Logger logger_logback = LoggerFactory.getLogger(LogBackDemo.class);
        logger_logback.info("Hello World");
    }
}
  • logback.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 日志输出级别 -->
    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

SLF4J(Simple Logging Facade for Java)

根据上述案例,发现使用不同的日志框架,就要引入不同的jar包,使用不同的代码获取Logger,如果项目后期需要升级,会导致大量的class需要修改,因此引入Slf4j

门面系统的作用

早起Apache Commons Logging出现,Common-logging提供一个日志入口,称为”门面日志“,即它不负责写日志,而是提供一个统一的接口,通过jar来决定使用的日志框架。log4j的大佬嫌弃Common-logging难用,开发了门面日志框架slf4j

slf4j使用方式

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Logger logger = LoggerFactory.getLogger(Test.class);
logger.info("Hello World!")

slf4j如何决定使用哪个框架日志呢,并且引入哪些jar包呢?

在这里插入图片描述

如图就是slf4j和日志框架的组合依赖结构图,使用slf4j需要首先导入「slf4j-api.jar」

  • 和log4j配合,需要导入「log4j.jar」,以及桥接包「slf4j-log412.jar」。
  • log4j2配合需要导入log4j2的「log4j-api.jar」、「log4j-core.jar」和桥接包「log4j-slf4j-impl.jar」
  • logback只需要导入「logback-classic.jar」和「logback-core.jar」即可,不需要桥接包

什么是桥接包,为什么logback没有

先让来让我们看看slf4j从LoggerFactory.getLogger()开始,到底干了什么。
流程如下:

在这里插入图片描述

原理就是就是让ClassLoader从classpath(依赖的jar)中找到「StaticLoggerBinder」这个类,然后利用他来返回log4j、logback中的Logger,然后打印日志。

所谓的桥接包,就是实现StaticLoggerBinder类,用来连接slf4j和日志框架。因为log4j和log4j2刚开始没有StaticLoggerBinder这个类,为了不改变程序结构,只能重新写一个新的jar来实现StaticLoggerBinder。而logback出现slf4j之后,于是在logback本身的jar中实现了StaticLoggerBinder,所以就不需要桥接包。

StaticLoggerBinder实现了使用底层日志框架创建Logger的功能,各自的StaticLoggerBinder为slf4j提供的Logger,再提供给用户打印日志。

log4j和log4j2桥接包及logback依赖里,都有StaticLoggerBinder类。

使用相关注意项

“Class path contains multiple SLF4J bindings.”

在使用slf4j的时候会遇到以上的报告信息。我也曾遇到过web服务因为slf4j问题启动失败。究其根本是因为logback-classic、log4j-slf4j-impl、slf4j-log412、slf4j-jdk这些jar不能同时存在。他们都实现了StaticLoggerBinder类而导致冲突,slf4j无法确定到底用哪个日志框架。

参考博客:

https://mp.weixin.qq.com/s/8eVxJoQx7YmiI2o0mOnRQg

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值