Java核心技术-日志(下)

系列文章

Java核心技术-日志(上)


前言

先阅读Java核心技术-日志(上) 文章,了解整个Java系统的发展历史以及目前的现状,在前一篇文章中介绍了JCL+(Log4j,JUL)组合。本文介绍SLF4J+Logback组合。

Logback

Logback是由Log4j创始人设计的另一个开源日志组件,继承自Log4j。目前最新版本1.2.11Logback分为三个不同的模块:

模块功能
logback-core其它两个模块的基础
logback-classiclog4j 的一个优化版本,完整实现SLF4J API
logback-accessServlet容器集成提供通过Http来访问日志的功能

一、架构

Logback主要由下面三部分组成:

Logger —— 日志记录器,定义日志类型、级别,属于logback-classic 模块。
Appender —— 指定日志的输出方式和目的地,属于logback-core 模块。
Layout —— 格式化日志信息,属于logback-core 模块。

由于logback-classic实现了原生的SLF4J API,所以Logback的一般使用方式是 slf4j-api + logback-classic 的形式。

1.Logger

Logger作为日志的记录器,把它关联到应用的对应的LoggerContext上后存放日志对象,也可以定义日志类型、级别。
通过 LoggerFactory.getLogger() 可以获取到具体的 logger 实例,名字相同则返回的 logger 实例也相同。由于logback实现了slf4j,因此使用slf4j的Logger抽象类,和工厂类即可

Logger x = LoggerFactory.getLogger(“test-logback”);
Logger y = LoggerFactory.getLogger(“wombat”);

x,y 是同一个 logger 对象。

2.Appender

Appender主要用于指定日志输出的目的地,目的地可以是控制台、文件、远程套接字服务器、 MySQLPostreSQLOracle和其他数据库、 JMS和远程UNIX Syslog守护进程等。

3.Layout

Layout 负责把事件转换成字符串,格式化的日志信息的输出。

4.LoggerContext

每个Logger 都被关联到一个 LoggerContextLoggerContext负责创建Logger,也负责以树结构排列各Logger

Logback执行流程:
在这里插入图片描述

二、日志级别

Logback级别定义在:org.slf4j.event.Level

package org.slf4j.event;

public enum Level {
    ERROR(40, "ERROR"),
    WARN(30, "WARN"),
    INFO(20, "INFO"),
    DEBUG(10, "DEBUG"),
    TRACE(0, "TRACE");
    }

日志级别优先级:TRACE < DEBUG < INFO < WARN < ERROR

三、 配置文件

Logback查找配置的顺序如下所示:

1.在系统配置文件System Properties中寻找是否有logback.configurationFile对应的value
2.在classpath下寻找是否有logback-test.xml
3.在classpath下寻找是否有logback.groovy(即logback支持groovyxml两种配置方式)
4.在classpath下寻找是否有logback.xml

如果配置文件 logback-test.xmllogback.groovy,logback.xml 都不存在,那么 logback 默认配置,它是一个关联到Root LoggerConsoleAppender 组成。输出用模式为%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%nPatternLayoutEncoder 进行格式化。Root Logger 默认级别是 DEBUG

接下来测试下默认配置:
添加maven依赖

  <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.36</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.11</version>
        </dependency>
    </dependencies>

测试程序,不添加任何配置:

package com.laopeng301;

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


public class LogbackTest
{
    public static void main(String[] args) {
        Logger logger= LoggerFactory.getLogger(LogbackTest.class);
        logger.info("info测试默认配置");
        logger.trace("trace默认配置不输出");
    }
}

15:02:50.304 [main] INFO com.laopeng301.LogbackTest - info测试默认配置

由于默认配置的日志级别是DEBUG,所以trace日志不会打印。

logback.xml常用配置

在这里插入图片描述
Logback配置文件非常的灵活,整个配置文件结构:
<configuration>开头,后面有零个或多个<appender>元素,有零个或多个<logger>元素,有最多一个<root>元素。

<Configuration scan="true" scanPeriod="60 seconds" debug="false">
    <Property name="app-name" value="logback-test" />
    <ContextName>${app-name}</ContextName>
    <Appender>
        
    </Appender>

    <Logger>
       
    </Logger>

    <Root>
       
    </Root>
</Configuration>  
Configuration
<configuration scan="true" scanPeriod="60 seconds" debug="false"> 

</configuration> 
参数说明
scan设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true
scanPeriod监测配置文件是否有修改的时间间隔,没有给出时间单位,默认单位是毫秒。当scantrue时,此属性生效。默认的时间间隔为1分钟
debug设置为true时,将打印出logback内部日志信息,默认false
Property & ContextName &Timestamp
<configuration scan="true" scanPeriod="60 seconds" debug="false"> 
   <Property name="app-name" value="logback-test" />
    <ContextName>${app-name}</ContextName>
    <Timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>
</configuration> 
  1. Property:定义变量,两个属性namevalue<Property>定义的值会被插入到Logger上下文中,可以使“${}”来使用变量。
  2. ContextName:设置上下文名称,每个Logger都关联到Logger上下文,默认上下文名称为default
  3. <Timestamp>:获取时间戳字符串,两个属性key(标示名称),datePattern(格式化SimpleDateFormat)。
Appender

负责写日志的组件,它有两个必要属性nameclassname指定Appender名称,class指定Appender的全限定名。例如:ch.qos.logback.core.ConsoleAppender

ConsoleAppender

控制台输出日志

<Configuration scan="true" scanPeriod="60 seconds" debug="false">
    <Property name="app-name" value="logback-test" />
    <ContextName>${app-name}</ContextName>
    <Timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>
    <Appender name="CONSOLE-LOG" class="ch.qos.logback.core.ConsoleAppender">
      <Encoder>
          <Pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</Pattern>
          <Target>System.out</Target>
      </Encoder>
    </Appender>

    <Root level="DEBUG">
          <Appender-ref ref="CONSOLE-LOG"></Appender-ref>
    </Root>
</Configuration>

<Encoder>:对日志进行格式化
<Target>:字符串System.out(默认)或者System.err

FileAppender

把日志记录到文件

  <Appender name="FILE-LOG" class="ch.qos.logback.core.FileAppender">
            <File>testFile.log</File>
            <Append>true</Append>
            <Encoder>
              <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
            </Encoder>
    </Appender>

<File>:被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。

<Append>true,日志被追加到文件结尾, false,清空现存文件,默认是true

<Encoder>:对日志进行格式化

<Prudent>:如果是 true,日志会被安全的写入文件,即使其他的FileAppender也在向此文件做写入操作效率低,默认是 false

RollingFileAppender

滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件

1.TimeBasedRollingPolicy 时间滚动策略

<Çonfiguration>
       <Appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
              <!--被写入的文件名-->
          <File>test.log</File>
              <!--日志追加到文件结尾 -->
              <Append>true</Append>
             <!--日志内容格式化 -->
          <Encoder>
             <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
          </Encoder>
              <!--发生滚动式,决定RollingFileAppender的行为,文件移动和命名,
              class定义滚动策略 TimeBasedRollingPolicy时间滚动策略 -->
          <RollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                    <!--滚动生成文件名的规则-->
              <FileNamePattern>tests.%i.log.zip</FileNamePattern>
                    <!--保留归档文件的最大数量,超出数量删除旧文件。-->
                    <MaxHistory>7</MaxHistory>
          </RollingPolicy>
       </Appender>
       <Root level="DEBUG">
          <appender-ref ref="FILE" />
       </Root>
</Çonfiguration>

上述配置表示每天生成一个日志文件,保存7天的日志文件。

2.FixedWindowRollingPolicy 固定窗口滚动策略

<Configuration>
   <Appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
          <File>test.log</File>

          <RollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
              <FileNamePattern>tests.%i.log.zip</FileNamePattern>
              <MinIndex>1</MinIndex>
              <MaxIndex>3</MaxIndex>
          </RollingPolicy>

          <TriggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
              <maxFileSize>5MB</maxFileSize>
          </TriggeringPolicy>
          <Encoder>
             <Pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</Pattern>
          </Encoder>
       </Appender>

   <Root level="DEBUG">
          <Appender-ref ref="FILE" />
       </Root>
</Configuration>

上述配置表示按照固定窗口模式生成日志文件,当文件大于5MB时,生成新的日志文件。窗口大小是1到3,当保存了3个归档文件后,将覆盖最早的日志。

以上是常用的Appender,需要了解其它的可以参考官网。

Logger

用来设置某一个包或具体的某一个类的日志打印级别、以及指定<Appender>

         <Logger name="类或者包" level="INFO" additivity="true">
              <Appender-ref ref="FILE" />
              <Appender-ref ref="CONSOLE" />
         </Logger>

name:用来指定受此Logger约束的某一个包或者具体的某一个类。
level: 用来设置打印级别
additivity: 是否向上级Logger传递打印信息。默认是true
Appender-ref:标识这个Appender将会添加到这个Logger
例如:

<logger name="com.apache.ibatis" level="TRACE"/>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
Root

Root Logger是所有<Logger>的上级

       <Root level="DEBUG">
          <Appender-ref ref="FILE" />
              <Appender-ref ref="CONSOLE" />   
       </Root>

四、 配置文件

1.添加maven依赖

  <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.36</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.11</version>
        </dependency>
    </dependencies>

2.新增配置文件:src/resource/logbackxml

<Configuration scan="true" scanPeriod="60 seconds" debug="false">
    <Property name="app-name" value="logback-test" />
    <ContextName>${app-name}</ContextName>
    <Timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>
    <Appender name="CONSOLE-LOG" class="ch.qos.logback.core.ConsoleAppender">
      <Encoder>
          <Pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</Pattern>
          <Target>System.out</Target>
      </Encoder>
    </Appender>
    <Appender name="FILE-LOG" class="ch.qos.logback.core.FileAppender">
            <File>testFile.log</File>
            <Append>true</Append>
            <Encoder>
              <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
            </Encoder>
    </Appender>
    <Root level="INFO">
          <Appender-ref ref="CONSOLE-LOG"></Appender-ref>
    </Root>
</Configuration>

3.测试类

package com.laopeng301;

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


public class LogbackTest
{
    public static void main(String[] args) {
        Logger logger= LoggerFactory.getLogger(LogbackTest.class);
        logger.info("info日志测试");
        logger.trace("trace在info级别不输出");
    }
}

185  [main] INFO  com.laopeng301.LogbackTest - info测试默认配置 

SLF4J

SLF4J即简单日志门面(Simple Logging Facade for Java)作为各种日志框架的简单Facade或抽象,例如:java.util.logging, logbackreload4j(log4j)

对于一般日志框架会选择slf4j-api作为门面,配上具体的实现框架(log4jlogback等),中间使用桥接器完成桥接。

在这里插入图片描述

1.单独SLF4J

单独slf4j-api是没有日志打印的效果,底层没有绑定具体的日志框架。
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.36</version>
</dependency>
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SLF4JTest {
    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger(SLF4JTest.class);
        logger.info("test");
    }
}
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation

2.SLF4J+logback

底层绑定logback日志实现框架
<dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.36</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.11</version>
        </dependency>
    </dependencies>

执行上述测试程序:

16:53:47.667 [main] INFO com.laopeng301.SLF4JTest - test

3.SLF4J+reload4j(Log4j)

底层绑定Log4j日志实现框架

  <dependencies>
        <!--reload4j适配器(包含slf4j-api)-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-reload4j</artifactId>
            <version>1.7.36</version>
        </dependency>
        <!--reload4j(原名Log4j)-->
        <dependency>
            <groupId>ch.qos.reload4j</groupId>
            <artifactId>reload4j</artifactId>
            <version>1.2.18.5</version>
        </dependency>
    </dependencies>

新增配置 src/resource/log4j.properties

log4j.rootLogger=DEBUG,console
#输出到控制台
log4j.appender.console=org.apache.log4j.ConsoleAppender
#设置输出样式
log4j.appender.console.layout=org.apache.log4j.PatternLayout
#日志输出信息格式为
log4j.appender.console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n

执行上述测试代码:

2022-04-27 16:58:48,165 [main] INFO  [com.laopeng301.SLF4JTest] - test

4.SLF4J+JUL

底层绑定Java自带的JUL日志实现框架
    <!--JUL适配器-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-jdk14</artifactId>
            <version>1.7.36</version>
        </dependency>

执行测试代码:

427, 2022 5:00:16 下午 com.laopeng301.SLF4JTest main
信息: test

5.SLF4J+Simple

底层绑定`SLF4J`官方推出的基本日志实现框架
<dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.36</version>
        </dependency>
        <!--基本的日志实现,-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.36</version>
        </dependency>
[main] INFO com.laopeng301.SLF4JTest - test

6.SLF4J+nop

关闭一切日志输出信息

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-nop</artifactId>
    <version>1.7.35</version>
</dependency>

7.SLF4J+LOG4J2

<!--Log4j2自带的日志门面-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.17.2</version>
        </dependency>
        <!--Log4j2具体的日志实现-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.17.2</version>
        </dependency>
        <!--导入slf4j日志的门面(最终这个案例的日志实现是log4j2) -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.36</version>
        </dependency>
        <!--为slf4j绑定日志实现 log4j2的适配器 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.17.2</version>
        </dependency>
2022-04-27 18:36:42,936 [main] INFO  SLF4JTest - test

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

laopeng301

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值