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 。

相關文章
相關標籤/搜索