日志系列1——slf4j日志框架原理
1.前言
说到日志工具,日常工作或学习中肯定听过这些名词:log4j、logback、jdk-logging、slf4j、commons-logging等,它们之间有什么关系,在整个日志体系中又扮演什么角色呢?
日志框架分为三大类,包括日志门面、日志适配器、日志库。利用门面设计模式,即Facade来进行解耦,使日志使用变得更简单。

2.日志门面
门面设计模式是面向对象设计模式中的一种,日志框架采用的就是这种模式,类似JDBC的设计理念。它只提供一套接口规范,自身不负责日志功能的实现,目的是让使用者不需要关注底层具体是哪个日志库来负责日志打印机具体的使用细节等。目前用得最为广泛的日志门面有两种:slf4j和commons-logging
3.日志库
它巨头实现了日志的相关功能,主流的日志库有三个,分别是log4j、log-jdk、logback。最早Java想要记录日志只能通过System.out或System.err来完成,非常不方便。log4j就是为了解决这一问题而提出的,它是最早诞生的日志库。接着JDK也在1.4版本引入了一个日志库java.util.logging.Logger,简称log-jdk。这样市面上就出现了两种日志功能的实现,开发者在使用时需要关注所使用的日志库的具体细节。logback是最晚出现的,它与log4j出自同一个作者,是log4j的升级版且本身就实现了slf4j的接口。
4.日志适配器
日志适配器分为两种场景:
日志门面适配器,因为slf4j规范是后来提出的,在此之前的日志库是没有实现slf4j的接口的,例如log4j.所以,在工程里要想使用slf4j+log4j的模式,就额外需要一个适配器(slf4j+log4j12)来解决接口不兼容的问
日志库适配器,在一些老的工程里,一开始为了开发简单而直接使用了日志库API来完成日志打印,随着时间的推移想将原来直接调用日志库的模式改为业界标准的门面模式(例如slf4j+logback组合),但老工程代码里打印日志的地方太多,难以改动,所以需要一个适配器来完成从旧日志库的API到slf4j的路由,这样在不改动原有代码的情况下也能使用slf4j来统一管理日志,而且后续自由替换具体日志库也不是问题。
5.日志库的选用
如果是新工程,则推荐使用slf4j+logback模式,因为logback自身实现了slf4j的接口,不需要额外引入适配器,另外logback是log4j的升级版,具备比log4j更多的优点,可通过如下配置进行集成:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j-api.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback-core.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback-classic.version}</version>
</dependency>
如果是老工程,则需要根据所使用的日志库来确定门面适配器,通常情况下老工程使用的都是log4j,因此以log4j日志库为例,可通过如下配置进行集成:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j-api.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j-log4j12.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
如果老代码直接使用了log4j日志库提供的接口来打印日志,则还需要引入日志库适配器,配置实例如下所示:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${log4j-over-slf4j.version}</version>
</dependency>
6.logback.xml 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true">
<property name="application_name" value="web" />
<property name="LOG_PATH" value="c:" />
<!-- 控制台输出 -->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder charset="UTF-8">
<pattern>%date %-5level %logger{80} [%X{trans_id}] - %msg%n</pattern>
<!-- <pattern>%date [%thread] %-5level %logger{80} - %msg%n</pattern> -->
</encoder>
</appender>
<!-- 时间滚动输出 文件日志 -->
<appender name="file—debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debug</level>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_PATH}/logs/${application_name}/${application_name}_debug.%d{yyyy-MM-dd}_%i.log</FileNamePattern>
<MaxHistory>100</MaxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10mb</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder charset="UTF-8">
<pattern>%date [%thread] %-5level %logger{80} [%X{trans_id}] - %msg%n</pattern>
</encoder>
</appender>
<!-- 时间滚动输出 文件日志 -->
<appender name="file—info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>info</level>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_PATH}/logs/${application_name}/${application_name}_info.%d{yyyy-MM-dd}_%i.log</FileNamePattern>
<MaxHistory>100</MaxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10mb</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder charset="UTF-8">
<pattern>%date [%thread] %-5level %logger{80} [%X{trans_id}] - %msg%n</pattern>
</encoder>
</appender>
<!-- 时间滚动输出 level为 ERROR 日志 -->
<appender name="file—error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${LOG_PATH}/logs/${application_name}/${application_name}_error.%d{yyyy-MM-dd}_%i.log</FileNamePattern>
<MaxHistory>100</MaxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10mb</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder charset="UTF-8">
<pattern>%date [%thread] %-5level %logger{80} [%X{trans_id}] - %msg%n</pattern>
</encoder>
</appender>
<Logger name="org.apache.http.impl.conn.PoolingHttpClientConnectionManager" level="DEBUG" additivity="false">
<appender-ref ref="file—debug" />
</Logger>
<appender name="ASYNC-ERROR" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>256</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="file—error"/>
</appender>
<root level="info">
<appender-ref ref="stdout" />
<appender-ref ref="file—info" />
<appender-ref ref="file—error" />
</root>
</configuration>
实例代码如下:
private static final Logger logger =LoggerFactory.getLogger(ConfigureQuartz.class);
注意,logger对象被定义为static变量,这是因为这个logger与当前类绑定,避免每次都new一个新对象,造成资源浪费,甚至引发OutOfMemoryError问题。
在使用slf4j+具体日志库模式时,由于slf4j相当于充当api抽象接口,所以我们的日志打印是也是面向接口编程的,当我们需要更换具体的日志库时,我们只需要引入具体的maven依赖就可以了,并对原有的日志库依赖进行移除,而不需要改动代码。至此,slf4j的架构原理讲解完成,之后会对具体的日志库logback的配置文件进行讲解,本章只是先简单给出logback.xml配置文件的基本模板,下一章节《日志系列2——logback配置文件详解》敬请期待。
日志系列1——slf4j日志框架原理的更多相关文章
- Log4j2日志框架集成Slf4j日志门面
1.说明 本文介绍使用日志门面Slf4j打印日志, 底层日志实现使用Log4j2框架, 方便以后切换底层日志实现, Log4j2可以替换成Logback等. 2.依赖管理 在pom.xml依赖管理中导 ...
- Spring Boot系列一:默认日志logback配置解析
前言 今天来介绍下Spring Boot如何配置日志logback,我刚学习的时候,是带着下面几个问题来查资料的,你呢 如何引入日志? 日志输出格式以及输出方式如何配置? 代码中如何使用? 正文 Sp ...
- SLF4J日志门面
SLF4J官网:http://www.slf4j.org/ SLF4J的作用通俗点讲,就是可以让我们的项目以最小的代价更换不同的日志系统.无需修改代码,只需要添加.删除相应的jar包和配置文件. 1. ...
- 10min系列之二日志可视化进阶
10min系列之二日志可视化进阶(作者原创,同步发布在github) 本文需要有一定的python和前端基础,如果没基础的,请关注我后续的基础教程系列博客 本文所有的demo,都是浏览器下展示的 原创 ...
- 实现jul 日志重定向到 slf4j
需求背景 jul 指的是java.util.logging,是 java 内置的日志模块,目前流行的Java日志组件还包括 jcl(common-logging).slf4j/log4j/logbac ...
- mysql 开发进阶篇系列 41 mysql日志之慢查询日志
一.概述 慢查询日志记录了所有的超过sql语句( 超时参数long_query_time单位 秒),获得表锁定的时间不算作执行时间.慢日志默认写入到参数datadir(数据目录)指定的路径下.默认文件 ...
- log4j日志整合输出(slf4j+commonslog+log4j+jdklogger)
log4j日志整合输出(slf4j+commonslog+log4j+jdklogger) 博客分类: 日志 J2EE项目中,经常会用到很多第三方的开源组件和软件,这些组件都使用各自的日志组件,比 ...
- JAVAEE——SpringBoot日志篇:日志框架SLF4j、日志配置、日志使用、切换日志框架
Spring Boot 日志篇 1.日志框架(故事引入) 小张:开发一个大型系统: 1.System.out.println(""):将关键数据打印在控制台:去掉?写在一个文件 ...
- Log4j,Log4j2,logback,slf4j日志学习
日志学习笔记 Log4j Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.数据库等:我们也可以控制每一条日志的输出格式:通过定义每一条 ...
随机推荐
- 《并发编程的艺术》阅读笔记之Sychronized
概述 在JDK1.6中,锁一共四种状态,级别由低到高依次是:无锁状态.偏向锁状态.轻量级锁状态和重量级锁状态.锁可以升级但不能降级,这是为了提高获得锁和释放锁的效率.只有重量级锁涉及到操作系统线程切换 ...
- SpringCloud(五)学习笔记之Hystrix
在微服务架构中多层服务之间会相互调用,如果其中有一层服务故障了,可能会导致一层服务或者多层服务故障,从而导致整个系统故障.这种现象被称为服务雪崩效应. Hystrix组件就可以解决此类问题,Hystr ...
- TeamViewer11 万全免费
下载地址:百度网盘 c4xm TeamViewer 是一款简单易用且功能强大的远程控制软件,它能穿越内网,摆脱路由器或防火墙的限制,任何一方都不需要拥有固定IP地址.让不懂技术的朋友也能远程控制电脑, ...
- 关于Sysinternals Suite
sysinternals 的网站创立于1996年由Mark russinovich和布赖科格斯韦尔主办其先进的系统工具和技术资料·微软于2006年7月收购sysinternals公司 . 不管你是一个 ...
- python学习21之高级特性
'''''''''1.切片(1)谁可以进行切片操作?——列表,元组,字符串(2)切片有以下几种操作'''#[a:b]:取从下标为a的元素开始,到下标为b-1的元素结束L=['aa','bb','cc' ...
- 2019-2020-1 20199326《Linux内核原理与分析》第五周作业
第五周学习内容 庖丁解牛Linux内核分析第四章:系统调用的三层机制(上) Linux内核分析实验四 学到的一些知识 4.1用户态.内核态.中断 宏观上Linux操作系统的体系架构分为用户态和内核态 ...
- [Linux] 检查是否已有进程在运行
出处:sblim-sfcb-1.4.9 / sfcBroker.c int process_is_running() { #define STRBUF_LEN 512 #define BUF_LEN ...
- GIT分布式版本控制
1.1Git简介 linus 用C语言编写 2005年诞生 分布式版本管理系统 速度快,适合大规模,跨地区多人协同开发 Git不仅是一款开源的分布式版本控制系统,而且有其独特的功能特性,例如大多数的分 ...
- NPM 私有仓库的搭建
NPM 私有仓库的搭建 为什么搭建私有仓库 balabala,当然是有需求的时候嘛 搭建流程 介绍和安装verdaccio 备注: 程序启动后,配置文件为/home/work/.config/verd ...
- 前端跨域解决方案: JSONP的通俗解说和实践
对于前端开发者而言,跨域是一个绕不开的话题.只有真正明白了各种方案的工作机制,才能针对性地进行跨域方案选型.本文将以探索者的视角,试图用最通俗的语言对一种"鼎鼎大名"的跨域解决方 ...