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 -jarjava -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"));
}

參考資料

log4j 產生的日志位置設置 和 catalina.home、catalina.base

版權聲明

作者: 瘦風(https://healchow.com)

出處: 博客園 瘦風的博客(https://www.cnblogs.com/shoufeng)

感謝閱讀, 如果文章有幫助或啟發到你, 點個[好文要頂👆] 或 [推薦👍] 吧😜

本文版權歸博主所有, 歡迎轉載, 但 [必須在文章頁面明顯位置標明原文鏈接], 否則博主保留追究相關人員法律責任的權利.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM