原文地址:http://www.work100.net/training/monolithic-frameworks-log4j.html
更多教程:光束雲 - 免費課程
Log4j
序號 | 文內章節 | 視頻 |
---|---|---|
1 | 概述 | - |
2 | 日誌級別 | - |
3 | 日誌輸出 | - |
4 | SLF4J | - |
5 | 實例 | - |
6 | 實例源碼 | - |
請參照如上章節導航
進行閱讀
1.概述
一個完整的軟件,日誌是必不可少的。
程序從開發、測試、維護、運行等環節,都需要向控制檯或文件等位置輸出大量信息。
這些信息的輸出, 在很多時候是使用 System.out.println()
無法完成的。
日誌信息根據用途與記錄內容的不同,分爲:調試日誌
、運行日誌
、異常日誌
等。
Log4j
的全稱爲 Log for java
,即專門用於 Java 語言的日誌記錄工具。
2.日誌級別
爲了方便對於日誌信息的輸出顯示,對日誌內容進行了分級管理。日誌級別由高到低,共分 6 個級別:
- fatal(致命的)
- error
- warn
- info
- debug
- trace(堆棧)
爲什麼要對日誌進行分級?
無論是將日誌輸出到控制檯,還是文件,其輸出都會降低程序的運行效率。但由於調試、運行維護的需要,客戶的要求等原因,需要進行必要的日誌輸出。這時就必須要在代碼中加入日誌輸出語句。
這些輸出語句若在程序運行時全部執行, 則勢必會降低運行效率。例如, 使用 System.out.println()
將信息輸出到控制檯,則所有的該輸出語句均將執行。會大大降低程序的執行效率。而要使其不輸出,唯一的辦法就是將這些輸出語句逐個全部刪除。這是個費時費力的過程。
將日誌信息進行分級管理,便可方便的控制信息輸出內容及輸出位置:哪些信息需要輸出,哪些信息不需要輸出,只需在一個日誌輸出控制文件中稍加修改即可。而代碼中的輸出語句不用做任何修改。
從這個角度來說,代碼中的日誌編寫,其實就是寫大量的輸出語句。只不過,這些輸出語句比較特殊,它們具有級別,在程序運行期間不一定被執行。它們的執行是由另一個控制文件控制。
3.日誌輸出
3.1.日誌輸出簡介
Log4j 的日誌輸出控制文件,主要由三個部分構成:
- 日誌信息的輸出位置:控制日誌信息將要輸出的位置,是控制檯還是文件等。
- 日誌信息的輸出格式:控制日誌信息的顯示格式,即以怎樣的字符串形式顯示。
- 日誌信息的輸出級別:控制日誌信息的顯示內容,即顯示哪些級別的日誌信息。
有了日誌輸出控制文件,代碼中只要設置好日誌信息內容及其級別即可,通過控制文件便可控制這些日誌信息的輸出了。
3.2.日誌屬性配置文件
日誌屬性文件 log4j.properties
是專門用於控制日誌輸出的。其主要進行三方面控制:
- 輸出位置:控制日誌將要輸出的位置,是控制檯還是文件等。
- 輸出佈局:控制日誌信息的顯示形式。
- 輸出級別:控制要輸出的日誌級別。
日誌屬性文件由兩個對象組成:日誌附加器
與 根日誌
。
根日誌,即爲 Java 代碼中的日誌記錄器,其主要由兩個屬性構成:日誌輸出級別與日誌附加器。
日誌附加器,則由日誌輸出位置定義,由其它很多屬性進行修飾,如輸出佈局、文件位置、文件大小等。
3.3.什麼是日誌附加器?
所謂日誌附加器,就是爲日誌記錄器附加上很多其它設置信息。附加器的本質是一個接口,其定義語法爲:log4j.appender.appenderName = 輸出位置
常用的附加器實現類
附加器實現類 | 說明 |
---|---|
org.apache.log4j.ConsoleAppender |
日誌輸出到控制檯 |
org.apache.log4j.FileAppender |
日誌輸出到文件 |
org.apache.log4j.RollingFileAppender |
當日志文件大小到達指定尺寸的時候將產生一個新的日誌文件 |
org.apache.log4j.DailyRollingFileAppender |
每天產生一個日誌文件 |
3.4.常用佈局類型
佈局類型 | 說明 |
---|---|
org.apache.log4j.HTMLLayout |
網頁佈局,以 HTML 表格形式佈局 |
org.apache.log4j.SimpleLayout |
簡單佈局,包含日誌信息的級別和信息字符串 |
org.apache.log4j.PatternLayout |
匹配器佈局,可以靈活地指定佈局模式。其主要是通過設置 PatternLayout 的 ConversionPattern 屬性值來控制具體輸出格式的 。 |
打印參數: Log4J 採用類似 C 語言中的 printf 函數的打印格式格式化日誌信息
格式化編碼 | 說明 |
---|---|
%m |
輸出代碼中指定的消息 |
%p |
輸出優先級,即:DEBUG ,INFO ,WARN ,ERROR ,FATAL |
%r |
輸出自應用啓動到輸出該 log 信息耗費的毫秒數 |
%c |
輸出所屬的類目,通常就是所在類的全名 |
%t |
輸出產生該日誌事件的線程名 |
%n |
輸出一個回車換行符,Windows 平臺爲 /r/n ,Unix 平臺爲 /n |
%d |
輸出日誌時間點的日期或時間,默認格式爲 ISO8601 。<br>也可以在其後指定格式,比如:%d{yyy MMM dd HH:mm:ss , SSS} 。<br>輸出類似:2002年10月18日 22:10:28,921 |
%l |
輸出日誌事件的發生位置,包括類目名、發生的線程,以及在代碼中的行數。<br>舉例:Testlog4.main(TestLog4.java: 10) |
4.SLF4J
slf4j 的全稱是 Simple Loging Facade For Java
,即它僅僅是一個爲 Java 程序提供日誌輸出的統一接口,並不是一個具體的日誌實現方案,就比如 JDBC 一樣,只是一種規則而已。
所以單獨的 slf4j
是不能工作的,必須搭配其他具體的日誌實現方案,比如 apache 的 org.apache.log4j.Logger
,JDK 自帶的 java.util.logging.Logger
以及 log4j
等。
5.實例
仍然以 hello-spring
項目進行代碼演示。
5.1.更新POM
修改 pom.xml
文件,增加 org.slf4j:slf4j-log4j12
依賴,代碼如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.work100.training.stage2</groupId>
<artifactId>hello-spring</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
</project>
5.2.創建 log4j.properties 配置文件
在 src/main/resources
目錄下創建名爲 log4j.properties
的屬性配置文件,代碼如下:
log4j.rootLogger=INFO, console, file
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.File=logs/log.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.A3.MaxFileSize=1024KB
log4j.appender.A3.MaxBackupIndex=10
log4j.appender.file.layout.ConversionPattern=%d %p [%c] - %m%n
日誌配置相關說明:
配置節 | 說明 |
---|---|
log4j.rootLogger |
根日誌,配置了日誌級別爲 INFO ,預定義了名稱爲 console 、file 兩種附加器 |
log4j.appender.console |
console 附加器,日誌輸出位置在控制檯 |
log4j.appender.console.layout |
console 附加器,採用匹配器佈局模式 |
log4j.appender.console.layout.ConversionPattern |
console 附加器,日誌輸出格式爲:日期 日誌級別 [類名] - 消息 換行符 |
log4j.appender.file |
file 附加器,每天產生一個日誌文件 |
log4j.appender.file.File |
file 附加器,日誌文件輸出位置 logs/log.log |
log4j.appender.file.layout |
file 附加器,採用匹配器佈局模式 |
log4j.appender.A3.MaxFileSize |
日誌文件最大值 |
log4j.appender.A3.MaxBackupIndex |
最多紀錄文件數 |
log4j.appender.file.layout.ConversionPattern |
file 附加器,日誌輸出格式爲:日期 日誌級別 [類名] - 消息 換行符 |
5.3.測試日誌輸出
創建一個測試類 Log4jTest.java
,並測試日誌輸出效果,代碼如下:
package net.work100.training.stage2.hello.spring;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* <p>Title: Log4jTest</p>
* <p>Description: </p>
*
* @author liuxiaojun
* @date 2020-02-12 17:01
* ------------------- History -------------------
* <date> <author> <desc>
* 2020-02-12 liuxiaojun 初始創建
* -----------------------------------------------
*/
public class Log4jTest {
public static final Logger logger = LoggerFactory.getLogger(Log4jTest.class);
public static void main(String[] args) {
logger.info("slf4j for info");
logger.debug("slf4j for debug");
logger.error("slf4j for error");
logger.warn("slf4j for warn");
String message = "Hello SLF4J";
logger.info("slf4j message is : {}", message);
}
}
運行程序,此時控制檯顯示爲:
2020-02-12 17:03:43,734 INFO [net.work100.training.stage2.hello.spring.Log4jTest] - slf4j for info
2020-02-12 17:03:43,734 ERROR [net.work100.training.stage2.hello.spring.Log4jTest] - slf4j for error
2020-02-12 17:03:43,734 WARN [net.work100.training.stage2.hello.spring.Log4jTest] - slf4j for warn
2020-02-12 17:03:43,736 INFO [net.work100.training.stage2.hello.spring.Log4jTest] - slf4j message is : Hello SLF4J
項目根目錄下也會多出 logs/log.log
目錄及文件
5.4.佔位符說明
打日誌的時候使用了 {}
佔位符,這樣就不會有字符串拼接操作,減少了無用 String 對象的數量,節省了內存。
並且,記住,在生產最終日誌信息的字符串之前,這個方法會檢查一個特定的日誌級別是不是打開了,這不僅降低了內存消耗而且預先降低了 CPU 去處理字符串連接命令的時間。
6.實例源碼
實例源碼已經託管到如下地址:
- <https://github.com/work100-net/training-stage2/tree/master/hello-spring>
- <https://gitee.com/work100-net/training-stage2/tree/master/hello-spring>
上一篇:JUnit
下一篇:綜合實例
如果對課程內容感興趣,可以掃碼關注我們的
公衆號
或QQ羣
,及時關注我們的課程更新