文章目录

  • 背景
  • SLF4J概述
  • 切换日志框架
  • 实际应用
    • 配合自身简单日志实现(slf4j-simple)
    • 配置logback日志实现
    • 配置Log4J日志实现(需适配器)
    • 配置JUL日志实现(需适配器)
    • 添加slf4j-nop依赖(日志开关)
  • 桥接旧的日志实现框架

背景

随着系统开发的进行,可能会更新不同的日志框架,造成当前系统中存在不同的日志依赖,让我们难以统一的管理和控制。就算我们强制要求所有的模块使用相同的日志框架,系统中也难以避免使用其他类似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日志门面的过程中,若是引入了两个日志实现框架会报以下错误,并会默认实现第一个引入的日志实现:

这里是同时配置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

测试程序

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实例并调用日志方法会出现以下错误:

配置logback日志实现

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

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

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依赖,所以我们添加该坐标即可。

添加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的依赖,所以我们只需要引入一个坐标即可。

测试程序

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>

测试程序

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");}
}

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

桥接旧的日志实现框架

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

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

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

可用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>

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

Java日志门面技术 SLF4J相关推荐

  1. Java日志门面技术 JCL

    文章目录 背景 JCL的诞生 JCL是什么? 快速入门 JCL原理 设计缺陷 背景 在前面博文中,我们分别讲述了常用的2个日志框架:JUL(Java Util Logging).Log4J.那么如何选 ...

  2. Java日志框架 -- 日志框架介绍、日志门面技术、JUL日志(JUL架构、JUL入门示例、JUL日志级别、JUL日志的配置文件)

    1. 日志的概念 日志文件是用于记录系统操作事件的文件集合,可分为事件日志和消息日志.具有处理历史数据.诊断问题的追踪以及理解系统的活动等重要作用. 2. Java日志框架 问题: 控制日志输出的内容 ...

  3. Java日志门面- JCL和 常用日志门面SLFJ详解

    使用日志门面的原因 目前经常用的日志框架技术有:JUL.Log4j.log4j2.logback用来记录日志信息 ,之前我们讲过,我们学习不同的日志框架.他们的API是不同的,这样难以进行有效的记忆, ...

  4. Java日志体系日志门面(Slf4j)日志实现(Log4j、Log4j2)详解

    1.背景 近日发生两次因日志使用不当导致的线上问题: 1.应用明明配置了info日志级别,却打印大量的debug日志,导致磁盘IO较高,很快就报磁盘空间不足告警 2.应用服务启动后报StackOver ...

  5. 日志门面技术(3):JCL(Jakarta Commons Logging)

    目录 背景 ▎ JCL的诞生 JCL 是什么? ▎快速入门案例 JCL原理 ✈ 源码断点查看执行流程 JCL日志门面总结 ☁ 每日一题:为什么要学习日志门面JCL? 日志框架出现的历史顺序:Log4j ...

  6. 日志门面框架Slf4j

    SLF4J的使用 简单日志门面(Simple Logging Facade For Java) SLF4J主要是为了给Java日志访问提供一套标准.规范 的API框架,其主要意义在于提供接口,具体的实 ...

  7. Java日志系统04 ---- slf4j门面日志

    目录标题 前言 简介 快速开始 Maven依赖 测试代码 Slf4j整合log4j Slf4j整合logback日志 logback日志简介 Logback使用 logback配置 Log4j项目升级 ...

  8. java日志管理(slf4j+logback,tomcat)

    对slf4j的理解: slf4j只是一个日志抽象层,独立于其他所有的日志类库,需要配合其他的日志类库使用,例如logback,具体的日志级别输出.记录位置.日志格式通过具体的日志类库来实现: slf4 ...

  9. java日志框架JUL、JCL、Slf4j、Log4j、Log4j2、Logback 一网打尽

    为什么程序需要记录日志 我们不可能实时的24小时对系统进行人工监控,那么如果程序出现异常错误时要如何排查呢?并且系统在运行时做了哪些事情我们又从何得知呢?这个时候日志这个概念就出现了,日志的出现对系统 ...

最新文章

  1. Go语言调度器之调度main goroutine(14)
  2. Maven(一)Maven及插件安装
  3. Ubuntu中设置环境变量PATH
  4. (3.5)HarmonyOS鸿蒙多按钮点击事件
  5. 使用jdbc执行SQL实现登录查询1-带配置文件和工具类
  6. Form界面设置只读
  7. 【STM32】关闭JTAG接口,引脚设置推挽输出
  8. 通过Xshell来访问和连接Linux
  9. php导出指定格式excel,php导出excel格式文件的例子
  10. Spark机器学习实例
  11. PayPal支付开发
  12. python如何解压zip文件_Python压缩解压zip文件
  13. 数据结构——循环队列
  14. mapping中insert List语句
  15. 1988年图灵奖--伊万·萨瑟兰简介
  16. 再劫面包店——未被实现的愿望的诅咒(正式版)
  17. 使用nginx配置服务器80端口指向多个服务,解决微信公众号等平台只能绑定80端口问题。
  18. matlab论文答辩题目,毕业设计答辩评及参考题目.doc
  19. Windows下Solr的安装与配置,附DIH全量导入MySQL数据、IK分词器配置详解——不用集成Tomcat
  20. window系统未能启动服务器,Windows系统下Apache服务器无法启动的问题解决

热门文章

  1. C语言基础知识手册(自用)
  2. Glide centerCrop fitCenter和ImageView的scaleType的关系,互相影响的探讨
  3. 运维 之 堡垒机开发
  4. Neuron综述:睡眠和警觉的时空动态
  5. x86、x64、amd64和arm CPU 架构 MSVC的各种版本 Visual Studio的安装
  6. python 中pandask的 iterrows、itertuples、iteritems的理解及遍历,用‘列名’和‘索引’方式访问,及速度比拼
  7. 搜索引擎百度/360/搜狗关键词搜索提交信息
  8. 赴美参加学术会议办理流程
  9. 软件测试方法之场景法详解及实战
  10. C语言动态数组(malloc()函数动态分配内存)