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

news2024/11/26 10:30:26

最近在工作中,发现接触到的很多小伙伴分不清楚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 关系图

在这里插入图片描述

日志框架完整集成例子

首先设置资源目录

在这里插入图片描述

logback 日志框架完整集成例子

 <!--slf4j 依赖-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <!-- logback依赖 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<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 普通文件-->
    <appender name="fileAppender" class="ch.qos.logback.core.FileAppender">
        <!-- 引入文件位置 -->
        <file>${logDir}/test_logback.log</file>
        <!-- 配置日志输出格式 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!-- 格式引用通用属性配置 -->
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>

    <!-- 配置控制台appender -->
    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <!--默认:System.out 表示以黑色字体输出日志-->
        <!--设置:System.err 表示以红色字体输出日志-->
        <target>
            System.err
        </target>
        <!--配置日志输出格式-->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!-- 格式引用通用属性配置 -->
            <pattern>${pattern}</pattern>
        </encoder>
    </appender>
    <!--
        日志记录器
        配置root logger
        level:配置日志级别
        可以同时配置多个appender,做日志的多方向输出
    -->
    <root level="ALL">
        <!-- 引入控制台appender -->
        <appender-ref ref="consoleAppender"/>
        <!-- 引入普通文件appender -->
        <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设置的文件位置以及输出内容
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

log4j2 日志框架完整集成例子

 <!--log4j2 依赖-->
        <!-- Slf4j的核心包,只有日志的接口,整合log4j2并没有实现 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <!-- 桥接器,将JCL的日志输出重定向到Slf4j中 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>1.7.25</version>
            <scope>runtime</scope>
        </dependency>
        <!-- 导入日志框架核心包与接口包 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.9.1</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.9.1</version>
            <scope>runtime</scope>
        </dependency>
        <!--用于slf4j与log4j2保持桥接 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.9.1</version>
            <scope>runtime</scope>
        </dependency>
        <!--用于解决web环境下关闭服务器时可能出现的log4j线程无法及时关闭的warn,web工程需要包含log4j-web,非web工程不需要 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-web</artifactId>
            <version>2.9.1</version>
            <scope>runtime</scope>
        </dependency>
        <!--使用log4j2的AsyncLogger时需要包含disruptor -->
        <dependency>
            <groupId>com.lmax</groupId>
            <artifactId>disruptor</artifactId>
            <scope>runtime</scope>
            <version>3.4.2</version>
        </dependency>

log4j2.xml

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

    <Properties>
        <!-- 需要配置日志目录 -->
        <Property name="baseDir">E:/code/log</Property>
        <Property name="appName">test_log4j2</Property>
        <Property name="pattern">%d %-5p [%t] [%c{1.}] %.-300m%n</Property>
    </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设置的文件位置以及输出内容
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/92520.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

项目式学习法(PBL)如何让你快速成为行业专家【一杯咖啡谈项目】

项目人人都是主角&#xff0c;没有旁观者。我们每个人也应当好PM&#xff0c;这就离不开学习提升自己&#xff0c;&#xff0c;如此&#xff0c;方能更好推动经济社会高质量发展。 1、项目式学习是什么&#xff1f; 关于项目式学习&#xff0c;目前国内外还没有个统一的定义&…

【python】 json字符串转对象

目录 一&#xff1a;json对象转换为json字符串 二&#xff1a;json字符串转换为json对象 三&#xff1a;json字符串{"name":"lily","sno":1001} 四&#xff1a;python面向对象程序设计 一&#xff1a;json对象转换为json字符串 import json…

Elasticsearch 安装及启动【Linux】

一、下载安装包 1.下载 Elasticsearch 官网下载地址&#xff1a;https://www.elastic.co/cn/downloads/past-releases#elasticsearch 2.下载 Kibana Kibana 数据可视化平台可以选择性安装 官网下载地址&#xff1a;https://www.elastic.co/cn/downloads/past-releases#kiban…

连续仨月霸占牛客榜首京东T8呕心巨作:700页JVM虚拟机实战手册

什么是Java虚拟机&#xff1f; 虚拟机是一种抽象化的计算机&#xff0c;通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机有自己完善的硬体架构&#xff0c;如处理器、堆栈、寄存器等&#xff0c;还具有相应的指令系统。JVM屏蔽了与具体操作系统平台相关的信息…

怎么防止同事用Evil.js的代码投毒

最近Evil.js被讨论的很多&#xff0c;项目介绍如下 项目被发布到npm上后&#xff0c;引起了激烈的讨论&#xff0c;最终因为安全问题被npm官方移除&#xff0c;代码也闭源了 作为一个前端老司机&#xff0c;我肯定是反对这种行为&#xff0c;泄私愤有很多种方式&#xff0c;代…

深度学习——多GPU训练代码实现

1.数据并行性。 一台机器有K个GPU&#xff0c;给定训练模型&#xff0c;每个GPU参数值是相同且同步&#xff0c;每个GPU独立地维护一组完整地模型参数。k2时数据并行地训练模型&#xff0c;利用两个GPU上的数据&#xff0c;并行计算小批量随机梯度下降。 K个GPU并行训练过程&a…

【Spring Cloud】Eureka注册中心从原理到实战图文详细教程

本期目录1. Eureka介绍1.1 Eureka能解决的问题2. Eureka原理3. 搭建Eureka Server3.1 引入依赖3.2 编写启动类3.3 修改配置文件3.4 启动Eureka微服务4. 服务注册4.1 导入依赖4.2 修改配置文件4.3 重启微服务4.4 启动多个微服务实例5. 服务发现5.1 修改业务层代码5.2 在RestTemp…

A_A05_002 sscom33串口调试助手使用

目录 一、软件获取 二、软件基本功能介绍 1、接收区 2、串口通信参数配置区 3、串口打开关闭与其他设置区域 4、手动发送区域 5、多文本发送区 6、辅助区域 三、注意事项 一、软件获取 网盘链接 直戳跳转 二、软件基本功能介绍 1、接收区 接收区就是接收外部设备给串口…

【2022年终总结】总结自己的2022,展望2023

目录一、工作杭州【述职-涨薪】【项目】从0到1&#xff0c;从1到多&#xff0c;在工作中寻找方法&#xff0c;承担更多的责任【技能】丰富了技术广度武汉1. 【项目】一个人就是一个团队二、成为博客新秀&前端领域优质创作者三、生活旅行猫猫情感2023年的flag学习&#xff1…

FFmpeg- 常用的滤镜命令

下面来熟悉一下常用的对视频操作的几个命令。这次需要完成的命令也包括在其中。 视频的画面大小的剪切(crop filter) 将输入的视频的帧&#xff0c;以左上角为坐标的原点&#xff0c;剪切成x,y坐标开始的指定大小。 语法&#xff1a; # []包裹的选项是可选的 crop ow[:oh[:x[:…

3D三维地图APP

3D三维地图APP 发布时间&#xff1a;2018-07-19 版权&#xff1a; 3D地图依据高程数据等对地表进行渲染&#xff0c;实现地表的起伏&#xff0c;模拟出真实的三维场景&#xff0c;让你有如身临其境般的感觉。 &#xff08;注&#xff1a;Bigemap 3D地图是一个三维地图浏览功能…

RNA-seq 详细教程:Wald test(10)

学习目标 了解生成比较结果所需的步骤&#xff08;Wald 检验&#xff09;总结不同层次的基因过滤了解对数倍变化收缩结果探索 默认情况下&#xff0c;DESeq2 使用 Wald 检验来识别在两个样本之间差异表达的基因。给定设计公式中使用的因素&#xff0c;以及存在多少个因素水平&a…

大学生影视主题网页制作 腾龙电影网页设计模板 学生静态网页作业成品 dreamweaver电影HTML网站制作

HTML实例网页代码, 本实例适合于初学HTML的同学。该实例里面有设置了css的样式设置&#xff0c;有div的样式格局&#xff0c;这个实例比较全面&#xff0c;有助于同学的学习,本文将介绍如何通过从头开始设计个人网站并将其转换为代码的过程来实践设计。 文章目录一、网页介绍一…

基于WIFI无线组网的水雨情远程监测预警系统

水雨情是重要的水文资料&#xff0c;在水资源配置和管理中有重要的参考价值&#xff0c;具体是指水位、流速、流量、降雨量、降雨强度等参数。随着物联网、雷达遥测、无线通信技术的发展&#xff0c;这些数据都能实现自动感知和远程监测&#xff0c;对于防汛抗洪和日常巡检有重…

MySql explain

执行计划是SQL语句经过查询分析器后得到的 抽象语法树 和 相关表的统计信息 作出的一个查询方案&#xff0c;这个方案是由查询优化器自动分析产生的。由于是动态数据采样统计分析出来的结果&#xff0c;所以可能会存在分析错误的情况&#xff0c;也就是存在执行计划并不是最优的…

经CSDN副总裁点拨,我发现了世界杯球队与优秀开发团队的共通点

☆ 世界杯已经快要接近尾声了&#xff0c;而无论法国还是阿根廷谁能走到最后&#xff0c;无疑他们都是非常优秀的世界杯球队&#xff0c;甚至可以说&#xff0c;能进入世界杯的球队&#xff0c;都是举世瞩目的国家队阵容。 ☆ 而我最近也一直在思考&#xff0c;那么我们的开发团…

SpringBoot2核心技术(核心功能)- 05、Web开发【5.1 SpringMVC自动配置概览+5.2简单功能分析】

1、SpringMVC自动配置概览 Spring Boot provides auto-configuration for Spring MVC that works well with most applications.(大多场景我们都无需自定义配置) The auto-configuration adds the following features on top of Spring’s defaults: ● Inclusion of ContentN…

手把手教你实现一个function模板

1.实现function需要用到的相关技术 建议看本文之前&#xff0c;需要先了解C11 function或者boost::function模板的基本用法&#xff0c;也最好看一下我的另外一篇文章&#xff1a; c11 function模板&#xff1a;模板特化与可变参数函数模板 如果你使用过C11 function模板或者…

关于Linux内核中的异步IO的使用

我们都知道异步IO的作用&#xff0c;就是可以提高我们程序的并发能力&#xff0c;尤其在网络模型中。在linux中有aio的一系列异步IO的函数接口&#xff0c;但是这类函数都是glibc库中的函数&#xff0c;是基于多线程实现&#xff0c;不是真正的异步IO&#xff0c;在内核中有真正…

生成无限制微信小程序码

生成无限制的微信小程序码&#xff0c;主要是通过后端请求微信的接口&#xff0c;然后微信会把小程序码返回来。 本文不讲详细的方法了&#xff0c;只讲其中的一些关键点&#xff0c;官方文档也附上去了&#xff0c;结合这些点看官方文档会比较方便。 方法&#xff1a; 获取…