java框架之SpringBoot(3)-日志

市面上的日志框架

日志抽象层 日志实现
JCL(Jakarta Commons Logging)、SLF4J(Simple Logging Facade For Java)、JBoss-Logging Log4jJUL(java.util.logging)Log4j2、Logback

日志抽象层

JBoss-Logging 不适合日常开发使用。JCL 最后一次更新版本时间为 2014 年,有些过期。因此 SpringBoot 选中的日志抽象层为 SLF4J。html

日志实现

日志实现 LogBack、Log4j 和抽象层 SLF4J 的做者是同一我的,且 LogBack 是后期针对 Log4j 的升级版,而 Log4j2 是 Apache 旗下开发的日志框架。因此 SpringBoot 的日志实现使用的是 Logback。java

SLF4J使用

编码

导入 slf4j 和 logback 的依赖,使用以下。web

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

public class HelloWorld {
  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger(HelloWorld.class);
    logger.info("Hello World");
  }
}

原理图

统一使用SLF4J

如何让系统中全部的日志都统一到 sfl4j?spring

  1. 将系统中其它日志框架排除。
  2. 用中间包替换原有的日志框架。
  3. 导入 sl4j 的其它实现。

SpringBoot日志关系

咱们已经知道一个基本的 SpringBoot  web 项目会包含以下依赖:apache

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

而在 spring-boot-starter-web 依赖又依赖于 spring-boot-stater , spring-boot-stater 就有日志相关依赖,以下:api

总结:springboot

  1. SpringBoot 底层也是使用 slf4j+logback 的方式进行日志记录。
  2. SpringBoot 使用中间包将其它的日志包都间接替换成了 slf4j,而 slf4j 的实现为 logback,因此 call 其它日志包 api 的时候实际上调用的是 logback,统一了日志实现。
  3. 若是咱们要引入其它框架,必定要把这个框架的默认日志依赖排除。

SpringBoot日志使用

默认配置

日志级别

现有以下示例:app

package com.springboot.logging;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class LoggingApplicationTests {

    @Test
    public void test() {
        Logger logger = LoggerFactory.getLogger(this.getClass());
     // 以下日志级别由低到高
     // 指定一个日志级别,就会在指定的级别以后的高级别生效
        logger.trace("trace info");
        logger.debug("debug info");
        logger.info("info info");
        logger.warn("warn info");
        logger.error("error info");
    }
}

运行该测试代码,输出以下:框架

2018-03-16 17:08:34.913  INFO 16228 --- [           main] c.s.logging.LoggingApplicationTests      : info info
2018-03-16 17:08:34.913  WARN 16228 --- [           main] c.s.logging.LoggingApplicationTests      : warn info
2018-03-16 17:08:34.913 ERROR 16228 --- [           main] c.s.logging.LoggingApplicationTests      : error info

得出结论,SpringBoot 程序中咱们使用的日志输出默认是 info 级别。spring-boot

咱们能够经过配置文件修改指定包下的日志输出级别,例:

logging.level.com.springboot.logging=trace  # 指定 com.springboot.logging 包下的日志输出级别为 trace

此时运行上面测试程序,输出内容为:

2018-03-16 17:13:06.451 TRACE 2836 --- [           main] c.s.logging.LoggingApplicationTests      : trace info
2018-03-16 17:13:06.451 DEBUG 2836 --- [           main] c.s.logging.LoggingApplicationTests      : debug info
2018-03-16 17:13:06.452  INFO 2836 --- [           main] c.s.logging.LoggingApplicationTests      : info info
2018-03-16 17:13:06.452  WARN 2836 --- [           main] c.s.logging.LoggingApplicationTests      : warn info
2018-03-16 17:13:06.452 ERROR 2836 --- [           main] c.s.logging.LoggingApplicationTests      : error info

若是直接指定整个项目日志输出级别,那么只须要把包路径位置替换为 root ,以下:

logging.level.root=trace

输出到文件

日志不只可输出到控制台,还能够配置输出到指定文件,以下:

logging.file=springboot.log

此时项目中的日志就会输出到项目根路径下的 springboot.log 文件中。

上面这种方式是使用相对项目路径,也可使用完整的绝对路径,以下:

logging.file=D://springboot.log

也能够只指定日志存放目录:

logging.path=/springboot/log

此时就会在项目所在磁盘的根目录的 /springboot/log 文件夹下生成一个 spring.log 文件。

输出格式

咱们能够改变日志的输出格式,好比在配置文件中修改在控制台的日志输出格式:

logging.path=/log  
# 控制台日志输出格式
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} ---> %msg%n
# 文件中日志输出格式
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} ---> %msg%n

# %d : 日期时间
# %thread : 线程名
# %-5level : 级别,从左显示 5 个字符宽度
# %logger{50} : logger 名称最长为 50 个字符,不然按照句点分割
# %msg : 日志消息
# %n : 换行符

此时运行上面测试程序,输出结果以下:

2019-03-16 17:41:23.432 [main] INFO  com.springboot.logging.LoggingApplicationTests ---> Started LoggingApplicationTests in 2.355 seconds (JVM running for 3.052)
2019-03-16 17:41:23.486 [main] INFO  com.springboot.logging.LoggingApplicationTests ---> info info
2019-03-16 17:41:23.486 [main] WARN  com.springboot.logging.LoggingApplicationTests ---> warn info
2019-03-16 17:41:23.486 [main] ERROR com.springboot.logging.LoggingApplicationTests ---> error info

指定配置文件

要使用自定义的日志配置文件,只须要在类路径下放上对应日志框架本身的配置文件便可,SpringBoot 就不使用它的默认配置了。而对应日志框架的配置文件命名也是有限制的,以下:

日志框架 可以使用配置文件名
Logback logback-spring.xml、logback-spring.groovy、logback.xml、logback.groovy
log4j2 log4j2-spring.xml、log4j2.xml
JDK(Java Util Logging) logging.properties

 咱们此时使用的是 SpringBoot 默认使用的 logback,因此能够在类路径下放入“logback.xml”:

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
    <property name="LOG_HOME" value="log"/>
    <!--定义日志文件名称-->
    <property name="FILE_NAME" value="testLog"/>
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--
            格式化输出:
                %d 表示日期
                %thread 表示线程名
                %-5level 级别从左显示 5 个字符宽度
                %msg 日志消息
                %n 是换行符
            -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>
    <!-- 按照天天生成日志文件 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${LOG_HOME}/${FILE_NAME}.%d{yyyy-MM-dd}.log</FileNamePattern>
            <!--日志文件保留天数-->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <!--格式化输出:%d 表示日期,%thread 表示线程名,%-5level 表示级别从左显示 5 个字符宽度 %msg 表示日志消息,%n 是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <!--日志文件最大的大小-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>
    <!-- 日志输出级别 -->
    <root level="INFO">
        <appender-ref ref="STDOUT"/> <!--启用控制台输出-->
        <appender-ref ref="FILE"/> <!--启用文件输出-->
    </root>
</configuration>

此时“logback.xml”就能够直接被日志框架读取配置。

高级功能

在 SpringBoot 项目中,SpringBoot 是推荐咱们使用文件名为“logback-spring.xml”的配置文件,由于使用“logback-spring.xml”文件名时该配置文件就不是直接被日志框架读取,而是先被 SpringBoot 读取,此时 SpringBoot 就给咱们提供了日志框架之外的功能,能够定制不一样 Profile 环境下来生效日志的不一样配置,使用以下:

<root level="INFO">
    <!--仅在非 prod 环境下启用控制台输出-->
    <springProfile name="!prod">
        <appender-ref ref="STDOUT"/> <!--启用控制台输出-->
    </springProfile>
    <!--仅在 prod 环境下启用文件输出-->
    <springProfile name="prod">
        <appender-ref ref="FILE"/> <!--启用文件输出-->
    </springProfile>
</root>

切换日志框架

切换到log4j

SpringBoot 默认使用 logback 做为日志实现,而咱们若是想要切换到其它日志实现该怎么作呢?下面以切换到 log4j 为例:

咱们能够先分析 SpringBoot 的日志关系 和 SLF4J 的日志适配图

由于默认使用的是 logback 实现,因此如今 SpringBoot 有导入 jcl-over-slf4j.jar 、 log4j-over-slf4j.jar 、 jul-to-slf4j.jar 这三个日志替换包,而咱们要切换成 log4j 实现,首先咱们要排除 log4j 的日志替换包即 log4j-over-slf4j.jar 和 logback 的实现包:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
<exclusions>
    <exclusion>
        <artifactId>log4j-over-slf4j</artifactId>
        <groupId>org.slf4j</groupId>
    </exclusion>
    <exclusion>
        <artifactId>logback-classic</artifactId>
        <groupId>ch.qos.logback</groupId>
    </exclusion>
</exclusions>
</dependency>

接着看下图:

能够看到要将 log4j 切换为 slf4j 的实现须要两个替换包,这两个替换包 SpringBoot 默认已经使用了,因此还须要添加一个适配包:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
</dependency>

此时能够添加 log4j 的配置文件“log4j.properties”:

log4j.rootLogger = info,stdout

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 = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

运行项目,会发现日志实现已经切换到 log4j。

log4j2场景启动器

上面演示的是如何切换 SpringBoot 的日志实现为 log4j,看起来有些麻烦,下面再看一个示例,将 SpringBoot 的日志实现切换为 log4j2。

切换为 log4j2 就很简单了,由于 SpringBoot 给咱们提供了 log4j2 的场景启动器,经过以前的分析咱们已经知道 SpringBoot 默认日志场景启动器为 spring-boot-starter-logging ,下面咱们直接排除这个场景启动器的依赖,添加 log4j2 的场景启动器:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <artifactId>spring-boot-starter-logging</artifactId>
                <groupId>org.springframework.boot</groupId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

此时 SpringBoot 项目的日志实现就已经切换为 log4j2 了,同 logback,要使用 Profile 功能时,需修改 log4j2 的配置文件名为 log4j2-spring.xml 。

相关文章
相关标签/搜索