1、觸發事件
今天正好在學習log4j,為了測試其配置文件log4j.properties中的各種配置,進行了頻繁修改和程序啟動以確認效果,因為是使用的IDEA建立的Web項目,接着問題就來了,配置文件修改后,重新運行Tomcat發現根本沒有生效,剛開始懷疑是文件中配置的寫法不對而且google了很久,反反復復發現配置沒有問題但是就是不行。
幸好知道IDEA中對於artifacts的定義,相當於部署包,Tomcat運行時實際是去讀取的這個東西里的文件,其編譯方式之前在另篇博客《
理解 IntelliJ IDEA 的項目配置和Web部署》中也有提到,一會兒在下面再單獨提一下。所以接下來,我又找到artifacts的文件夾目錄,到里面去找
log4j.properties看看,發現配置內容還是我更改之前的,怪不得運行沒有效果,因為真正讀取的配置文件根本就沒有改變。
可是IDEA編譯的時候不是會把目錄內容復制到artifacts目錄下嗎?為什么不是最新的配置文件?目前猜想可能跟IDEA版本有關,這個留在下面在講。
大概的觸發事件就是這樣,不過最終還是得到了解決,大概寫一下,說不定能幫助到別人。
2、IDEA的編譯方式
這里提IDEA的編譯方式,是為了最后更好地描述和理解。
IDEA的編譯方式和Eclipse不同,它並不是自動編譯,而是每次在容器運行之前進行先編譯,再運行。我們可以看到Tomcat中的容器配置:

IDEA中編譯方式有如下三種,如上圖所示,這里我們每次容器運行之前,都進行了Make方式的代碼編譯:
- Compile:對選定的目標(Java 類文件),進行強制性編譯,不管目標是否是被修改過。
- Rebuild:對選定的目標(Project),進行強制性編譯,不管目標是否是被修改過,由於 Rebuild 的目標只有 Project,所以 Rebuild 每次花的時間會比較長。
- Make:使用最多的編譯操作。對選定的目標(Project 或 Module)進行編譯,但只編譯有修改過的文件,沒有修改過的文件不會編譯,這樣平時開發大型項目才不會浪費時間在編譯過程中。
另外,注意看第二個黃色標記的地方 “Build '你的artifact名稱' artifact”,這里就要提到容器運行時,IDEA都做了什么(更多詳情參考
《
理解 IntelliJ IDEA 的項目配置和Web部署
》
):
- 在運行server前會做一次編譯。編譯后class文件存放在指定的項目編譯輸出目錄下;
- 根據artifact中的設定對目錄結構進行創建;
- 拷貝web資源的根目錄下的所有文件到artifact的目錄下;
- 拷貝編譯輸出目錄下的classes目錄到artifact下的WEB-INF下;
- 拷貝lib目錄下所需的jar包到artifact下的WEB_INF下;
- 運行server,運行成功后,如有需要,會自動打開瀏覽器訪問指定url。
3、大概是IDEA10的特例
了解了IDEA的編譯方式,可以知道,那么就算是配置文件,只要其所在文件夾設置為了資源目錄,那么在容器運行的時候,實際上也是會將里面的內容復制到最后的artifact中去的,可是我自己在嘗試的時候IDEA卻沒有按常理出牌。
我找了下相關的問題,有的網友貼了圖,我才發現,高版本的IDEA中對於配置文件的目錄,有單獨的資源標志。如下有網友回答情況:

標記為Resources的目錄會被復制到artifact中。
可是我看了下我的IDEA10的配置結構,並沒有這個東西:

就算配置文件的目錄標志為唯一能用的Sources了,IDEA還是不給我復制。所以我理解,Sources可能只會復制過去能編譯的文件,最終復制過去的即是 .class 文件,而諸如 .properties 的配置文件是不會復制的。
怎么辦,難道要手動復制?幸好,網友的力量是強大的,按照如下步驟執行:
1、把所需要的配置文件的文件夾,以依賴的方式導入項目:

2、在artifact配置中,將這兩個文件夾添加進去

3、添加完成后會發現,左側output_root中就有了這兩個文件夾目錄,之后容器在運行的時候,就會將這文件夾中的內容復制到artifact中去,也就是達到了我們的目的

此時再運行,每次的配置文件修改,都可以看到效果變更了。
什么,你問我為什么項目一開始運行的時候沒有發現這個問題?因為這個項目老大第一次給我的時候,配置文件直接就已經在artifact中有一份了,並不知道是他之前手動放進去的,還是怎么回事。
而且,其實更另我困惑的是,其他的配置文件諸如strust.xml,之前我也並沒有按照如上所述解決方案去進行處理,可是修改后是可以生效的,我也就搞不懂到底是IDEA哪里出了問題,之前可以現在不行,攤手。所以就有這個 “大概是IDEA10的特例” 的子標題。
很傷,反正不開心。