Java日志门面技术 SLF4J

背景

随着系统开发的进行,可能会更新不同的日志框架,造成当前系统中存在不同的日志依赖,让我们难以统一的管理和控制。就算我们强制要求所有的模块使用相同的日志框架,系统中也难以避免使用其他类似spring,mybatis等其他的第三方框架,它们依赖于我们规定不同的日志框架,而且他们自身的日志系统就有着不一致性,依然会出来日志体系的混乱。

SLF4J概述

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

切换日志框架

application下面的SLF4J API表示slf4j的日志门面,包含三种情况:

  • 若是只导入slf4j日志门面没有导入对应的日志实现框架,那么日志功能将会是默认关闭的,不会进行日志输出的。
  • 蓝色图里Logback、slf4j-simple、slf4j-nop出来的比较晚就遵循了slf4j的API规范,也就是说只要导入对应的实现就默认实现了对应的接口,来实现开发。
  • 对于中间两个日志实现框架log4j(slf4j-log4j12)、JUL(slf4j-jdk14)由于出现的比slf4j早,所以就没有遵循slf4j的接口规范,所以无法进行直接绑定,中间需要加一个适配层(Adaptationlayer),通过对应的适配器来适配具体的日志实现框架,其对应的适配器其实就间接的实现了slf4j-api的接口规范。

注意:在图中对于logback需要引入两个jar包,不过在maven中有一个传递的思想,当配置logback-classic时就会默认传递core信息,所以我们只需要引入logback-classic的jar包即可。

相关注意点

在使用slf4j日志门面的过程中,若是引入了两个日志实现框架会报以下错误,并会默认实现第一个引入的日志实现:
image-20210307220735026
这里是同时配置simple以及logback情况,以pom.xml中配置顺序有关

实际应用

配合自身简单日志实现(slf4j-simple)

若想使用自身的日志实现框架,需要引入第三方jarslf4j-simple(slf4j自带实现类):

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.7.5</version>
</dependency>

其中该坐标包含了对应的slf4j-api的依赖,可以不用手动导入slf4j-api

image-20210307221415150

测试程序

public class LogTest {
    //获取Logger实例
    public static final Logger LOGGER = LoggerFactory.getLogger(LogTest.class);
    public static void main(String[] args) {
        System.out.println(LOGGER.getName());
        //打印日志记录
        LOGGER.error("error");
        LOGGER.warn("warn");
        LOGGER.info("info");
        LOGGER.debug("debug");
        LOGGER.trace("trace");
        //占位符输出
        String name = "changlu";
        int age = 20;
        LOGGER.info("报错,name:{},age:{}",name,age);
        //打印堆栈信息
        try {
            int i = 5/0;
        }catch (Exception e){
            LOGGER.error("报错",e);
        }
    }
}

默认日志等级为INFO,能够实现占位符输出,并且可以在日志等级方法中传入异常实例,来打印对应的日志信息。

注意点:若是我们只使用日志门面而没有导入指定的日志实现框架,调用Logger实例并调用日志方法会出现以下错误:

image-20210307212325551

配置logback日志实现

引入logback-classic的jar包,其中包含有slf4j-api以及logback-core的依赖,所以只需要引入该依赖即可:

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>

image-20210307222202760

public class LogTest {
    //获取Logger实例
    public static final Logger LOGGER = LoggerFactory.getLogger(LogTest.class);
    public static void main(String[] args) {
        System.out.println(LOGGER.getName());
        //打印日志记录
        LOGGER.error("error");
        LOGGER.warn("warn");
        LOGGER.info("info");
        LOGGER.debug("debug");
        LOGGER.trace("trace");
        //占位符输出
        String name = "changlu";
        int age = 20;
        LOGGER.info("报错,name:{},age:{}",name,age);
        //打印堆栈信息
        try {
            int i = 5/0;
        }catch (Exception e){
            LOGGER.error("报错",e);
        }
    }
}

配置Log4J日志实现(需适配器)

首先添加日志框架实现依赖

之前在1.3中介绍,对于Log4jJUL这些比较早出现的日志实现框架需要有对应的适配层,在这里我们引入对应的适配器slf4j-log412的依赖坐标:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.25</version>
</dependency>

slf4j-log4j12坐标中实际就包含了Log4j以及slf4j-api依赖,所以我们添加该坐标即可。

image-20210307224435135

添加log4j.properties配置文件

# rootLogger日志等级为trace,输出到屏幕上
log4j.rootLogger = trace,console
# console
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern= [%-5p]%r %l %d{yyyy-MM-dd HH:mm:ss:SSS} %m%n

测试程序

public class LogTest {
    //获取Logger实例
    public static final Logger LOGGER = LoggerFactory.getLogger(LogTest.class);
    public static void main(String[] args) {
        System.out.println(LOGGER.getName());
        //打印日志记录
        LOGGER.error("error");
        LOGGER.warn("warn");
        LOGGER.info("info");
        LOGGER.debug("debug");
        LOGGER.trace("trace");
        //占位符输出
        String name = "changlu";
        int age = 20;
        LOGGER.info("报错,name:{},age:{}",name,age);
        //打印堆栈信息
        try {
            int i = 5/0;
        }catch (Exception e){
            LOGGER.error("报错",e);
        }
    }
}

配置JUL日志实现(需适配器)

对于slf4j日志门面实现JUL日志框架需要使用是适配器来实现slf4j的日志接口,我们直接添加对应适配器依赖如下:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-jdk14</artifactId>
    <version>1.5.6</version>
</dependency>

JUL是我们jdk自带的日志框架,所以不需要额外引入jar包,引入slf4j-jdk14坐标,其中就包含了slf4j-api的依赖,所以我们只需要引入一个坐标即可。

image-20210307225832423

测试程序

public class LogTest {
    //获取Logger实例
    public static final Logger LOGGER = LoggerFactory.getLogger(LogTest.class);
    public static void main(String[] args) {
        System.out.println(LOGGER.getName());
        //打印日志记录
        LOGGER.error("error");
        LOGGER.warn("warn");
        LOGGER.info("info");
        LOGGER.debug("debug");
        LOGGER.trace("trace");
        //占位符输出
        String name = "changlu";
        int age = 20;
        LOGGER.info("报错,name:{},age:{}",name,age);
        //打印堆栈信息
        try {
            int i = 5/0;
        }catch (Exception e){
            LOGGER.error("报错",e);
        }
    }
}

添加slf4j-nop依赖(日志开关)

当添加了slf4j-nop坐标后,其相当于一个日志开关,导入实现以后就不会使用任何实现框架:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-nop</artifactId>
    <version>1.7.27</version>
</dependency>

image-20210307231206025

测试程序

public class LogTest {
    //获取Logger实例
    public static final Logger LOGGER = LoggerFactory.getLogger(LogTest.class);
    public static void main(String[] args) {
        LOGGER.error("error");
        LOGGER.warn("warn");
        LOGGER.info("info");
        LOGGER.debug("debug");
        LOGGER.trace("trace");
    }
}

image-20210307230924201

默认就关闭了slf4j的日志框架使用。

桥接旧的日志实现框架

直接举场景来说明:对于一些老项目直接使用的是Log4j或JUL的日志实现框架,并没有使用到日志门面来进行管理日志框架,当项目需要迭代升级时,我们想把原先的日志实现框架切换为logback,此时会出现一个问题,若是我们直接将对应的日志jar包更改为logback,那么项目中会出现大量报错,因为原先引入的包是import org.apache.log4j.Logger;,此时就会出现问题,我们需要重新修改大量的代码,需要耗费大量的时间与精力。

解决方案:在slf4j中可以使用桥接器从而让我们不用修改一行代码实现日志框架的切换。在slf4j中附带了几个桥接木块,这些模块对于log4j、JCL和JUL的API调用重定向(其实就是全限定名与原来的完全相同)。

下图包含了对应的解决方案:

image-20210308195930231

可用log4j-over-slf4j.jar替代Log4j

log4j-over-slf4j桥接器使用

模拟场景
老项目直接使用的是org.apache.log4j.Logger,现今项目迭代升级,需要使用Logback日志框架

我们首先将log4jjar包移除,之后引入logback-classic依赖坐标,此时就会报错

解决方案:使用桥接器log4j-over-slf4j

引入坐标依赖:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>log4j-over-slf4j</artifactId>
    <version>1.7.27</version>
</dependency>

不用修改任何代码即可替换日志框架

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值