日志框架之日志门面SLF4J的使用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了日志框架之日志门面SLF4J的使用相关的知识,希望对你有一定的参考价值。

(日志框架之日志门面SLF4J的使用)

SLF4J概述

SLF4J日志门面主要提供两大功能:

日志框架的绑定: 将应用程序代码与具体的日志记录实现绑定,还可以在运行时切换不同的日志记录实现。

日志框架的桥接:将日志记录到一个共同的目标日志API中,可以维护更好的可读性和可维护性的应用程序

SLF4J的简单使用

        <!-- slf4j 日志门面 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.26</version>
        </dependency>

        <!-- slf4j 内置的简单实现 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.21</version>
        </dependency>
public class Slf4j 

    public static final Logger LOGGER = LoggerFactory.getLogger(Slf4j.class);

    @Test
    public void test() 
        //日志输出
        LOGGER.error("error");
        LOGGER.warn("wring");
        LOGGER.info("info");
        LOGGER.debug("debug");
        LOGGER.trace("trace");

        //使用占位符输出日志信息
        String name = "hello slf4j";
        LOGGER.info("占位符输出日志信息:", name);

        //捕获异常,让日志输出,而非输出堆栈信息
        try 
            int i = 1 / 0;
         catch (Exception e) 
            // e.printStackTrace();
            LOGGER.error("异常输出:", e);

        
    

14:25:02.512 [main] ERROR cn.ybzy.Slf4j - error
14:25:02.520 [main] WARN cn.ybzy.Slf4j - wring
14:25:02.520 [main] INFO cn.ybzy.Slf4j - info
14:25:02.520 [main] INFO cn.ybzy.Slf4j - 占位符输出日志信息:hello slf4j
14:25:02.525 [main] ERROR cn.ybzy.Slf4j - 异常输出:
java.lang.ArithmeticException: / by zero
	at cn.ybzy.Slf4j.test(Slf4j.java:27)

SLF4J与日志框架的绑定

slf4j日志门面与日志实现框架的绑定关系如下: 日志框架出现的时间顺序:

log4j -->JUL-->JCL--> slf4j --> logback --> log4j2

因此,在实现日志框架的绑定/切换的时候,log4j与jul日志框架需要间接添加日志的适配器

日志框架的绑定过程

1.导入SLF4J库

2.导入绑定具体的日志实现框架

注意:

1.绑定已经实现了slf4j的日志框架,直接添加对应依赖

2.绑定没有实现slf4j的日志框架,先添加日志的适配器,再添加实现类的依赖

3.slf4j有且仅有一个日志实现框架的绑定(如果出现多个默认使用第一个依赖日志实现)

3.配置日志框架

3.使用 SLF4J API 记录日志

使用 SLF4J 中的 Logger 接口记录日志:

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

public class MyClass 
    private static final Logger logger = LoggerFactory.getLogger(MyClass.class);
    
  public void myMethod()
      logger.info("info");
  

slf4j+slf4j-simple

        <!-- slf4j 日志门面 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.26</version>
        </dependency>

        <!-- slf4j 内置的简单实现 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.21</version>
        </dependency>

配置示例

# 默认日志等级,当在源代码中未指定时使用
org.slf4j.simpleLogger.defaultLogLevel=debug

# 日志文件名,如果日志输出到文件中
# org.slf4j.simpleLogger.logFile=mylogfile.log

# 只显示Logger名称的最后一部分(最末尾的点之后的部分)
org.slf4j.simpleLogger.showShortLogName=true

# 显示每个日志信息的时间和日期
org.slf4j.simpleLogger.showDateTime=true

# 日志消息的日期和时间格式
org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss.SSS

# 特定记录器的日志等级
# org.slf4j.simpleLogger.log.com.foo=warn

# 替换 WARN 级别输出的字符串
# org.slf4j.simpleLogger.warnLevelString=WARNING

slf4j+logback

        <!-- slf4j 日志门面 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.26</version>
        </dependency>

        <!--logback 日志实现-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>

配置示例

<configuration>

    <!-- 控制台输出的 appender -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%dHH:mm:ss.SSS [%thread] %-5level %logger36 -
                %msg%n
            </pattern>
        </encoder>
    </appender>

    <!-- 日志文件输出的 appender -->
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>logs/myLogFile.log</file>
        <append>false</append>
        <encoder>
            <pattern>%dHH:mm:ss [%thread] %-5level %logger36 -
                %msg%n
            </pattern>
        </encoder>
    </appender>

    <!-- 各个包的日志级别 -->
    <logger name="com.example.myapp" level="INFO" />
    <logger name="org.springframework.data" level="DEBUG" />
    <logger name="org.hibernate" level="WARN" />

    <!-- 日志级别 root 日志级别 -->
    <root level="INFO">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE" />
    </root>

</configuration>

slf4j+nop

		<!-- slf4j 日志门面 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.26</version>
        </dependency>
        
       <!-- nop日志开关-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-nop</artifactId>
            <version>1.7.25</version>
        </dependency>

配置示例

slf4j+log4j

	     <!-- slf4j日志门面 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.26</version>
        </dependency>
        
      <!--  绑定log4j日志实现,需要导入slf4j-log4j12适配器-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.12</version>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

配置示例

#配置根日志级别
log4j.rootLogger=INFO, stdout, FILE

#配置控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%dyyyy-MM-dd HH:mm:ss %-5p %c1:%L - %m%n

#配置日志文件输出
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
log4j.appender.FILE.File=./logs/application.log
log4j.appender.FILE.MaxFileSize=10MB
log4j.appender.FILE.MaxBackupIndex=10
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=%dyyyy-MM-dd HH:mm:ss %-5p %c1:%L - %m%n

slf4j+jul

		 <!-- slf4j日志门面 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.26</version>
        </dependency>
        
  	 	 <!-- 绑定jul日志实现,需要导入slf4j-jdk14适配器-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-jdk14</artifactId>
            <version>1.7.25</version>
        </dependency>

配置示例

# 将JUL的日志委托给SLF4J API
handlers = org.slf4j.bridge.SLF4JBridgeHandler
# 配置的是日志级别
.level = FINEST
org.slf4j.bridge.SLF4JBridgeHandler.level = FINEST

SLF4J桥接旧的日志框架

SLF4J桥接旧的日志框架示意图:

SLF4J提供的桥接器

<!-- log4j-->
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>log4j-over-slf4j</artifactId>
	<version>$version</version>
</dependency>
<!-- jul -->
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>jul-to-slf4j</artifactId>
	<version>$version</version>
</dependency>
<!--jcl -->
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>jcl-over-slf4j</artifactId>
	<version>$version</version>
</dependency>

SLF4J桥接旧的日志框架流程:

1. 移除老的日志框架的依赖

2. 添加SLF4J提供的桥接组件

3. 添加SLF4J的具体实现

桥接旧的日志框架,如:将系统使用的logf4j日志框架切换到logback日志框架

旧的日志系统

  	 <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
public class Log4j 
    public static final Logger LOGGER = Logger.getLogger(Log4j.class);

    @Test
    public void test()throws Exception
        LOGGER.info("hello lgo4j");
    

INFO cn.ybzy.Log4j.test(Log4j.java:12) 2021-03-21 15:11:30,580 hello lgo4j

移除旧日志框架的依赖

当移除log4j的依赖时,项目中使用到的地方将报错

添加SLF4J提供的桥接组件

引入slf4j日志门面与log4j的桥接器,原来报错的地方全部恢复正常

   	<!-- slf4j日志门面 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.26</version>
        </dependency>

         <!--配置log4j的桥接器-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>log4j-over-slf4j</artifactId>
            <version>1.7.25</version>
        </dependency>

添加SLF4J的具体实现

    <!--logback 日志实现-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>

桥接旧的日志框架后测试:发现日志输出发生变法,桥接成功。

15:18:48.591 [main] INFO cn.ybzy.Log4j - hello lgo4j

以上是关于日志框架之日志门面SLF4J的使用的主要内容,如果未能解决你的问题,请参考以下文章

Java日志框架学习--日志门面--中

slf4j 日志门面模式应用(双亲委派特例)

slf4j 日志门面模式应用(双亲委派特例)

slf4j 日志门面模式应用(双亲委派特例)

slf4j 日志门面模式应用(双亲委派特例)

slf4j 日志门面模式应用(双亲委派特例)