1. 程式人生 > >java 日誌框架簡單實用用法

java 日誌框架簡單實用用法

在我們學java的時候,我們最先使用的是 system.out.println 記錄程式的執行過程,後來我們接觸了日誌框架,它擁有更專業的日誌記錄能力,但是在我們還沒有充分認識這些日誌框架之前,也只是寫一些log.info之類的語句,沒有發現它比system.out.println好在哪裡,後來接觸了真實的專案,學習別人的 日誌配置, 瞭解到slf4j是java大部分日誌框架的門面,具體用 log4j,logback都自己隨意(多型),但是api還是用slf4j的,因為這樣統一的介面方法容易維護,至於 slf4j和log4j是怎麼關聯上的 不需要你去過多操心。

這裡不講需要用哪些jar包,直接從slf4j的xml配置檔案開始講起。

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds">
    <!-- 控制檯 appender -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>
               [%-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n
            </pattern
>
<charset>UTF-8</charset> <!-- 此處設定字符集 --> </encoder> </appender> <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"
>
<!-- 按天回滾 daily --> <!--<fileNamePattern>E:\CentOS\qymp-%d{yyyy-MM-dd}.log--> <fileNamePattern>e:/logs\oak0825-%d{yyyy-MM-dd}.log </fileNamePattern> <!-- 日誌最大的歷史 60天 --> <maxHistory>180</maxHistory> </rollingPolicy> <encoder> <pattern> [%-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n </pattern> <charset>UTF-8</charset> </encoder> </appender> <appender name="accessLog" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 按天回滾 daily --> <!--<fileNamePattern>E:\CentOS\qymp-%d{yyyy-MM-dd}.log--> <fileNamePattern>e:/logs\oak0825-access-%d{yyyy-MM-dd}.log </fileNamePattern> <!-- 日誌最大的歷史 60天 --> <maxHistory>180</maxHistory> </rollingPolicy> <encoder> <pattern> [%-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n </pattern> <charset>UTF-8</charset> </encoder> </appender> <appender name="mail" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 按天回滾 daily --> <!--<fileNamePattern>E:\CentOS\qymp-%d{yyyy-MM-dd}.log--> <fileNamePattern>e:/logs\oak0825-mail-%d{yyyy-MM-dd}.log </fileNamePattern> <!-- 日誌最大的歷史 60天 --> <maxHistory>180</maxHistory> </rollingPolicy> <encoder> <pattern> [%-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n </pattern> <charset>UTF-8</charset> </encoder> </appender> <!-- mailLog --> <logger name="mailLogLogger" additivity="false" level="INFO"> <appender-ref ref="mail" /> <appender-ref ref="STDOUT" /> </logger> <!-- accessLog --> <logger name="gloablAccessLogLogger" additivity="false" level="INFO"> <appender-ref ref="accessLog" /> <appender-ref ref="STDOUT" /> </logger> <!--root 也是 logger --> <root level="INFO"> <appender-ref ref="STDOUT" /> <appender-ref ref="file" /> </root> </configuration>

我們分步驟講解:

appender 可以定義不同的日誌收集方式,在這裡只輸出到控制檯,當然另一個比較常用的就是寫到日誌檔案中,後面會講到。在這裡這個appender name為STDOUT,根據class可知該收集方式為控制檯輸出,並且子標籤pattern和charset定義了日誌輸出的格式和編碼。

<!-- 控制檯 appender -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>
               [%-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n
            </pattern>
            <charset>UTF-8</charset>
            <!-- 此處設定字符集 -->
        </encoder>
    </appender>

我們再看另一個 appender,class用了RollingFileAppender,說明該收集方式是按日期寫入日誌檔案, 它每一天會生成一個日誌檔案,按天回滾,同時也定義了一些日誌存放位置,日誌儲存最大天數,日誌格式等資訊。

<appender name="file"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 按天回滾 daily -->
            <!--<fileNamePattern>E:\CentOS\qymp-%d{yyyy-MM-dd}.log-->
            <fileNamePattern>e:/logs\oak0825-%d{yyyy-MM-dd}.log
            </fileNamePattern>
            <!-- 日誌最大的歷史 60天 -->
            <maxHistory>180</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>
                [%-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n
            </pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

我們再看一下 root標籤,他本質是一個logger ,如果說appender決定了怎麼記錄日誌,那麼logger 則決定了日誌在哪裡記錄,logger在一個系統可以有多個,並且可以是繼承關係,後面會具體說明,我們先看一個logger的情形,這個root裡面應用了 name為STDOUT和file的appender,說明當我們執行log.info()時,它不僅會輸出到控制檯,而且會記錄成檔案到本地硬碟中,是不是開始感覺到了日誌框架的強大? 注意。root 有個level引數,決定了最低的日誌記錄等級,如果我們用log.debug()時,因為我們這裡設定的是Info,比debug等級更高,所以debug打出來的日誌是不會記錄下來的。

    <root level="INFO">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="file" />
    </root>

剛剛我們說了logger可以有多個,那麼什麼時候我們會用到多個logger呢? 比如說我們有個專案,裡面有兩個功能,一個是 郵件傳送功能,一個是其它普通的功能,普通功能的日誌可以直接用root 記錄,但是 郵件傳送功能的日誌我希望抽取出來,單獨寫到一個日誌檔案中,怎麼辦?這時候我們可以建立另一個logger,專門用來記錄郵件的傳送程序。

我們先定義一個appender,name為mail, 裡面的內容大致與name 為 file的appender相同,但是存放路徑我們肯定要另外指定。

<appender name="mail"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 按天回滾 daily -->
            <!--<fileNamePattern>E:\CentOS\qymp-%d{yyyy-MM-dd}.log-->
            <fileNamePattern>e:/logs\oak0825-mail-%d{yyyy-MM-dd}.log
            </fileNamePattern>
            <!-- 日誌最大的歷史 60天 -->
            <maxHistory>180</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>
                [%-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n
            </pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

我在再寫一個name為mailLogLogger的logger,記錄等級為info,裡面兩個appender,說明它也會列印到控制檯,不同的是檔案記錄不再是用file,而是mail,從而達到郵件功能單獨抽取出來的目的。

我們會看到一個additivity屬性,這是幹嘛的?我們前面說了root 也是一個logger,它是所有logger的基類,具體說,預設情況下子Logger會繼承父Logger的appender,也就是說子Logger會在父Logger的appender裡輸出。若是additivity設為false,則子Logger只會在自己的appender裡輸出,而不會在父Logger的appender裡輸出。

    <!-- mailLog -->
    <logger name="mailLogLogger" additivity="false" level="INFO">
        <appender-ref ref="mail" />
        <appender-ref ref="STDOUT" />
    </logger>

最後我們在java程式碼中怎麼用不同的logger呢?這裡用的是slf4j的語法,在getLogger中指定自己需要用的Logger的name即可。

private Logger log = LoggerFactory.getLogger("mailLogLogger");

這裡簡單且實用的介紹一下java日誌框架的用法,主要自己之前也對slf4j的xml配置檔案比較迷糊,這裡做一個整理。