1. 程式人生 > >【SpringBoot探索二】SpringBoot專案整合日誌記錄功能

【SpringBoot探索二】SpringBoot專案整合日誌記錄功能

在之前專案的基礎上新增日誌

1.讓專案具有輸出日誌功能

在pom檔案中加入依賴

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

這樣也包含了日誌功能,在程式碼中就可以使用日誌輸出類了

 package com.my.webapp.service.impl;

import com.my.webapp.service.LoginService;
import
org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; /** */ @Service public class LoginServiceImpl implements LoginService { private final Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName()); @Override public String login
() { logger.debug("使用slf4j進行日誌記錄!"); return "welcome to spring boot world!"; } }

當然這樣我們還沒法執行程式看到效果,還需要先編寫日誌配置檔案logback.xml

2.配置日誌

編寫logback.xml
在resource目錄下新增logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/2002/xmlspec/dtd/2.10/xmlspec.dtd">
<configuration> <!--web應用名稱--> <contextName>webapp</contextName> <!--自定義變數名, 通過${name}來使用--> <property name="test" value="testValue"/> <!--獲取時間戳字串,key為名稱,datePattern為格式化時間戳為指定格式字串--> <timestamp key="time" datePattern="yyyyMMdd'T'HHmmss"/> <!--自定義輸出源--> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- encoder 預設配置為PatternLayoutEncoder --> <encoder> <!--輸出格式 %n 換行 %-5level 從左往右佔5個字元,輸出列印級別 %d 輸出日期,格式為HH:mm:ss %logger 輸出該日誌的類或包 %msg 日誌記錄 --> <pattern>%n[%-5level]-%d{HH:mm:ss}-%logger-%thread-%msg</pattern> </encoder> </appender> <!--根logger--> <root level="DEBUG"> <appender-ref ref="STDOUT"/> </root> </configuration>

新增好後,執行專案,則會自動載入該日誌配置檔案
當運行了

logger.debug("使用slf4j進行日誌記錄!");

控制檯則能看到如下效果

[DEBUG]-10:53:31-LoginServiceImpl-http-nio-8080-exec-1-使用slf4j進行日誌記錄!

3.自定義轉義型別資料

在上面我們除了用自帶的格式,如%n,%msg等等,如果我們還想要設定其它型別資料,比如每條日誌上輸出請求url,那麼則需要自定義PatternLayoutEncoder
編寫一個繼承自PatternLayoutEncoderBase的類,覆蓋start()方法,主要往InstanceConverterMap裡新增自定義轉義型別以及值

package com.my.webapp.logback;

import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.pattern.PatternLayoutEncoderBase;
import com.my.webapp.logback.converter.HttpRequestConverter;

import java.util.HashMap;
import java.util.Map;

/**
 */
public class PatternLayoutEncoder extends PatternLayoutEncoderBase<ILoggingEvent> {
    @Override
    public void start() {
        PatternLayout patternLayout = new PatternLayout();
        patternLayout.getInstanceConverterMap().putAll(setPatternType());
        patternLayout.setContext(context);
        patternLayout.setPattern(getPattern());
        patternLayout.setOutputPatternAsHeader(outputPatternAsHeader);
        patternLayout.start();
        this.layout = patternLayout;
        super.start();
        super.start();
    }

    /**
     * 自定義轉義型別
     * @return
     */
    private Map<String, String> setPatternType() {

        Map<String, String> map = new HashMap<String, String>();
        map.put("request", HttpRequestConverter.class.getName());

        return map;
    }
}

這裡需要注意Map的value為自定義Converter的類名

編寫對應型別的Converter
需要繼承ClassicConverter並覆蓋converter()方法

HttpRequestConverter.java

package com.my.webapp.logback.converter;

import ch.qos.logback.classic.pattern.ClassicConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 */
public class HttpRequestConverter extends ClassicConverter{
    @Override
    public String convert(ILoggingEvent iLoggingEvent) {

        ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        if(requestAttributes == null){
            return "";
        }

        HttpServletRequest request = requestAttributes.getRequest();
        if(request == null){
            return "";
        }
        return request.getRequestURI();
    }
}

converter()方法輸出的值即為輸出日誌時,%request對應的值

修改encoder屬性,class修改為我們剛自定義的類。
這樣我們就可以在輸出格式中新增%request這種型別了

  <encoder charset="UTF-8" class="com.my.webapp.logback.PatternLayoutEncoder">
        <pattern>%n[%-5level]--%d{HH:mm:ss}--%logger--%thread--%method--[%request]--%msg</pattern>
        </encoder>

日誌執行效果如下:

[DEBUG]–15:09:42–LoginServiceImpl–http-nio-8080-exec-1–login–[/user/loginWithService/31]–[debug]使用slf4j進行日誌記錄!

4.自定義logger

剛剛的配置將所有類的輸出格式都是一致的,如果需要配置特定類或包下的類,比如設定不同列印級別,就需要自定義logger

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/2002/xmlspec/dtd/2.10/xmlspec.dtd">

<configuration>
    <!--web應用名稱-->
    <contextName>webapp</contextName>
    <!--自定義變數名, 通過${name}來使用-->
    <property name="test" value="testValue"/>
    <!--獲取時間戳字串,key為名稱,datePattern為格式化時間戳為指定格式字串-->
    <timestamp key="time" datePattern="yyyyMMdd'T'HHmmss"/>


    <!--自定義輸出源-->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- encoder 預設配置為PatternLayoutEncoder -->
        <encoder charset="UTF-8">
            <!--輸出格式
            %n 換行
            %-5level 從左往右佔5個字元,輸出列印級別
            %d 輸出日期,格式為HH:mm:ss
            %logger  輸出該日誌的類或包
            %msg 日誌記錄
            -->
            <pattern>%n[%-5level]-%d{HH:mm:ss}-%logger-%thread-%msg</pattern>
        </encoder>
    </appender>
    <!--logger用於設定某個包或某個類的日誌列印級別,以及設定appender
        name: 指定的包或類
        level: 列印級別 TRACE, DEBUG, INFO, WARN, ERROR, ALL, OFF,不區分大小寫,還有特殊值INHERITED或者同義詞NULL,代表強制執行上級的級別。
                如果未設定此屬性,那麼當前loger將會繼承上級的級別。
        additivity: 是否向上級loger傳遞列印資訊。預設是true。
    -->
    <!--<logger name="com.my.webapp" level="DEBUG" addtivity="false">-->
    <!--使用自定義的日誌輸出配置,比如輸出到檔案或者是控制檯-->
    <!--ref 引用的appender 對應appender的name值-->
    <!--<appender-ref ref="STDOUT"/>-->
    <!--</logger>-->

    <!--這裡指定springframework包下所有的類,日誌輸出級別為INFO,additivity預設為true。則將日誌資訊遞交給上級logger(root)處理,
        要處理的日誌資訊為INFO及之後的級別
    -->
    <logger name="org.springframework" level="INFO"/>
    <!--http包下的日誌輸出到控制檯,並且不會傳遞給上級處理-->
    <logger name="org.apache.http" level="INFO" additivity="false">
        <appender-ref ref="STDOUT"/>
    </logger>
    <!--根logger-->
    <root level="DEBUG">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

5.設定將日誌輸出到檔案

新增一個新的appender,其負責將日誌記錄在檔案中

<!--輸出到檔案中-->
    <appender name="LogFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--設定日誌滾動策略,比如切換檔案記錄日誌,或重新命名等
        clss: 滾動策略 TimeBasedRollingPolicy為最常見滾動策略,根據時間來制定
        -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日誌檔案輸出的檔名-->
            <FileNamePattern>${filePath}/webapp-%d{yyyy-MM-dd}.log</FileNamePattern>
            <!--日誌保留的最大個數,超過了則刪除最舊的檔案-->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder charset="UTF-8">
            <pattern>%n[%-5level]-%d{HH:mm:ss}-%logger-%thread-[%method]-%msg</pattern>
        </encoder>

        <!--日誌檔案最大的大小-->
        <!--class 日誌通知觸發策略 SizeBasedTriggeringPolicy,超過設定大小則發出通知-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <!--單個日誌檔案大小限制,超過則記錄在新的日誌檔案中-->
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>

將想要輸出日誌到檔案中的looger修改appender-ref引用為剛設定的appender(如”LogFile”)

 <root level="DEBUG">
        <!--輸出到控制檯-->
        <!--<appender-ref ref="STDOUT"/>-->
        <!--輸出到指定檔案-->
        <appender-ref ref="LogFile"/>
    </root>

這樣日誌都會記錄到檔案中了,路徑為我設定的
E:\java\logfile\目錄下

最終logback.xml檔案內容:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/2002/xmlspec/dtd/2.10/xmlspec.dtd">

<configuration>
    <!--web應用名稱-->
    <contextName>webapp</contextName>
    <!--自定義變數名, 通過${name}來使用-->
    <property name="test" value="testValue"/>
    <!--獲取時間戳字串,key為名稱,datePattern為格式化時間戳為指定格式字串-->
    <timestamp key="time" datePattern="yyyyMMdd'T'HHmmss"/>

    <!--定義一個日誌存放目錄屬性,方便修改-->
    <property name="filePath" value="E:/java/logfile"/>

    <!--自定義輸出源-->

    <!--輸出到控制檯-->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- encoder
            class 預設配置為PatternLayoutEncoder -->
        <encoder charset="UTF-8" class="com.my.webapp.logback.PatternLayoutEncoder">
            <!--輸出格式
            %n 換行
            %-5level 從左往右佔5個字元,輸出列印級別
            %d 輸出日期,格式為HH:mm:ss
            %logger  輸出該日誌的類或包
            %msg 日誌記錄
            %method 列印該日誌的方法
            如果需要列印其它型別資料則需要自定義PatternLayoutEncoder方法(比如%request)
            -->
            <pattern>%n[%-5level]--%d{HH:mm:ss}--%logger--%thread--%method--[%request]--%msg</pattern>
        </encoder>
    </appender>

    <!--輸出到檔案中-->
    <appender name="LogFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--設定日誌滾動策略,比如切換檔案記錄日誌,或重新命名等
        clss: 滾動策略 TimeBasedRollingPolicy為最常見滾動策略,根據時間來制定
        -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日誌檔案輸出的檔名-->
            <FileNamePattern>${filePath}/webapp-%d{yyyy-MM-dd}.log</FileNamePattern>
            <!--日誌保留的最大個數,超過了則刪除最舊的檔案-->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder charset="UTF-8">
            <pattern>%n[%-5level]-%d{HH:mm:ss}-%logger-%thread-[%method]-%msg</pattern>
        </encoder>

        <!--日誌檔案最大的大小-->
        <!--class 日誌通知觸發策略 SizeBasedTriggeringPolicy,超過設定大小則發出通知-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <!--單個日誌檔案大小限制,超過則記錄在新的日誌檔案中-->
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>

    <!--logger用於設定某個包或某個類的日誌列印級別,以及設定appender
        name: 指定的包或類
        level: 列印級別 TRACE, DEBUG, INFO, WARN, ERROR, ALL, OFF,不區分大小寫,還有特殊值INHERITED或者同義詞NULL,代表強制執行上級的級別。
                如果未設定此屬性,那麼當前loger將會繼承上級的級別。
        additivity: 是否向上級loger傳遞列印資訊。預設是true。
    -->
    <!--http包下的日誌輸出到控制檯,不會傳遞給上級處理-->
    <logger name="org.apache.http" level="INFO" additivity="false">
        <appender-ref ref="STDOUT"/>
    </logger>
    <!--這裡指定springframework包下所有的類,日誌輸出級別為INFO,additivity預設為true。則將日誌資訊遞交給上級logger(root)處理,
        要處理的日誌資訊為INFO及之後的級別
    -->
    <logger name="org.springframework" level="INFO"/>

    <!--根logger-->
    <root level="DEBUG">
        <!--輸出到控制檯-->
        <!--<appender-ref ref="STDOUT"/>-->
        <!--輸出到指定檔案-->
        <appender-ref ref="LogFile"/>
    </root>
</configuration>

以上即為logback常用配置
部落格參考案例已上傳: