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

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 最通俗易懂的 JAVA slf4j,log4j,log4j2,logback 关系与区别以及完整集成案例

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 关系图




23e56a4dd7504ee3803c513e23d91aae.png

日志框架完整集成例子

首先设置资源目录

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 ,这时候他会报错还是会用哪个呢,我们测试结果如下:

首先他会输出提示提醒你发现了哪些可以绑定的实现框架

然后会告诉你最终用了哪个

相关文章
|
3月前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
816 31
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
5月前
|
Java Maven Windows
使用Java创建集成JACOB的HTTP服务
本文介绍了如何在Java中创建一个集成JACOB的HTTP服务,使Java应用能够调用Windows的COM组件。文章详细讲解了环境配置、动态加载JACOB DLL、创建HTTP服务器、实现IP白名单及处理HTTP请求的具体步骤,帮助读者实现Java应用与Windows系统的交互。作者拥有23年编程经验,文章来源于稀土掘金。著作权归作者所有,商业转载需授权。
使用Java创建集成JACOB的HTTP服务
|
10天前
|
存储 缓存 Java
Java中的分布式缓存与Memcached集成实战
通过在Java项目中集成Memcached,可以显著提升系统的性能和响应速度。合理的缓存策略、分布式架构设计和异常处理机制是实现高效缓存的关键。希望本文提供的实战示例和优化建议能够帮助开发者更好地应用Memcached,实现高性能的分布式缓存解决方案。
32 9
|
2月前
|
人工智能 自然语言处理 Java
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
FastExcel 是一款基于 Java 的高性能 Excel 处理工具,专注于优化大规模数据处理,提供简洁易用的 API 和流式操作能力,支持从 EasyExcel 无缝迁移。
135 9
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
|
28天前
|
Java API Apache
java集成stable diffusion
通过REST API和JNI两种方法,我们可以在Java应用程序中集成Stable Diffusion模型。REST API方法更加简单和易于维护,而JNI方法则提供更高的性能。根据具体应用场景和需求,选择合适的集成方法,可以充分利用Stable Diffusion的强大功能,实现高效的图像生成和处理。
56 15
|
4月前
|
Java 程序员 API
Android|集成 slf4j + logback 作为日志框架
做个简单改造,统一 Android APP 和 Java 后端项目打印日志的体验。
181 1
|
4月前
|
JSON Java 开发工具
Java服务端集成Google FCM推送的注意事项和实际经验
本文分享了作者在公司APP海外发布过程中,选择Google FCM进行消息推送的集成经验。文章详细解析了Java集成FCM推送的多种实现方式,包括HTTP请求和SDK集成,并指出了通知栏消息和透传消息的区别与应用场景。同时,作者还探讨了Firebase项目的创建、配置和服务端集成的注意事项,帮助读者解决文档混乱和选择困难的问题。
176 1
|
4月前
|
JSON Java 开发工具
Java服务端集成Google FCM推送的注意事项和实际经验
公司的app要上海外,涉及到推送功能,经过综合考虑,选择Google FCM进行消息推送。 查看一些集成博客和官方文档,看的似懂非懂,迷迷惑惑。本篇文章除了将我实际集成的经验分享出来,也会对看到的博客及其中产生的疑惑、注意事项一一评论。 从官方文档和众多博客中,你会发现Java集成FCM推送有多种实现方式,会让生产生文档很乱,不知作何选择的困惑。
136 0
|
4月前
|
安全 算法 Java
数据库信息/密码加盐加密 —— Java代码手写+集成两种方式,手把手教学!保证能用!
本文提供了在数据库中对密码等敏感信息进行加盐加密的详细教程,包括手写MD5加密算法和使用Spring Security的BCryptPasswordEncoder进行加密,并强调了使用BCryptPasswordEncoder时需要注意的Spring Security配置问题。
261 0
数据库信息/密码加盐加密 —— Java代码手写+集成两种方式,手把手教学!保证能用!
|
4月前
|
数据采集 监控 Java
SpringBoot日志全方位超详细手把手教程,零基础可学习 日志如何配置及SLF4J的使用......
本文是关于SpringBoot日志的详细教程,涵盖日志的定义、用途、SLF4J框架的使用、日志级别、持久化、文件分割及格式配置等内容。
281 0
SpringBoot日志全方位超详细手把手教程,零基础可学习 日志如何配置及SLF4J的使用......