最通俗易懂的 JAVA slf4j,log4j,log4j2,logback 关系与区别以及完整集成案例

最近在工作中,发现接触到的很多小伙伴分不清楚logback slf4j 以及log4j 的关系,有的人认为是一个东西,有的人认为是完全没关系,或者说有关系但是不清楚具体是什么区别和联系,今天咱们就简单梳理下他们之间的联系和区别以及如何使用

slf4j 于log4j,log4j2,logback 是什么关系,有何区别

什么是 slf4j

slf4j不是一个真正意义的可用应用程序,他是一个接口层
就像java 的接口性质一样,单纯集成了slf4j 的话,执行比如log.info log.debug等方法,只能在控制台打印日志,并不会在持久化到文件,或者其他自定义介质上,slf4j至少需要一个实现层框架,比如log4j,logback等

什么是 log4j,log4j2,logback

log4j,log4j2(log4j的2.0+版本),logback都是log日志的实现框架,作者都是Ceki Gülcü或者说是他的团队,最早开发的是log4j,并基于slf4j和log4j,优化开发了logback,再后来又用全新的技术disruptor框架
重构log4j底层并将logback取其精华重新搭建了一个全新的框架log4j2
也就是log4j的2.0+版本,可以这么理解,logback是log4j的升级版,但并没有用log4j那套接口 log4j2
推翻了log4j和logbak所有底层实现,但是复用了log4j的几大模块和接口

slf4j,log4j,log4j2,logback的关系

前面说了slf4j只是接口层,必须依赖实现层的框架实现接口层才能真正实现日志记录 log4j(与slf4j接口一致无需适配),log4j2,logback(本身内嵌了slf4j
转换器)都是实现层的框架,但是其实都是有自己独立的接口层的,但是这就有一个问题
一个应用程序用了独立用了log4j款就改,如果哪天想要切换成logback框架的话,所有的log初始化以及log
debug,info等语句都要替换
那么工作量太大了,几乎就是整个项目级别的日志语法替换,所以就需要以后所有开发的应用程序都基于接口层统一提供log初始化以及log.debug,log.info语法记录
基于这一点log4j的作者Ceki Gülcü,独立开发了一个slf4j层,专门用来适配底层的实现
就算你这个日志实现框架比如log4j2,logback
目前提供的接口不兼容slf4j也没关系,再开发一个xxx-slf4j-impl实现就slf4j的接口就可以了,相当于做了一个adapter
比如应用程序的底层实现框架用的是log4j2,但是接口层我想要用slf4j接口层,那么就引入一个log4j-slf4j-impl.jar等就可以了

slf4j,log4j,log4j2,logback 时间线

log4j ->slf4j ->logback ->log4j2

slf4j,log4j,log4j2,logback 关系图

最通俗易懂的 JAVA slf4j,log4j,log4j2,logback 关系与区别以及完整集成案例_第1张图片

日志框架完整集成例子

首先设置资源目录

最通俗易懂的 JAVA slf4j,log4j,log4j2,logback 关系与区别以及完整集成案例_第2张图片

logback 日志框架完整集成例子

 
        <dependency>
            <groupId>org.slf4jgroupId>
            <artifactId>slf4j-apiartifactId>
            <version>1.7.25version>
        dependency>
        
        <dependency>
            <groupId>ch.qos.logbackgroupId>
            <artifactId>logback-classicartifactId>
            <version>1.2.3version>
        dependency>

logback.xml


<configuration>
    
    <property name="pattern" value="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L %thread %m%n"/>
    
    <property name="logDir" value="E:/code/log"/>

    
    <appender name="fileAppender" class="ch.qos.logback.core.FileAppender">
        
        <file>${logDir}/test_logback.logfile>
        
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            
            <pattern>${pattern}pattern>
        encoder>
    appender>

    
    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        
        
        <target>
            System.err
        target>
        
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            
            <pattern>${pattern}pattern>
        encoder>
    appender>
    
    <root level="ALL">
        
        <appender-ref ref="consoleAppender"/>
        
        <appender-ref ref="fileAppender"/>
    root>
configuration>

logback demo code

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

/**
 * @Author alan.wang
 */
public class LogTester {

    private static Logger logger = LoggerFactory.getLogger(LogTester.class);

    public static void main(String[] args){
        logger.debug("这是Log4j2 debug");
        logger.info("这是Log4j2 info");
        logger.warn("这是Log4j2 warn");
        logger.error("这是Log4j2 error");
    }

}

logback日志执行结果

我们看一下logback.xml设置的文件位置以及输出内容
最通俗易懂的 JAVA slf4j,log4j,log4j2,logback 关系与区别以及完整集成案例_第3张图片
最通俗易懂的 JAVA slf4j,log4j,log4j2,logback 关系与区别以及完整集成案例_第4张图片
最通俗易懂的 JAVA slf4j,log4j,log4j2,logback 关系与区别以及完整集成案例_第5张图片

log4j2 日志框架完整集成例子

 
        
        <dependency>
            <groupId>org.slf4jgroupId>
            <artifactId>slf4j-apiartifactId>
            <version>1.7.25version>
        dependency>
        
        <dependency>
            <groupId>org.slf4jgroupId>
            <artifactId>jcl-over-slf4jartifactId>
            <version>1.7.25version>
            <scope>runtimescope>
        dependency>
        
        <dependency>
            <groupId>org.apache.logging.log4jgroupId>
            <artifactId>log4j-coreartifactId>
            <version>2.9.1version>
            <scope>runtimescope>
        dependency>
        <dependency>
            <groupId>org.apache.logging.log4jgroupId>
            <artifactId>log4j-apiartifactId>
            <version>2.9.1version>
            <scope>runtimescope>
        dependency>
        
        <dependency>
            <groupId>org.apache.logging.log4jgroupId>
            <artifactId>log4j-slf4j-implartifactId>
            <version>2.9.1version>
            <scope>runtimescope>
        dependency>
        
        <dependency>
            <groupId>org.apache.logging.log4jgroupId>
            <artifactId>log4j-webartifactId>
            <version>2.9.1version>
            <scope>runtimescope>
        dependency>
        
        <dependency>
            <groupId>com.lmaxgroupId>
            <artifactId>disruptorartifactId>
            <scope>runtimescope>
            <version>3.4.2version>
        dependency>

log4j2.xml

<Configuration status="warn" monitorInterval="30">

    <Properties>
        
        <Property name="baseDir">E:/code/logProperty>
        <Property name="appName">test_log4j2Property>
        <Property name="pattern">%d %-5p [%t] [%c{1.}] %.-300m%nProperty>
    Properties>

    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="${pattern}"/>
        Console>

        <RollingFile name="File" fileName="${baseDir}/${appName}/${appName}.log" filePattern="${baseDir}/${appName}/%d{yyyyMMdd}-%i.${appName}.log">
            <PatternLayout pattern="${pattern}"/>

            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="2048 MB"/>
            Policies>

            <DefaultRolloverStrategy max="30">
                <Delete basePath="${baseDir}/${appName}" maxDepth="1">
                    <IfFileName glob="*/*.log"/>
                    <IfLastModified age="20d"/>
                Delete>
            DefaultRolloverStrategy>
        RollingFile>

    Appenders>

    <Loggers>

        <Root level="debug" includeLocation="false" additivity="false">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="File"/>
        Root>
    Loggers>
Configuration>

logback demo code

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

/**
 * @Author alan.wang
 */
public class LogTester {

    private static Logger logger = LoggerFactory.getLogger(LogTester.class);

    public static void main(String[] args){
        logger.debug("这是Log4j2 debug");
        logger.info("这是Log4j2 info");
        logger.warn("这是Log4j2 warn");
        logger.error("这是Log4j2 error");
    }

}

log4j2日志执行结果

我们看一下log4j2.xml设置的文件位置以及输出内容
最通俗易懂的 JAVA slf4j,log4j,log4j2,logback 关系与区别以及完整集成案例_第6张图片
最通俗易懂的 JAVA slf4j,log4j,log4j2,logback 关系与区别以及完整集成案例_第7张图片
最通俗易懂的 JAVA slf4j,log4j,log4j2,logback 关系与区别以及完整集成案例_第8张图片

logback,log4j2 同时框架同时存在时,slf4j会用哪个实现

有些时候我们引入第三方或者自己多个模块引入时会不小心同时集成了多个日志框架比如同时继承了logback和log4j2 ,这时候他会报错还是会用哪个呢,我们测试结果如下:

首先他会输出提示提醒你发现了哪些可以绑定的实现框架
在这里插入图片描述

然后会告诉你最终用了哪个
在这里插入图片描述

你可能感兴趣的:(java,devops以及相关,log4j,java,logback,slf4j,log4j2)