java日志框架介绍

参考地址:https://blog.csdn.net/xhf852963/article/details/141226327

java主流日志框架

  • 日志实现(具体干活的):JUL(java util logging)、logback、log4j、log4j2

  • 日志门面(指定规则的):JCL(Jakarta Commons Logging)、slf4j( Simple Logging Facade for Java)

JUL日志框架

Java util Logging是java原生的日志框架,使用时不需要另外引用第三方类库,使用方便,学习简单,能在小型应用中灵活使用。

在JUL中有以下组件:

Loggers:被称为记录器,应用程序通过获取Logger对象,调用其API来来发布日志信息。Logger 通常时应用程序访问日志系统的入口程序。

  • Handler :负责将日志记录发送到适当的目的地,如控制台、文件或者网络目的地。下面是一些常见的 Handler 类型:
  • ConsoleHandler - 将日志记录输出到标准错误流(通常是控制台)。
  • FileHandler - 将日志记录输出到文件中。可以通过配置指定文件名模式,允许创建滚动文件。
  • SocketHandler - 将日志记录发送到套接字服务器。
  • StreamHandler - 将日志记录输出到任意的输出流。
  • MemoryHandler - 将日志记录存储在内存缓冲区中,当满足某些条件时,将缓冲区中的日志记录推送到目标 Handler。

Formatters:Formatter 接口用于定义日志记录的格式。通过自定义 Formatter,可以控制日志输出的具体样式,比如日期格式、消息前缀等。也有一些内置的 Formatter 类。
Level:每条日志消息都有一个关联的日志级别。该级别粗略指导了日志消息的重要性和紧迫,可以将Level和Loggers,Handler 做关联以便于我们过滤消息。
Filters:过滤器,根据需要定制哪些信息会被记录,哪些信息会被放过。

代码示例

package org.example.logTest;
import java.io.IOException;
import java.util.logging.*;

public class JUITest1 {
    public static void main(String[] args) {
        // 获取日志记录器对象
        Logger logger = Logger.getLogger("org.example.logTest.JUITest1");
        // 日志输出
        logger.info("日志输出测试:1111111111");
        // 使用通用方法进行日志输出
        logger.log(Level.INFO,"message info !");
        // 通过占位符方式代替字符串拼接输入日志
        String name = "yoyo";
        int age = 20;
        logger.log(Level.INFO,"name:{0},age:{1}",new Object[]{name,age});
        
        try {
            // 1.创建 FileHandler 实例,指定日志文件的位置和是否追加日志
            FileHandler fileHandler = new FileHandler("app.log", true);
            // 2.设置日志格式化器
            fileHandler.setFormatter(new SimpleFormatter());
            // 3.创建 ConsoleHandler 实例
            ConsoleHandler consoleHandler = new ConsoleHandler();
            // 添加 Handler 到 Logger
            logger.addHandler(fileHandler);
            logger.addHandler(consoleHandler);
            // 4.设置 Logger 的日志级别
            logger.setLevel(java.util.logging.Level.ALL);
            // 记录一条日志消息
            logger.info("This is an info message.");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

 运行结果

JUL日志级别

在 JUL 中定义了 7 种日志的级别,分别为:SEVERE(最高值)> WARNING > INFO (默认级别) > CONFIG > FINE > FINER > FINEST(最低值),如下代码:

package org.example.logTest;

import java.util.logging.Level;
import java.util.logging.Logger;

public class JULTest2 {
    public static void main(String[] args) {
        // 1.创建日志记录器对象
        Logger logger = Logger.getLogger("org.example.logTest");
        //2.日志输出的第二种方式,指定日志的输出级别
        logger.log(Level.SEVERE,"SEVERE msg");
        logger.log(Level.WARNING,"WARNING msg");
        logger.log(Level.INFO,"INFO msg");
        logger.log(Level.CONFIG,"CONFIG msg");
        logger.log(Level.FINE,"FINE msg");
        logger.log(Level.FINER,"FINER msg");
        logger.log(Level.FINEST,"FINEST msg");
    }
}

运行结果:

 可以看到由于默认级别是 INFO,它只会打印比 INFO 级别高的日志。

我们看看Level这个枚举类的源代码:

public class Level implements java.io.Serializable {
    private static final String defaultBundle = "sun.util.logging.resources.logging";
    private final String name;
    private final int value;
    private final String resourceBundleName;
    private transient String localizedLevelName;
    private transient Locale cachedLocale;

    public static final Level OFF = new Level("OFF",Integer.MAX_VALUE, defaultBundle);

    public static final Level SEVERE = new Level("SEVERE",1000, defaultBundle);

    public static final Level WARNING = new Level("WARNING", 900, defaultBundle);

    public static final Level INFO = new Level("INFO", 800, defaultBundle);

    public static final Level CONFIG = new Level("CONFIG", 700, defaultBundle);

    public static final Level FINE = new Level("FINE", 500, defaultBundle);

    public static final Level FINER = new Level("FINER", 400, defaultBundle);

    public static final Level FINEST = new Level("FINEST", 300, defaultBundle);

    public static final Level ALL = new Level("ALL", Integer.MIN_VALUE, defaultBundle);

    protected Level(String name, int value) {
        this(name, value, null);
    }

    protected Level(String name, int value, String resourceBundleName) {
        this(name, value, resourceBundleName, true);
    }

    private Level(String name, int value, String resourceBundleName, boolean visible) {
        if (name == null) {
            throw new NullPointerException();
        }
        this.name = name;
        this.value = value;
        this.resourceBundleName = resourceBundleName;
        this.localizedLevelName = resourceBundleName == null ? name : null;
        this.cachedLocale = null;
        if (visible) {
            KnownLevel.add(this);
        }
    }
......

自定义日志级别

还有两个特殊的级别,ALL 和 OFF,他们都属于自定义的级别,其中 OFF 可用来关闭日志记录,ALL 可用来启用所有的日志消息,如下代码:

package org.example.logTest;

import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

public class JULTest3 {
    public static void main(String[] args) {
        // 1.创建日志记录器对象
        Logger logger = Logger.getLogger("org.example.logTest");
        // 2.关闭系统默认的级别
        logger.setUseParentHandlers(false);
        // 3.重新配置日志具体级别
        logger.setLevel(Level.ALL);
        // 4.创建 ConsoleHandler 控制台输出
        ConsoleHandler consoleHandler = new ConsoleHandler();
        // 5.创建简单格式转换对象
        SimpleFormatter simpleFormatter = new SimpleFormatter();
        // 6.将 Handler 和 Formatter 进行关联: logger ——关联—— Handler ——关联—— Formatter
        consoleHandler.setFormatter(simpleFormatter);
        logger.addHandler(consoleHandler);
        // 7.设consoleHandler 控制台输出的级别~
        consoleHandler.setLevel(Level.ALL);

        logger.log(Level.SEVERE,"SEVERE msg");
        logger.log(Level.WARNING,"WARNING msg");
        logger.log(Level.INFO,"INFO msg");
        logger.log(Level.CONFIG,"CONFIG msg");
        logger.log(Level.FINE,"FINE msg");
        logger.log(Level.FINER,"FINER msg");
        logger.log(Level.FINEST,"FINEST msg");
    }
}

运行结果:

 Logger对象父子关系

 JUL 中 Logger 之间存在父子关系,这种父子关系通过树状结构存储,JUL 在初始化时会创建一个顶层 RootLogger 作为所有 Logger 父 Logger,存储上作为树状结构的根节点。并父子关系通过路径来关联。

package org.example.logTest;

import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

public class JULTest4 {
    public static void main(String[] args) {
        // 父子关系通过命名规范包结构来的
        Logger logger1 = Logger.getLogger("org.example.logTest");
        Logger logger2 = Logger.getLogger("org.example");

        // logger1的父元素对象是logger2
        System.out.println(logger1.getParent() == logger2);
        // 所有日志记录器的顶级父元素为:LogManager$RootLogger
        System.out.println(logger2.getParent());

        // 创建控制台输出控制器
        ConsoleHandler consoleHandler = new ConsoleHandler();
        // 创建简单个格式转换对象
        SimpleFormatter simpleFormatter = new SimpleFormatter();
        logger2.addHandler(consoleHandler);
        consoleHandler.setFormatter(simpleFormatter);

        // 关闭系统默认的级别
        logger2.setUseParentHandlers(false);
        // 设置日志级别
        logger2.setLevel(Level.INFO);
        logger2.log(Level.INFO,"level info 1");
        logger2.log(Level.FINE,"level fine 1");
        // 子日志记录器默认继承父记录器日志级别
        logger1.log(Level.INFO,"level info 2");
        logger1.log(Level.FINE,"level fine 2");
    }
}

运行结果:

 JUL日志配置文件

JUL日志配置文件默认位置:$JAVAHOME\jre\lib\logging.properties,如图:

 指定配置文件的位置,首先在 resources 下创建一个 logging.properties 文件

handlers= java.util.logging.ConsoleHandler
.level= ALL

java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

java.util.logging.ConsoleHandler.level = FINE
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

com.xyz.foo.level = SEVERE

在代码里面读取配置文件

package org.example.logTest;

import java.io.IOException;
import java.io.InputStream;
import java.util.logging.LogManager;
import java.util.logging.Logger;

public class JULTest5 {
    public static void main(String[] args) throws IOException {
        // 通过类加载器读取自定义配置文件(通过类路径读取资源文件)
        InputStream in =
                JULTest5.class.getClassLoader().getResourceAsStream("logging.properties");
        // 获取日志管理器对象
        LogManager logManager = LogManager.getLogManager();
        // 通过日志管理器加载配置文件
        logManager.readConfiguration(in);

        Logger logger = Logger.getLogger("package org.example.logTest");
        logger.severe("severe");
        logger.warning("warning");
        logger.info("info");
        logger.config("config");
        logger.fine("fine");
        logger.finer("finer");
        logger.finest("finest");
    }
}

运行结果

 日志原理解析

JUL流程示意图:

1、初始化 LogManager,LogManager 加载 logging.properties 配置,并添加 Logger 到LogManager。

2、从单例 LogManager 获取 Logger

3、设置级别 Level,并指定日志记录 LogRecord

4、Filter 提供了日志级别之外更细粒度的控制

5、Handler 是用来处理日志输出位置

6、Formatter 是用来格式化 LogRecord 的。

Log4j

Log4j 是 Apache 下的一款开源的日志框架,通过在项目中使用 Log4J,我们可以控制日志信息输出到控制台、文件、甚至是数据库中。我们可以控制每一条日志的输出格式,通过定义日志的输出级别,可以更灵活的控制日志的输出过程。方便项目的调试。

Log4j官方文档:https://logging.apache.org/log4j/1.x/

https://logging.apache.org/

Log4j入门

添加maven依赖

<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>

java代码demo

package org.example.logtest;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;

public class Logtest1 {
    public static void main(String[] args) {
        // 1、由于没有配置文件,所以需要初始化系统配置信息
        BasicConfigurator.configure();

        // 2、创建日志记录器对象
        Logger logger = Logger.getLogger(Logtest1.class);
        // 3、日志记录输出的第一种方式
        logger.info("hello log4j");
        // 4、日志记录输出的第二种方式
        logger.fatal("fatal"); // 严重错误,一般会造成系统崩溃和终止运行
        logger.error("error"); // 错误信息,但不会影响系统运行
        logger.warn("warn"); // 警告信息,可能会发生问题
        logger.info("info"); // 程序运行信息,数据库的连接、网络、IO操作等
        logger.debug("debug"); // 调试信息,一般在开发阶段使用,记录程序的变量、参数等
        logger.trace("trace"); // 追踪信息,记录程序的所有流程信息
    }
}

输出结果如下所示,没有输出 trace 日志信息是因为 log4j 默认的日志输出级别是 debug

 日志的级别从高到低分别为:fatal > error > warn > info > debug > trace ,在实际开发中一般只使用 error、warn、info 和 debug 就可以了。

Log4j组件

 Log4J 主要由 Loggers (日志记录器)、Appenders(输出端)和 Layout(日志格式化器)组成。其中 Loggers 控制日志的输出级别与日志是否输出;Appenders 指定日志的输出方式(输出到控制台、文件等);Layout 控制日志信息的输出格式。

Loggers

日志记录器,负责收集处理日志记录,实例的命名就是类 “XX” 的 full quailied name(类的全限定名),Logger 的名字大小写敏感,其命名有继承机制:例如:name 为 org.apache.commons 的 logger 会继承 name 为 org.apache 的 logger。

Log4J 中有一个特殊的 logger 叫做 “root”,他是所有 logger 的根,也就意味着其他所有的 logger 都会直接或者间接地继承自 root。root logger 可以用 Logger.getRootLogger() 方法获取。

Appenders

Appender 用来指定日志输出到哪个地方,可以同时指定日志的输出目的地。Log4j 常用的输出目的地有以下几种:

ConsoleAppender 将日志输出到控制台
FileAppender 将日志输出到文件中
DailyRollingFileAppender 将日志输出到一个日志文件,并且每天输出到一个新的文件
RollingFileAppender 将日志信息输出到一个日志文件,并且指定文件的尺寸,当文件大小达到指定尺寸时,会自动把文件改名,同时产生一个新的文件
JDBCAppender 把日志信息保存到数据库中

Layout

布局器 Layouts 用于控制日志输出内容的格式,让我们可以使用各种需要的格式输出日志。 Log4j 常用的 Layouts 有以下几种:

HTMLLayout 格式化日志输出为HTML表格形式
SimpleLayout 简单的日志输出格式化,打印的日志格式为(info - message)
PatternLayout 最强大的格式化期,可以根据自定义格式输出日志,如果没有指定转换格式,就是用默认的转换格式

使用配置文件

在 resources 目录下添加 log4j.properties 的配置文件,并配置相关的配置信息,如下所示:

# 指定 RootLogger 顶级父元素默认配置信息
# 指定日志级别为 info,使用的 appdener 为 console
log4j.rootLogger = info,console

# 指定控制台日志输出的 appender 对象
log4j.appender.console = org.apache.log4j.ConsoleAppender

# 指定消息格式 layout
log4j.appender.console.layout = org.apache.log4j.SimpleLayout

测试代码如下:

package org.example.logtest;

import org.apache.log4j.Logger;

public class Logtest2 {
    public static void main(String[] args) {
        Logger logger = Logger.getLogger(Logtest2.class);
        // 2、日志记录输出的第一种方式
        logger.info("hello log4j");
        // 3、日志记录输出的第二种方式
        logger.fatal("fatal"); // 严重错误,一般会造成系统崩溃和终止运行
        logger.error("error"); // 错误信息,但不会影响系统运行
        logger.warn("warn"); // 警告信息,可能会发生问题
        logger.info("info"); // 程序运行信息,数据库的连接、网络、IO操作等
        logger.debug("debug"); // 调试信息,一般在开发阶段使用,记录程序的变量、参数等
        logger.trace("trace"); // 追踪信息,记录程序的所有流程信息
    }
}

 输出到文件

配置文件如下

# 指定 RootLogger 顶级父元素默认配置信息
# 指定日志级别为 info,使用的 appdener 为 console
log4j.rootLogger = info,console,file

# 指定控制台日志输出的 appender 对象
log4j.appender.console = org.apache.log4j.ConsoleAppender

# 指定消息格式 layout
log4j.appender.console.layout = org.apache.log4j.SimpleLayout

# 日志输出的 appender 对象
log4j.appender.file = org.apache.log4j.FileAppender
# 指定消息格式 layout
log4j.appender.file.layout = org.apache.log4j.PatternLayout
# 指定消息格式的内容
log4j.appender.file.layout.conversionPattern = [%p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n
# 指定日志文件保存路径
log4j.appender.file.file = log4j.log
# 指定日志文件的字符集
log4j.appender.file.encoding = UTF-8

再次运行以上代码,则日志文件输出到了项目根目录

 日志门面

在项目的初期时,我们可能只是使用 JUL 进行日志的单一输出,JUL 可以满足项目的需求。但是随着功能的增加,单一的日志文件会越来越臃肿,所以我们需要按照一定的规则进行滚动拆分,比如说按照时间以天为单位进行管理,但是 JUL 并不支持。

此时我们就需要在项目中引入 log4j,但是项目之前的日志代码都是基于 JUL 来实现的,一旦换了日志框架,那么之前的代码就需要修改,工作量是非常大的。所以此时 apache 组织就站出来了,将这两个日志框架进行了统一的管理和维护,提供了一个日志门面 JCL ,并提供了一套全新的 api,以面向接口的方式来操作具体的实现。即日志框架变了,代码也不需要发生修改。这个就是日志门面技术。

日志门面的实现

常见的日志门面有 JCL 和 slf4j。JCL 仅支持 JUL 和 log4j 框架,目前已经被淘汰。slf4j 是目前市场上比较主流的日志门面,它支持现在所有的日志实现框架。

常见的日志实现有 JUL、log4j、logback、log4j2 等。

日志门面和日志实现关系

最早的时候,用户要想进行日志记录是直接操作日志实现类的。这种方式意味着,如果后期日志实现发生了变化,代码也需要发生变化。

但是现在有了日志门面之后,用户只需要操作统一的 api 就可以了,由这套接口的底层再去操作具体的日志实现进行日志的记录,这样就可以实现用户和日志实现的解耦的思想,方便进行统一的管理和维护。后期如果想替换日志实现,只需要替换相应的 jar 包即可。

日志框架历史顺序

log4j -->JUL-->JCL--> logback --> slf4j --> log4j2

  • jdk 最早期的时候是没有提供日志记录功能的,而是通过 System.out 的方式进行输出,此时 apache 的一个哥们就设计出了一个框架 log4j,设计出来之后很受欢迎。所以 jdk 在 1.4 版本时也设计出了一个日志框架 JUL。
  • 所以当时市场就比较混乱,有的公司使用 log4j,有的公司使用 JUL,为了解决这个问题,apache 公司就推出了 JCL 来统一管理 log4j 和 JUL。
  • 过了一段时间之后 log4j 的创始人和 apache 闹了一些矛盾就出去单飞了,然后单飞的这个哥们就基于 log4j 设计出了一个全新的日志框架 logback,功能和性能比 log4j 更强大,但是用的人不多,因为 JCL 不支持 logback。
  • 基于这种情况,这个哥们又设计出了一个日志门面 slf4j,这个日志门面支持所有的日志实现框架,而且操作起来非常简单。等到 slf4j 出现之后,JCL 就完犊子了。
  • apache 公司就着急了,市场上没有人用了,所以他们就蛰伏了两年,根据 logback 开放的源代码,设计出了全新的日志框架 log4j2,它从功能上而言几乎和 logback 一致,但是性能上比 logback 提升了很多。需要注意的是 log4j2 既是日志门面技术也是日志实现框架

使用日志门面的原因

  1. 面向接口开发,不再依赖具体的实现类。减少代码的耦合
  2. 项目通过导入不同的日志实现类,可以灵活的切换日志框架
  3. 统一 API,方便开发者学习和使用
  4. 统一配置便于项目日志的管理

JCL日志门面

 JCL官方文档:https://commons.apache.org/proper/commons-logging/dependency-info.html

JCL 全称为 Jakarta Commons Logging,是 Apache 提供的一个通用日志 API。

它是为 "所有的 Java 日志实现" 提供一个统一的接口,它自身也提供一个日志的实现,但是功能非常常弱(SimpleLog)。所以一般不会单独使用它。他允许开发人员使用不同的具体日志实现工具:Log4j、Jdk 自带的日志(JUL)。

JCL 有两个基本的抽象类:基本记录器 Log 和负责创建 Log 实例的 LogFactory。架构图如下:

首先创建一个 maven 工程,添加如下的 maven 依赖:

 

<dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>

测试代码如下:

package org.example.logTest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class LogTest1 {
    public static void main(String[] args) {
        // 创建日志对象
        Log log = LogFactory.getLog(LogTest1.class);
        // 日志记录输出
        log.fatal("fatal");
        log.error("error");
        log.warn("warn");
        log.info("info");
        log.debug("debug");
        System.out.println("Hello world!");
    }
}

输出结果如下,可以看到 JCL 默认调用的就是 JUL 里面的 api 来打印日志的。

 接下来我们添加 log4j 的 maven 依赖,并将 log4j.properties 配置文件复制到 resources 目录下,再次执行上面的代码,可以看到,这次调用就是 log4j 的底层 api 了。

JCL原理

JCL 底层实际上是通过 LogFactory 动态加载 Log 实现类来完成日志功能的,可以加载下面的四种实现类。

JCL 这种日志门面支持的日志实现数组有下面的四个,首先判断是否存在 log4j ,如果存在则调用它的 api,不存在则调用 jdk 自带的 logger。

 slf4j

官方文档:https://www.slf4j.org/manual.html

简单日志门面(Simple Logging Facade For Java)SLF4J 主要是为了给 Java 日志访问提供一套标准、规范的 API 框架,其主要意义在于提供接口,具体的实现可以交由其他日志框架,例如 log4j 和 logback 等。当然 slf4j 自己也提供了功能较为简单的实现,但是一般很少用到。对于一般的 Java 项目而言,日志框架会选择 slf4j 作为门面,配上具体的实现框架(log4j、logback等),中间使用桥接器完成桥接。

SLF4J 是目前市面上最流行的日志门面。现在的项目中,基本上都是使用 SLF4J 作为我们的日志系统。SLF4J 日志门面主要提供两大功能:日志框架的绑定和日志框架的桥接。

快速入门

首先创建一个 maven 工程,并添加下面的依赖:

<dependencies>
        <!--slf4j core 使用slf4j必須添加-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>2.0.17</version>
        </dependency>
        <!--slf4j 自带的简单日志实现 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>2.0.17</version>
        </dependency>
    </dependencies>

测试代码

package org.example.logTest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Logtest1 {
    // 声明日志对象
    private final static Logger LOGGER = LoggerFactory.getLogger(Logtest1.class);
    public static void main(String[] args) {
        //打印日志信息
        LOGGER.error("error");
        LOGGER.warn("warn");
        LOGGER.info("info"); // 默认输出级别为 info
        LOGGER.debug("debug");
        LOGGER.trace("trace");

        // 使用占位符输出日志信息
        String name = "jack";
        Integer age = 18;
        LOGGER.info("用户:{},{}", name, age);

        // 将系统异常信息写入日志
        try {
            int i = 1 / 0;
        } catch (Exception e) {
            // e.printStackTrace();
            LOGGER.info("出现异常:", e);
        }
    }
}

运行结果

 绑定日志的实现

 

在这个图片的上方绿颜色的部分表示的是我们项目的应用,如果我们的项目想要进行日志记录的话,首先需要关联 SLF4J,它就是面向的接口,统一所有日志的 api,就是 maven 依赖里面的 slf4j-api ,它的下方需要提供具体的实现,在这里一共有三种情况。

第一种情况是如果项目中只引入了 slf4j-api 日志门面,并没有导入具体的日志实现,那么日志的这个功能就是关闭的,此时不会进行任何的日志输出。上图中左侧的第一个。

第二种情况是蓝颜色部分,它里面有三种日志实现,一个是 logback,一个是 slf4j 内置的 simple 简单框架,还有一个是 nop,这三个框架的设计是要比 slf4j 要晚的,所以它们默认就遵从 slf4j 的开发规范了,即我们只需要导入它们的实现即可。上图中左侧的第二、五和六个。

第三种情况是灰颜色部分,即中间那两个,一个是 log4j,一个是 JUL,它们两个设计的比较早,默认是并没有遵循 slf4j 的规范的,它们是无法进行直接绑定的,中间需要添加一个适配层 Adaptation 来适配我们具体的实现,就会简介的遵循我们的 slf4j 的 api 规范。

绑定logback

logback文档地址:https://logback.qos.ch/documentation.html

添加maven依赖

<dependencies>
        <!--slf4j core 使用slf4j必須添加-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.27</version>
        </dependency>
        <!-- logback 日志实现-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
    </dependencies>

执行上面同样的代码,如图:

绑定 slf4j-nop

slf4j-nop 是一个日志的开关,当我们导入这个实现之后,就表示 slf4j 就不会使用任何的日志实现框架,这个功能就关闭了,如下 maven 依赖:

<dependencies>
        <!--slf4j core 使用slf4j必須添加-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.27</version>
        </dependency>
        <!-- nop 日志的开关-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-nop</artifactId>
            <version>1.6.6</version>
        </dependency>
    </dependencies>

运行上面的代码,可以看到无任何日志输出

绑定log4j 

如果想要绑定 log4j,需要需要绑定一个 slf4j-log412 适配器,如下 maven 依赖:

<dependencies>
        <!--slf4j core 使用slf4j必須添加-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.27</version>
        </dependency>
        <!-- 绑定 log4j 日志实现,需要导入适配器-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>

还需要把以前案例中使用的 log4j.properties 文件粘贴到 resources 目录下,然后执行测试代码,如下所示:

 

posted @ 2024-12-23 23:14  远洪  阅读(99)  评论(0)    收藏  举报