1. 程式人生 > >log4j.properties讀取webapp.root值失敗,導致的setFile(null,..)的解決方案

log4j.properties讀取webapp.root值失敗,導致的setFile(null,..)的解決方案

    這個問題折磨了我整整一天,特此寫出來幫助後來的小夥伴們少走彎路.

    我先描述環境,你來看看是否和你的情況相似.

    專案中使用了spring與log4j,使用org.springframework.web.util.Log4jConfigListener監聽,log4j.properties中配置了${webapp.root}來獲取web.xml中配置的webAppRootKey.大致相關程式碼如下:

web.xml:

<context-param> 
 	<param-name>webAppRootKey</param-name>
 	<param-value>SzWeb.root</param-value>
</context-param> 
<context-param> 
 	<param-name>log4jConfigLocation</param-name> 
 	<param-value>/WEB-INF/classes/log4j.properties</param-value>
</context-param>  
<context-param> 
 	<param-name>log4jRefreshInterval</param-name> 
 	<param-value>60000</param-value>
</context-param> 
<listener>
 	<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>	  

log4j.properties:

log4j.appender.logfile_error.File=${webapp.root}/WEB-INF/logs/SystemError.log
網上流傳導致setFile(null,..)的原因是
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j.properties</param-value>
需要設定成classpath:log4j.properties

而在我的專案中,我發現的原因是:

listener的執行順序導致的...

web.xml內的執行順序是這樣的 context-param-->listener-->filter-->servlet,而listener的執行順序是按你書寫順序的...

我的專案中存在AB兩個listener,Alistener在前,其中做了一些系統業務引數的初始化,Blistener就是Log4jConfigListener,本來是沒什麼問題的,但是A中偏偏有對日誌的操作,所以在Blistener還沒有生效前就要求log4j開始做日誌處理,所以log4j同學就去找自己的配置檔案,然後發現裡面有一個${webapp.root},然後它就去system的property裡面找,發現沒有然後就報錯...為什麼沒有呢?因為Blistener實際上去讀取了servlet.realpath,然後把你設定的webAppRootKey和realpath關聯起來,儲存到system的property裡面...結果B還沒來得及幹,A就去找了...

至此找到了原因...(之前google...度娘都問了...根本沒有人和我一樣,最終還是看了看Log4jConfigListener這玩意到底幹了啥,然後才想起來可能是執行順序導致的)

好了,完結撒花