1.參考文獻:
- Apache Commons-logging使用實例
- Apache Log4j配置說明
- log4j.properties配置詳解
- commons-logging結合Log4j的問題
- Properties文件相關
- Apache通用日志工具commons-logging和Log4j使用總結
2.Commons-Loggin簡介
Apache針對不同的語言平台為做了一系列日志工具包,可應用於java、.net、php、c++,這些日志包都是免費的,使用非常方便,可以極大提高編程效率。並且,Apache為了讓眾多的日志工具有一個相同操作方式,還實現做了一個通用日志工具包:commons-logging,也稱Jakarta Commons Logging (JCL)。commons-logging是為那些需要建立在不同環境下使用不同日志架構的組件或庫的開發者創建的,其中包括Apache Log4j以及Java log的日志架構。把日志信息commons-logging的Log接口,並由commons-logging在運行時決定使用哪種日志架構。現在,Apache通用日志工具commons-logging和Log4j已經成為Java日志的標准工具。
3.快速入門
JCL有兩個基本的抽象類:Log(基本記錄器)和LogFactory(負責創建Log實例)。當commons-logging.jar被加入到CLASSPATH(通常將commons-logging.jar放在web project下的WebContent\WEB-INF\lib目錄中)之后,它會合理地猜測你想用的日志工具,然后進行自我設置,用戶根本不需要做任何設置。默認的LogFactory是按照下列的步驟去發現並決定那個日志工具將被使用的(按照順序,尋找過程會在找到第一個工具時中止,這個順序非常重要):
- 尋找當前factory中名叫org.apache.commons.logging.Log配置屬性的值
- 尋找系統中屬性中名叫org.apache.commons.logging.Log的值
- 如果應用程序的classpath中有log4j,則使用相關的包裝(wrapper)類(Log4JLogger)
- 如果應用程序運行在jdk1.4的系統中,使用相關的包裝類(Jdk14Logger)
- 使用簡易日志包裝類(SimpleLog)
package log.sample;
public class ca {
static {
// Is Log4J Available?用戶Log4J是否可用
try {
/**
* 通過Class.forName("org.apache.log4j.Logger"))來查找Log4J,
* 只有將log4j.jar添加到classpath以后才能找到,
* 這也是為什么默認情況下只要將log4j.jar文件放在lib文件夾中
* 而不需要在common-logging.properties配置文件中進行配置就能自動使用log4j的原因
*/
if (null != Class.forName("org.apache.log4j.Logger")) {
log4jIsAvailable = true;
} else {
log4jIsAvailable = false;
}
} catch (Throwable t) {
log4jIsAvailable = false;
}
// Is JDK 1.4 Logging Available?原來同上面的Log4J
try {
if ((null != Class.forName("java.util.logging.Logger")) &&
(null != Class.forName("org.apache.commons.logging.impl.Jdk14Logger"))) {
jdk14IsAvailable = true;
} else {
jdk14IsAvailable = false;
}
} catch (Throwable t) {
jdk14IsAvailable = false;
}
// Set the default Log implementation,通過common-logging.properties配置文件來決定日志實現方式
String name = null;
try {
name = System.getProperty("org.apache.commons.logging.log");
if (name == null) {
name = System.getProperty("org.apache.commons.logging.Log");
}
} catch (Throwable t) {
}
if (name != null) {
try {
setLogImplementation(name);
} catch (Throwable t) {
try {
setLogImplementation
("org.apache.commons.logging.impl.NoOpLog");
} catch (Throwable u) {
;
}
}
} else {
try {
if (log4jIsAvailable) {//如果log4j可用,默認優先使用Log4JLogger
setLogImplementation
("org.apache.commons.logging.impl.Log4JLogger");
} else if (jdk14IsAvailable) {//第二優先使用Jdk14Logger
setLogImplementation
("org.apache.commons.logging.impl.Jdk14Logger");
} else {//最后使用commoms-logging中的自帶的實現,但它不進行任何操作
setLogImplementation
("org.apache.commons.logging.impl.NoOpLog");
}
} catch (Throwable t) {
try {
setLogImplementation
("org.apache.commons.logging.impl.NoOpLog");
} catch (Throwable u) {
;
}
}
}
}
}
- -org.apache.commons.logging.impl.Jdk14Logger:使用JDK1.4。
- -org.apache.commons.logging.impl.Log4JLogger:使用Log4J。
- -org.apache.commons.logging.impl.Log4JCategoryLog:使用Log4J,該實現已被棄用,推薦使用Log4JLogger
- -org.apache.commons.logging.impl.LogKitLogger:使用 avalon-Logkit。
- -org.apache.commons.logging.impl.SimpleLog:common-logging自帶日志實現類。它實現了Log接口,把日志消息都輸出到系統錯誤流System.err 中。
- -org.apache.commons.logging.impl.NoOpLog:common-logging自帶日志實現類。它實現了Log接口。 其輸出日志的方法中不進行任何操作。
4.信息級別
確保日志信息在內容上和反應問題的嚴重程度上的恰當,是非常重要的。log4j主要有如下的信息級別:
- fatal:非常嚴重的錯誤,導致系統中止。期望這類信息能立即顯示在狀態控制台上。
- error:其它運行期錯誤或不是預期的條件。期望這類信息能立即顯示在狀態控制台上。
- warn:使用了不贊成使用的API、非常拙劣使用API, '幾乎就是'錯誤, 其它運行時不合需要和不合預期的狀態但還沒必要稱為 "錯誤"。期望這類信息能立即顯示在狀態控制台上。
- info:運行時產生的有意義的事件。期望這類信息能立即顯示在狀態控制台上。
- debug:系統流程中的細節信息。期望這類信息僅被寫入log文件中。
- trace:更加細節的信息。期望這類信息僅被寫入log文件中。
通常情況下,我們希望將info級別以上的日志信息輸出到控制台,而debug級別以上的信息寫入到log文件中,而error信息寫入到一個單獨的文件中去,下面我們的實例將會實現這樣的功能。
4.使用commons-logging結合log4j進行開發
4.1. 下載必要的jar包
下載commons-logging.jar和log4j.jar包,然后把它們放到工程的lib目錄下,引入工程中。
4.2. 編寫common-logging.properties配置文件
在屬性文件common-logging.properties中設置實現接口的類。如下(這里設置Log4j為所使用的日志包):
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
這里需要注意的是,如果common-logging.properties配置使用Log4JCategoryLog,會報錯誤,具體見參考文獻4。配置如下:
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JCategoryLog
在第三節中我們講到如何在項目中引入了log4j.jar,那么common-logging默認會使用log4j最為日志實現方式。
4.3.log4j.properties配置實現日志的不同輸出形式
前面我們講到要求在控制台輸入info級別的日志,然后有一個log.log記錄debug級別以上的日志,一個error.log記錄error級別以上的日志。log4j.properties配置如下:
### set log levels ###
log4j.rootLogger = debug , stdout , D , E
### 輸出到控制台 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
## 輸出INFO級別以上的日志
log4j.appender.stdout.Threshold = INFO
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %d{ABSOLUTE} %5p %c{1}:%L - %m%n
### 輸出到日志文件 ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = D:/logs/log.log
log4j.appender.D.Append = true
## 輸出DEBUG級別以上的日志
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 保存異常信息到單獨文件 ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
## 異常日志文件名
log4j.appender.E.File = D:/logs/error.log
log4j.appender.E.Append = true
## 只輸出ERROR級別以上的日志!!!
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
4.4.單獨使用log4j實例:Log4jTest.java
package log.sample;
import org.apache.log4j.Logger;
public class Log4jTest {
private static Logger log = Logger.getLogger(Log4jTest.class);
public void log() {
log.debug("Debug info.");
log.info("Info info");
log.warn("Warn info");
log.error("Error info");
log.fatal("Fatal info");
}
public static void main(String[] args) {
Log4jTest test = new Log4jTest();
test.log();
}
}
4.5.common-logging結合log4j實例:JCLTest.java
package log.sample;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class JCLTest {
private static Log log = LogFactory.getLog(JCLTest.class);
public void log(){
log.debug("Debug info.");
log.info("Info info");
log.warn("Warn info");
log.error("Error info");
log.fatal("Fatal info");
}
public static void main(String[] args) {
JCLTest test = new JCLTest();
test.log();
}
}
說明:4.4和4.5的輸出結果是一樣的。