1. 程式人生 > 程式設計 >Java 配置log4j日誌檔案路徑 (附-獲取當前類路徑的多種操作)

Java 配置log4j日誌檔案路徑 (附-獲取當前類路徑的多種操作)

1 日誌路徑帶來的痛點

Java 專案中少不了要和log4j等日誌框架打交道,開發環境和生產環境下日誌檔案的輸出路徑總是不一致,設定為絕對路徑的方式缺少了靈活性,每次變更專案路徑都要修改檔案,目前想到的最佳實現方式是: 根據專案位置自動載入並配置檔案路徑.

本文借鑑 Tomcat 的配置方式 “${catalina.home}/logs/catalina.out”,通過相對路徑的方式設定日誌的輸出路徑,有其他解決方案的小夥伴,請直接評論區交流哦😯

2 log4j.properties檔案的配置

# 設定要輸出的日誌的級別 - 注意: properties檔案中的註釋資訊只能處於行首,不要跟在行尾
log4j.rootLogger=INFO,stdout,logfile

### 輸出到控制檯,Java程式執行時的標準輸出資訊
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
# 2019-05-25 19:09:46
log4j.appender.stdout.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%t] [%c] [%p] - %m%n

### 輸出到日誌檔案
# 按天滾動生成,不支援MaxFileSize,而RollingFileAppender支援
log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
# 專案的logs目錄下
# log4j.appender.logfile.File=${base.dir}/logs/elastic-server.log
log4j.appender.logfile.Append=true
# 輸出INFO及以上的日誌,按日期滾動就無須配置單個日誌檔案的最大體積了
log4j.appender.logfile.Threshold=INFO
# log4j.appender.logfile.MaxFileSize=100MB
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%t] [%c] [%p] - %m%n

3 徹底解決痛點

3.1 單獨的Java程式包 (非Java Web專案)

單獨的Java程式包,需要通過命令java -jar或java -cp的方式啟動;

我們可以在啟動命令中加入系統執行時變數,在log4j載入配置檔案之前通過System.getProperties("path")讀取此變數,即可實現靈活載入當前路徑.

(1) 啟動指令碼設定:

假設當前專案的目錄結構為:

/Projects/KafkaConsumer
丨 bin 專案的啟動指令碼
丨 conf 專案的配置檔案
丨 lib 專案的其他依賴包
丨 bogs 專案的日誌輸出路徑

啟動指令碼位於bin目錄下,內容示例如下:

# 獲取當前指令碼所處的目錄,然後進入其上級目錄,最後pwd輸出該目錄,最終的結果是/Project/KafkaConsumer
base_dir=$(cd `dirname $0`; cd ..; pwd)
# 獲取Java執行程式的位置,並指定主類
java_bin=$(which java)
main_class="org.shoufeng.elastic.ConsumerMain"

# 通過-cp、擴充套件CLASSPATH、指定主類的方式啟動專案,# 並通過“-D”的方式向此程式的執行時環境中設定當前專案的路徑,# 即可在程式中通過System.getProperty("base.dir")獲取此路徑 

nohup ${java_bin} -Dbase.dir=${base_dir} -cp ${CLASSPATH}:${base_dir}/conf:${base_dir}/lib/* ${main_class} >> /dev/null &

(2) Java程式讀取變數:

實log4j的FileAppender本身支援動態設定檔案路徑,如:

log4j.appender.logfile.File=${base.log}/logs/app.log

其中“${base.log}”是一個變數,會被System Property中的base.log的值代替,程式碼中的使用方式為:

public static void main(String[] args) {
 // 獲取系統執行時變數中的日誌檔案的輸出路徑
 // 此變數需要在啟動命令中通過-D的方式設定
 String baseDir = System.getProperty("base.dir");
 if (baseDir == null) {
  // 開發環境中使用
  baseDir = System.getProperty("user.dir");
  System.setProperty("base.dir",baseDir);
 }
 log.info("==== 系統執行路徑: " + System.getProperty("base.dir") + " ====");
 // 其他處理邏輯......
}

需要注意的是,這種方式設定的環境變數只在當前Java程序(也就是當前專案)中有效,並不會影響到其他專案.

3.2 Web專案

如果是Web專案,可通過修改Web容器的環境變數方式實現. 以 Tomcat 為例:

# log4j的配置檔案支援伺服器的vm環境變數,格式類似${catalina.home} 
log4j.appender.R=org.apache.log4j.RollingFileAppender 
log4j.appender.R.File=${catalina.home}/logs/logs_tomcat.log 
log4j.appender.R.MaxFileSize=100MB 

${catalina.home}是在${tomcat_home}/bin/catalina.sh中通過-D引數設定的:

-Dcatalina.home="$CATALINA_HOME"

基於這個思路,我們也可以向Web容器的VM引數中設定一個引數,比如-Dmylog.home="/Project/logs",建立日誌物件時即可使用.

4 附錄 - 獲取當前專案、類路徑的幾種方式

public static void main(String[] args) {
 // 獲取 class 檔案的絕對路徑,定位到具體的包名,結果如: 
 // /Projects/KafkaConsumer/target/classes/org/shoufeng/consumer/
 System.out.println(KafkaConsumer.class.getResource(""));

 // 獲取 class 檔案的絕對路徑,如: /Projects/KafkaConsumer/target/classes/,// 如果在bin目錄下通過java -jar等命令啟動時,結果就是 /Projects/KafkaConsumer/bin/
 System.out.println(ClassLoader.getSystemResource(""));
 System.out.println(KafkaConsumer.class.getResource("/"));
 System.out.println(KafkaConsumer.class.getClassLoader().getResource(""));
 System.out.println(Thread.currentThread().getContextClassLoader().getResource(""));
 // 說明: 上述4種用法的返回結果型別都是URL,其toString()返回的內容以"file:"開頭,可通過“.toString().substring(5)”去除
 // 推薦: 使用“.getPath()”就可以直接獲取到路徑

 // 獲取工程的絕對路徑,如: /Projects/KafkaConsumer,// 若在bin中通過java -jar等命令啟動,路徑就變成了: /Projects/KafkaConsumer/bin
 System.out.println(System.getProperty("user.dir"));
}

補充知識:在web中使用log4j時,配置日誌檔案的存放位置

廢話不多說,直接上程式碼。

log4j.properties配置如下

log4j.rootLogger = info,out1,out2
log4j.appender.out1=org.apache.log4j.FileAppender
log4j.appender.out1.File=test.log

log4j.appender.out1.layout=org.apache.log4j.PatternLayout
log4j.appender.out1.layout.ConversionPattern=%d %-5p - %m at %l%n

log4j.appender.out2=org.apache.log4j.ConsoleAppender
log4j.appender.out2.layout=org.apache.log4j.PatternLayout
log4j.appender.out2.layout.ConversionPattern=%d %-5p - %m at %l%n

問題一:這個test.log檔案會存放在哪呢?

經測試發現,test.log這個相對路徑相對的是user.dir系統引數的值。

假如我的tomcat的安裝路徑為D:\apache-tomcat-6.0.16,則user.dir=D:\apache-tomcat-6.0.16\bin,當不確定時,我們可以用System.getProperties()將所有的系統引數在jsp中打印出來。

問題二:

如果我們將test.log改為絕對路徑/test.log,這個test.log檔案又會存放在哪呢?

經測試發現,/test.log這個絕對路徑的根路徑是user.dir系統引數的根路徑,即test.log會存放在D:\test.log。

補充:

我們在log4j.properties檔案中還可以通過${系統引數}的方式來指明日誌檔案存放路徑。

log4j.appender.out1.File=${user.dir}/logs/test.log

以上這篇Java 配置log4j日誌檔案路徑 (附-獲取當前類路徑的多種操作)就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。