前言
Log4j2的介紹可以參考上一篇博客。
Log4j2很好的一點是可以用configuration file來配置log system。但是這個配置文件的存放位置比較糾結一些。文中會介紹如何更改Log4j2配置文件的路徑和名稱。
目錄
本文的內容將回答如下問題:
1、如何產生LogEvent?
2、LogEvent的傳遞是怎樣的?
3、如何更改Log4j2配置文件的的名稱和路徑?
正文
1、如何產生LogEvent?
在調用Logger對象的info、error、trace等函數時,就會產生LogEvent。LogEvent跟LoggerConfig一樣,也是由Level的。LogEvent的Level主要是用在Event傳遞時,判斷在哪里停下。具體的可以參考上一篇日志。
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class Test { private static Logger logger = LogManager.getLogger("HelloWorld"); public static void main(String[] args){ Test.logger.info("hello,world"); Test.logger.error("There is a error here"); } }
如代碼中所示,這樣就產生了兩個LogEvent。
2、LogEvent的傳遞是怎樣的?
我們在IDE中運行一下這個程序,看看會有什么輸出。

發現,只有ERROR的語句輸出了,那么INFO的語句呢?
不着急,先來看看工程目錄結構:

可以看到,工程中沒有寫入任何的配置文件。所以,application應該是使用了默認的LoggerConfig Level。那么默認的Level是多少呢?
在log4j2的源文件中,可以看到其DefaultConfiguration類的java doc,描述如下:
/**
* The default configuration writes all output to the Console using the default logging level. You configure default logging level by setting the
* system property "org.apache.logging.log4j.level" to a level name. If you do not specify the property, Log4J uses the ERROR Level. Log
* Events will be printed using the basic formatting provided by each Message.
可見,默認的輸出地是console,默認的級別是ERROR級別。
那么,為什么默認ERROR級別會導致INFO級別的信息被攔截呢?
看如下表格:

左邊豎欄是Event的Level,右邊橫欄是LoggerConfig的Level。Yes的意思就是這個event可以通過filter,no的意思就是不能通過filter。
可以看到,INFO級別的Event是無法被ERROR級別的LoggerConfig的filter接受的。所以,INFO信息不會被輸出。
3、如何改變Log4j2的名稱和路徑?
如果想要改變默認的配置,那么就需要configuration file。Log4j的配置是寫在log4j.properties文件里面,但是Log4j2就可以寫在XML和JSON文件里了。
(1)放在classpath(src)下,以log4j2.xml命名
使用Log4j2的一般都約定俗成的寫一個log4j2.xml放在src目錄下使用。這一點沒有爭議。
(2)將配置文件放到別處
在系統工程里面,將log4j2的配置文件放到src目錄底下很不方便。如果能把工程中用到的所有配置文件都放在一個文件夾里面,當然就更整齊更好管理了。但是想要實現這一點,前提就是Log4j2的配置文件能重新定位到別處去,而不是放在classpath底下。
那么,有這個可能嗎?
看看文檔里怎么說吧:
1.Log4j will inspect the "log4j.configurationFile" system property and, if set,will attempt to load the configuration using the ConfigurationFactory that matches the file extension.
2.If no system property is set the JSON ConfigurationFactory will look for log4j2-test.json or log4j2-test.jsn in the classpath.
3.If no such file is found the XML ConfigurationFactory will look for log4j2-test.xml in the classpath.
4.If a test file cannot be located the JSON ConfigurationFactory will look for log4j2.json or log4j2.jsn on the classpath.
5.If a JSON file cannot be located the XML ConfigurationFactory will try to locate log4j2.xml on the classpath.
6.If no configuration file could be located the DefaultConfiguration will be used. This will cause logging output to go to the console.
可見,如果沒有設置"log4j.configurationFile" system property的話,application將在classpath中按照如下查找順序來找配置文件:
log4j2-test.json 或log4j2-test.jsn文件
log4j2-test.xml文件
log4j2.json 或log4j2.jsn文件
log4j2.xml文件
這就是為什么在src目錄底下放log4j2.xml文件可以被識別的原因了。
如果想將配置文件重命名並放到別處,就需要設置系統屬性log4j.configurationFile。
設置的方式是在VM arguments中寫入該屬性的key和value:
-Dlog4j.configurationFile="D:\learning\blog\20130115\config\LogConfig.xml"
在myeclipse中,就是 右鍵-》run as -》run configuration-》右邊窗口的“(x)=argument”=》VM arguments
然后寫入上述key和value即可。
-D是參數,不能缺少。
測試
在“D:\learning\blog\20130115\config\”路徑下編寫文件:

root LoggerConfig的Level設為INFO。
在myeclipse中寫入log4j.configurationFile系統屬性:

測試的java程序如上文,在此不再重復。運行,console輸出如下:

期待已久的INFO語句出現了。
總結:
這次測試最糾結的地方是在配置文件的重定位上。先google了一番,在overflowstack上看到有人有一樣的問題,CSDN上也是,不過都沒人說怎么解決。翻看手冊,是看到了log4j.configurationFile這個設置系統屬性的地方。試了一下(當時沒寫參數-D),沒有成功,以為這個方法不對。就在Log4j2的網站上下載了源代碼,一點點查找改路徑的地方。找到最后,還是從log4j.configurationFile這個系統屬性上入手。無奈,又回到原點。最后竟然是沒寫參數-D。哎,蒼天吶……
