现在spring boot日志流行两个一个是 Logback + SLF4J 组合,一个是 log4j2,每都有自己的特点。这里先使用spring boot默认的日志组合 Logback + SLF4J ,它使用起来比较简单没有太复杂的配置关系。

  • Logback日志库需要和SLF4J配合使用。SLF4J是一个实现Java日志切换库。
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.36</version>
</dependency>
-----------------  导入任何一个都可以   ------------------
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-logging</artifactId>
    <version>2.2.3.RELEASE</version>
</dependency>

1 日志基本输出

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TextLog {
    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger(TextLog.class);
        logger.info("Hello Logback!!");
    }
}

10:54:22.651 [main] INFO cn.core.sys.TextLog - Hello Logback!!
  • 配置文件(logback.xml)不存在,则默认将日志输出到控制台。

日志级别

所有日志都会遵守这个级别顺序 TRACE < DEBUG < INFO < WARN < ERROR

logger.trace("跟踪");
logger.debug("调试");
logger.info("信息");
logger.warn("警告");
logger.error("错误");

参数输出

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TextLog {
    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger(TextLog.class);
        logger.info("{}",    "日志");
        logger.info("{} {}", "日志", "信息");
        logger.info("{} {}", "日志");
        logger.info("{}",    "日志", "信息");
        logger.info("\\{}",  "日志");
        logger.info("{ }",   "日志");
    }
}
11:00:13.027 [main] INFO cn.core.sys.TextLog - 日志
11:00:13.030 [main] INFO cn.core.sys.TextLog - 日志 信息
11:00:13.031 [main] INFO cn.core.sys.TextLog - 日志 {}
11:00:13.031 [main] INFO cn.core.sys.TextLog - 日志
11:00:13.031 [main] INFO cn.core.sys.TextLog - {}
11:00:13.031 [main] INFO cn.core.sys.TextLog - { }
  • 声明的参数字符串传将递给第一个{},如果有第二个参数传递给第二个{}。
  • 如果参数没有对应的{},{}将输出为{}字符串。

异常输出

Logger logger = LoggerFactory.getLogger(Main.class);
try {
    throw new Exception("test exception");
} catch (Exception e) {
    logger.info("error", e);
}
11:04:15.972 [main] INFO cn.core.sys.TextLog - error
java.lang.Exception: test exception
	at cn.core.sys.TextLog.main(TextLog.java:9)
  • 可以将异常跟踪输出到日志。

2 logback.xml 配置文件

文件目录

src/main/
  |-java
  |  -cn/core/sys
  |     |-Test.java
  |-resources
     |-logback.xml

配置文件logback.xml 直接放在类路径下。例如 src下 ,resources 下,classpath下

种类

说明

appender 附加器

设置日志输出目的地和日志格式。由记录器和根指定。

logger 记录器

设置要输出的日志级别。通过将 appender 指定为子元素来设置输出目标等。

root 根

记录器的常用设置。

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%msg%n</pattern>
        </encoder>
    </appender>
    <root>
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

< appender >标签定义了 appender

  • <encoder>标签的<pattern>用于定义输出的格式。
  • ch.qos.logback.core.ConsoleAppender通过指定类,您可以定义要输出到控制台的附加程序。

< root >标签描述根记录器的设置

  • <appender-ref>指定 appender(日志输出目标)。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TextLog {
    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger(TextLog.class);
        logger.info("欢迎来到 韬哥的Logback!!");
    }
}
日志输出 
欢迎来到 韬哥的Logback!!

3 输出格式

日志消息打印格式可以定义为开头是特殊参数%m,例如.%

每个转换格式的日志输出信息可以加入特定参数。**例如,您可以传递一种格式,例如输出日期date

格式参数参照

设定参数

输出结果

说明

%c(c, lo, logger)

sample.logback.Main

打印记录器的名称。

%d(d,date)

2022-04-01 00:36:55,947

输出日期和时间。

%d{HH:mm}

00:57

输出指定时间格式。

%m(m, msg, message)

欢迎来到 韬哥的Logback!!

输出传递给记录器的消息。

a%n b

a<换行> b

输出与执行环境匹配的换行代码。

%p (p, le, level)

INFO

输出日志级别。

%t (t,thread)

main

输出日志时输出线程名。

例如 xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        // 日期%d  打印类名%c 空格  %m日志 %n回车换行
        <pattern>%d %c %m%n</pattern>
    </encoder>
</appender>
  <root>
    <appender-ref ref="STDOUT" />
  </root>
</configuration>
输出格式
2022-07-13 11:39:03,833 cn.core.sys.TextLog 欢迎来到 韬哥的Logback!!
 <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</pattern>
2022-07-13 12:13:23.647 [main] INFO  cn.core.sys.TextLog - 欢迎来到 韬哥的Logback!!
  • %date{yyyyMMdd} 自定义格式。

输出字符串

设定参数

输出结果

说明

[%5m]

“123” [ 123] “123456” [123456]

最小字符长度,右对齐并用半角空格填充。

[%.5m]

“123” [123] “123456” [23456]

超出最大字符长度,从左起依次省略超过位数的部分。

[%-5]

“123” [123 ]

最小宽度设置为负,它将左对齐。

[%.-5]

“123456” [12345]

如果最大宽度设置为负,则从右起依次省略超过位数的部分。

[%3.5m]

“123456” [23456] “12” [ 12]

最小宽度和最大宽度。

[%-3.-5m]

“123456” [12345] “1234” [1234]

最小宽度和最大宽度,它将左对齐。

4 日志记录器

  • <logger>标签中设置声明记录器的引用名称。
  • getLogger()记录器的名称作为方法参数传递给指定的记录器。
public class TextLog {
    public static void main(String[] args) {
        //指定输出的记录器名称 zhtbs
        Logger logger = LoggerFactory.getLogger("zhtbs");
        logger.debug("debug");                     |
        logger.info("欢迎来到 韬哥的Logback!!");    |
    }                                              |
}                                                  |
<appender>                                         |
    <encoder>                                      |
    <pattern></pattern>                            |
        </encoder>                                 |
    </appender>        |---------------------------|
    <logger name="zhtbs" level="info" />
    <root>
        <appender-ref ref="STDOUT" />
    </root>
   打印输出  zhtbs记录器的日志信息 
  2022-07-13 12:24:43.406 [main] INFO  sampleLogger - 欢迎来到 韬哥的Logback!!

level 输出级别

  • <logger>level使用属性指定记录器的级别。
  • 只输出指定级别以上的日志。

继承关系

记录器可以父子关系的命名关系输出日志信息。

  • 父子关系用“.”号来分割
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
  <logger name="zht" level="trace" />
  <logger name="zht.bar" level="info" />
    <root>
        <appender-ref ref="STDOUT" />
    </root>
</configuration>
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TextLog {
    public static void main(String[] args) {
        Logger z = LoggerFactory.getLogger("zht");
        z.trace("trace");
        z.debug("debug");
        z.info("info");
        Logger z1 = LoggerFactory.getLogger("zht.bar");
        z1.trace("trace");
        z1.debug("debug");
        z1.info("info");
        Logger z2 = LoggerFactory.getLogger("zht.bar.Hoge");
        z2.trace("trace");
        z2.debug("debug");
        z2.info("info");
    }
}
输出结果
2022-07-13 12:54:55.662 [main] TRACE zht - trace
2022-07-13 12:54:55.664 [main] DEBUG zht - debug
2022-07-13 12:54:55.664 [main] INFO  zht - info
2022-07-13 12:54:55.665 [main] INFO  zht.bar - info
2022-07-13 12:54:55.665 [main] INFO  zht.bar.Hoge - info
  • 默认情况下,根记录器的级别为debug
  • zht 使用logger覆盖它 trace级别日志。
  • zht.bar 记录器设置info,它之覆盖info级别的日志。
  • 另一方面,zht.bar.Hogeloggerfoo.bar继承了 logger 的设置,info`只输出级别日志。

记录器 appender 对应关系设置

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="zht1" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <appender name="zht2" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>zht.bar.Hoge : %msg%n</pattern>
        </encoder>
    </appender>
    <logger name="zht" level="trace" />
    <logger name="zht.bar.Hoge"  >
        <appender-ref ref="zht2" />
    </logger>
    <root>
        <appender-ref ref="zht1" />
    </root>
</configuration>
  • 通过为 logger 设置 appender,中的ref="zht2"属性来指定 logger 的日志输出方式,与appender name=“zht1” 名字为对应关系。
public static void main(String[] args) {
        Logger z = LoggerFactory.getLogger("zht");
        z.trace("trace");
        z.debug("debug");
        z.info("info");
        Logger z1 = LoggerFactory.getLogger("zht.bar");
        z1.trace("trace");
        z1.debug("debug");
        z1.info("info");
        Logger z2 = LoggerFactory.getLogger("zht.bar.Hoge");
        z2.trace("trace");
        z2.debug("debug");
        z2.info("info");
    }
输出结果
2022-07-13 12:56:27.667 [main] TRACE zht - trace
2022-07-13 12:56:27.669 [main] DEBUG zht - debug
2022-07-13 12:56:27.669 [main] INFO  zht - info
2022-07-13 12:56:27.670 [main] TRACE zht.bar - trace
2022-07-13 12:56:27.670 [main] DEBUG zht.bar - debug
2022-07-13 12:56:27.670 [main] INFO  zht.bar - info
zht.bar.Hoge : trace
2022-07-13 12:56:27.670 [main] TRACE zht.bar.Hoge - trace
zht.bar.Hoge : debug
2022-07-13 12:56:27.670 [main] DEBUG zht.bar.Hoge - debug
zht.bar.Hoge : info
2022-07-13 12:56:27.670 [main] INFO  zht.bar.Hoge - info
  • additivity=“false”
<logger name="zht.bar" additivity="false">
    <appender-ref ref="zht3" />
 </logger>

additivity属性,false则不会继承父logger中设置的appender 输出格式, logger 的子节点将再次继承父节点的 appender 输出格式。

5 日志文件输出

使用**ch.qos.logback.core.FileAppender** 日志文件输出类,创建日志文件保存到本地硬盘中。

logback.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="zht1" class="ch.qos.logback.core.FileAppender">
        <file>logback-zht.log</file>
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <root>
        <appender-ref ref="zht1" />
    </root>
</configuration>
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TextLog {
    public static void main(String[] args) {
        Logger z = LoggerFactory.getLogger("zht");
        z.trace("trace");
        z.debug("debug");
        z.info("info");
    }
}

项目跟目录下出现一个logback-zht.log文件。

|-src/main/
|  |-java
|  |  -cn/core/sys
|  |    |-Test.java
|  |-resources
|    |-logback.xml
|-logback-zht.log  日志文件

6 轮换日志文件

如果要轮换日志文件,请在 appender 类中指定 ch.qos.logback.core.rolling.RollingFileAppender这给工具类。

  • rollingPolicy标签中设置ch.qos.logback.core.rolling.TimeBasedRollingPolicy 日志时间创建日志类。
  • fileNamePattern 中指定日志文件名称。

日志文件的日期格式会自动推断并执行按时间进行分割日志文件

  • %d{yyyyMMdd_HHmmss} 这个格式情况下,时间格式被指定到秒,所以当以秒为单位执行分割日志文件。
  • %d{yyyy-MM-dd}如果日期发生变化,它将按天进行分割日志文件。
  • 根据自定义的时间格式来分割日志文件。
<xml version="1.0" encoding="UTF-8">
<configuration>
    <appender name="zht1" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logback-zht.log</file>
        <---------TimeBasedRollingPolicy 时间分割日志文件 ----------->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <---------{yyyyMMdd_HHmmss} 以秒为单位分割日志文件 ----------->
            <---------logback-zht-%d{yyyyMMdd}.log 以天分割日志文件 ----------->
            <fileNamePattern>logback-zht-%d{yyyyMMdd_HHmmss}.log</fileNamePattern>
        </rollingPolicy>
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <root>
        <appender-ref ref="zht1" />
    </root>
</configuration>

多次执行日志输出。

|-src/main/
|  |-java
|  |  -cn/core/sys
|  |    |-Test.java
|  |-resources
|    |-logback.xml
|-logback-zht.log  日志文件
|-logback-zht-20220711_132131.log
|-logback-zht-20220711_133531.log

自动删除文件设置

  • <maxHistory> 使用标签,设置要保留多少日志文件。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="zht1" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logback-zht.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logback-zht-%d{yyyyMMdd_HH}.log</fileNamePattern>
            <maxHistory>3</maxHistory> <!-- ★最大保存文件数 -->
        </rollingPolicy>
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <root>
        <appender-ref ref="zht1" />
    </root>
</configuration>

------------------------    时间格式    ----------------------------
%d{yyyyMMdd_HH}  按每天小时分割创建文件
<fileNamePattern>logback-sample-%d{yyyyMMdd_HH}.log</fileNamePattern>
2022-07-11  20:00                52 logback-sample-2022-07-11_20.log
2022-07-11  21:00                52 logback-sample-2022-07-1121.log
2022-07-11  22:00                37 logback-sample-2022-07-11_22.log
2022-07-11  23:58                37 logback-sample.log

格局时间格式判断删除文件 ,例如 为and %d{yyyyMMdd_HH},“超过 3 小时的文件”将被删除 maxHistory``3 。日志输出为 23:00的时候 删除了 3 小时以外的(20:00)所有文件。

日志存储每月的文件夹中,每天轮换创建新日志文件

在日期格式中%d{yyyyMM,aux}指定选项,aux 属性数值。例如 代表每月文件夹的部分。

  • auxauxiliary(auxiliary) 的缩写,这并%d中使用aux标识文件轮换的时间。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="zht1" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logback-zht.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>%d{yyyyMM,aux}/logback-zht-%d{yyyyMMdd}.log</fileNamePattern>
        </rollingPolicy>
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <root>
        <appender-ref ref="zht1" />
    </root>
</configuration>
------------------------    时间格式    ----------------------------
日志文件都保存在对应的年月文件夹下
<fileNamePattern>%d{yyyyMM,aux}/logback-zht-%d{yyyyMMdd}.log</fileNamePattern>

压缩日志

需要压缩日志,在fileNamePattern属性中更改指定文件名的扩展名,它将zip自动压缩。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="zht1" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logback-zht.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logback-zht-%d{yyyyMMdd_HHmmss}.zip</fileNamePattern>
        </rollingPolicy>
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <root>
        <appender-ref ref="zht1" />
    </root>
</configuration>

7 Spring boot 基础配置

在spring boot项目中,logback.xml配置文件需要放在 src/main/resource 中,它会自动被程序加载到。

spring boot中logback.xml配置文件名称,最好推荐名“logback-spring.xml”

如果要更改配置文件的位置,请在 application.properties 中设置以下内容

logging.config=classpath:logback/logback-spring.xml
logging:
  config: classpath:logback-spring.xml
  level:
    org.thymeleaf: info
    org:
      springframework:
        boot:
          autoconfigure:
            logging: info
  • 当解析 logback-spring.xml 时出现警告或错误时,控制台上会显示一条指示内部状态的消息。如果您希望消息显示时没有警告或错误,请将配置选项卡上的调试属性设置为 true。
  • Spring Boot 提供了 logback 的默认设置。 通过将以下包含标签添加到 logback-spring.xml 来加载默认设置。

logback-spring.xml

<configuration debug="true">
    <include resource="org/springframework/boot/logging/logback/base.xml" />
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
</configuration>

普通日志设置logback-spring.xml

<xml version="1.0" encoding="UTF-8">
<configuration debug="true">
    <include resource="org/springframework/boot/logging/logback/base.xml" />
    <appender name="zht1" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logback-zht.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>%d{yyyyMMdd,aux}/logback-zht-%d{yyyyMMdd}.log</fileNamePattern>
        </rollingPolicy>
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <appender name="zht2" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <root level="debug">
        <appender-ref ref="zht1" />
        <appender-ref ref="zht2" />
    </root>
</configuration>

自动保存与删除多余日志设置logback-spring.xml

<xml version="1.0" encoding="UTF-8">
<configuration>

    <!-- 后台打印 -->
    <appender name="zht1" class="ch.qos.logback.core.ConsoleAppender">
        <target>System.out</target>
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d{yyyy/MM/dd HH:mm:ss} %-5level [%thread] - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 日志保持到本地文件中 -->
    <appender name="zht2" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--日志名称设置 -->
        <file>/log/zht/app.log</file>
        <!--日志按规则保持压缩文件 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>/log/zht/app-%d{yyyy-MM-dd}.log.zip</fileNamePattern>
            <maxHistory>3</maxHistory>
        </rollingPolicy>
        <!--日志输出格式 -->
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d{yyyy/MM/dd HH:mm:ss} %-5level [%thread] - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 保存日志 -->
    <logger name="appLogger" level="INFO">
      <appender-ref ref="zht2" />
    </logger>

    <!-- 后台输出日志 -->
    <root level="INFO">
        <appender-ref ref="zht1" />
    </root>
</configuration>

日志使用方法

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
    /** 指定日志类名称class **/
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @GetMapping("/test")
    public void test() {
        logger.info("访问");
    }
}