Struts與Apache通用日誌包
在應用程序中輸出日誌有三個目的:
l 監視代碼中變量的變化情況,把數據週期性地記錄到文件中供其他應用進行統計分析工作
l 跟蹤代碼運行時軌跡,作爲日後審計的依據
l 擔當集成開發環境中的調試器,向文件或控制檯打印代碼的調試信息
1.1 Apache通用日誌包概述
Apache通用日誌包(Commons Logging Package)是Apache的一個開放源代碼項目,它提供了一組通用的日誌接口,用戶可以自由地選擇實現日誌接口的第三方軟件,通用日誌包目前支持以下日誌實現:
l Log4J日誌器(http://jakarta.apache.org/log4j)
l JDK1.4 Logging日誌器(在JDK1.4中自帶了該日誌器)
l SimpleLog日誌器(把日誌消息輸出到標準的系統錯誤流System.err)
l NoOpLog日誌器(不輸出任何日誌消息)
通用日誌包中的兩個常用接口爲LogFactory和Log。
1.1.1 Log接口
通用日誌包把日誌消息分爲6種級別:FATAL、ERROR、WARN、INFO、DEBUG和TRACE,由高到低。org.apache.commons.logging.Log接口代表日誌器,分別提供瞭如上的一組輸出日誌的方法,只有當它輸出日誌的級別大於或等於爲日誌器配置的日誌級別,這個方法纔會被真正執行。如,日誌器的級別爲WARN,那麼在程序中,它的fatal()、error()、warn()方法纔會被執行,而info()、debug()、trace()不會被執行。
Log接口還提供了isXXXEnabled()來判斷是否允許輸出特定級別的日誌消息的方法。在程序中輸出某種級別的日誌消息之前,提倡先調用這些方法來判斷(log.isDebugEnabled...)該級別的日誌是否允許輸出。
1.1.2 LogFactory接口
org.apache.commons.logging.LogFactory接口提供了獲得日誌器實例的兩個靜態方法:
public static Log getLog(String name) throws LogConfigurationException public static Log getLog(Class class) throws LogConfigurationException |
第一個方法以name作爲日誌器名字,第二個方法以class參數指定的類的名字作爲日誌器的名字。(getLog(class.getName()); )
1.2 常用的日誌實現
1.2.1 NoOpLog日誌器
在通用日誌包中自帶了org.apache.commons.logging.impl.NoOpLog日誌實現類,它實現了Log接口,但是它的輸出日誌方法不執行任何操作。
1.2.2 SimpleLog日誌器
在通用日誌包中自帶了org.apache.commons.logging.impl.SimpleLog日誌實現類,它實現了Log接口,它把日誌消息輸出到標準的系統錯誤流System.err,在SimpleLog初始化的過程中,從名爲“simplelog.properties”的屬性文件中讀取以下屬性:
l org.apache.commons.logging.simplelog.defaultlog:爲SimpleLog的所有實例設置默認的日誌級別,可選值包括:fatal、error、warn、info、debug和trace,如果沒有設置這個屬性,默認爲info
l org.apache.commons.logging.simplelog.showShortLogname:如果爲true,表示在輸出的日誌消息中應包括當前日誌器實例的間寫名字,默認爲true
l org.apache.commons.logging.simplelog.showdatetime:如果爲true,表示在輸出的日誌消息中應包括當前時間信息,默認爲false
SimpleLog將根據以上屬性來控制日誌輸出級別和輸出格式,在它的輸出日誌方法中,先判斷是否允許輸出該級別的日誌,當判斷結果爲true時,才輸出日誌。
public final void debug(Object message) { if ( isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG) ) { //判斷是否允許輸出該級別日誌 log(SimpleLog.LOG_LEVEL_DEBUG, message, null); } }
protected boolean isLevelEnabled( int logLevel) { return (logLevel >= currentLogLevel ); //currentLogLevel代表當前日誌器的日誌級別 } |
1.2.3 Log4J日誌器
Log4J是一個日誌操作包,它允許靈活地指定日誌消息輸出的目的地(如控制檯、文件、GUI組件,甚至是套接口服務器、NT的事件記錄器和UNIX Syslog守護進程),還可以控制每一條日誌的輸出格式。
Log4J主要由三大組件構成:
l Logger:負責生成日誌,並能根據配置的日誌級別來決定什麼日誌消息應該被輸出,什麼日誌消息應該被忽略
l Appender:定義日誌消息輸出的目的地,指定日誌消息應該被輸出到什麼地方
l Layout:指定日誌消息的輸出格式
1.3 配置通用日誌接口
在Web應用中使用通用日誌包,需要進行以下配置
l 準備有關的JAR文件
l 在commons-logging.properties屬性文件中指定日誌器(即日誌實現類)
l 爲特定的日誌器設置日誌級別、輸出格式和輸出地點等屬性
1.3.1 準備JAR文件
通用日誌包的單獨下載爲:http://jakarta.apache.org/commons/logging,在Struts1.1的下載軟件中也包含了通用日誌包,爲commons-logging.jar,應該把此jar文件複製到WEB-INF/lib目錄下,它只包含了NoOpLog和SimpleLog兩個類,Log4J還需要單獨下載,並放到WEB-INF/lib下,在Tomcat5.0.24中,<CATALINA_HOME>/bin下已經包含了commons-logging-api.jar,tomcat啓動時,會加載這個文件中的類,這要不需要再拷貝commons-logging.jar到lib下。
1.3.2 指定日誌器
通用日誌接口從“commons-logging.properties”的屬性文件中獲取實現日誌接口的日誌器信息,位於WEB-INF/classes目錄下
該文件中的“org.apache.commons.logging.Log”指定日誌實現類:
org.apache.commons.logging.Log= org.apache.commons.logging.impl.SimpleLog 或 org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JCategoryLog |
1.3.3 配置日誌器屬性
舉例配置SimpleLog,此日誌器輸出地點固定爲System.err,但是可以在simplelog.properties屬性文件中設置其日誌級別:
org.apache.commons.logging.simplelog.defaultlog=info
此simplelog.properties文件放在WEB-INF/classes目錄下
1.4 配置Log4J
Log4J支持兩種配置文件格式:XML文件和Jave屬性文件(採用“鍵=指”格式)
1.4.1 配置Log4J的一般步驟
1. 配置Logger組件:
Logger組件支持繼承關係,所有的Logger組件都直接或間接繼承rootLogger,語法爲:
log4j.rootLogger=[priority],appenderName, appenderName,...
其中,priority是日誌級別,可選OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE和ALL;appenderName指定Appender組件,用戶可以同時指定多個Appender組件
2. 配置Appender組件:
配置日誌消息輸出目的地Appender,語法爲:
log4j.appender.appenderName=fully.qualified.name.of.appender.class log4j.appender.appenderName.option1=value1 ... log4j.appender.appenderName.optionN=valueN |
Log4J提供的Appender有以下幾種:
l org.apache.log4j.ConsoleAppender(控制檯)
l org.apache.log4j.FileAppender(文件)
l org.apache.log4j.DailyRollingFileAppender(每天產生一個日誌文件)
l org.apache.log4j.RollingFileAppender(文件大小到達指定大小時產生一個新的文件)
l org.apache.log4j.WriterAppender(將日誌消息以流格式發送到任意指定的地方)
如以下代碼定義了一個名爲”file”的Appender,它把日誌消息輸出到log.txt文件:
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=log.txt
3. 配置Layout組件:
語法爲:
log4j.appender.appenderName.layout=fully.qualified.name.of.layout.class log4j.appender.appenderName.layout.option1=option1 ... log4j.appender.appenderName.layout.optionN=optionN |
Log4J提供的Layout有以下幾種:
l org.apache.log4j.HTMLLayout(以HTML表格形式佈局)
l org.apache.log4j.PatternLayout(可以靈活地指定佈局模式)
l org.apache.log4j.SimpleLayout(包含日誌消息的級別和信息字符串)
l org.apache.log4j.TTCCLayout(包含日誌產生的時間、線程和類別等信息)
PatternLayout可以讓開發者依照ConversionPattern去定義輸出格式。
PatternLayout的格式
符號 |
描述 |
%r |
自程序開始後消耗的毫秒數 |
%t |
表示日誌記錄請求生成的線程 |
%p |
表示日誌級別 |
%r? |
與日誌請求相關的類別名稱 |
%c |
日誌消息所在的類名 |
%m%n |
表示日誌消息的內容 |
1.4.2 Log4J的配置樣例
要求程序中的日誌消息既能輸出到程序運行的控制檯上,又能輸出到指定的文件中,並且當輸出到控制檯上使用SimpleLayout佈局,輸出到文件中使用PatternLayout佈局
##LOGGERS## #define a logger named helloAppLogger log4j.rootLogger=INFO,console,file
##APPENDERS## #define an appender named console, which is set to be a ConsoleAppender log4j.appender.console=org.apache.log4j.ConsoleAppender
#define an appender named file, which is set to be a RollingFileAppender log4j.appender.file=org.apache.log4j.RollingFileAppender log4j.appender.file.File=log.txt
##LAYOUTS## #assign a SimpleLayout to console appender log4j.appender.console.layout=org.apache.log4j.SimpleLayout
#assign a PatternLayout to file appender log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%t %p- %m%n |
1.4.3 Log4J對應用性能的影響
以下幾個因素:
l 日誌輸出目的地:如果把日誌輸出到控制檯的速度和輸出到文件系統的速度不同
l 日誌輸出格式:採用SimpleLayout比PatternLayout簡單,因此速度更快
l 日誌級別:級別越低,輸出的內容越多,對性能的影響越大
1.5 在Struts應用中訪問通用日誌接口
通用日誌接口的優點在於它允許靈活地指定日誌實現,當日志實現發生改變時,例如由SimpleLog改爲Log4J,對Struts應用程序代碼沒有任何影響
1.5.1 在Action類中訪問通用日誌接口
1. 通過import語句引入logging API:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
2. 調用LogFactory類的靜態方法getLog(),獲得Log類的一個實例
Log log = LogFactory.getLog(“helloapp”);
3. 調用Log類的輸出日誌方法:
log.trace()、log.debug()、log.info()、log.warn()、log.error()、log.fatal()
1.5.2 在JSP中訪問通用日誌接口
在JSP中訪問通用日誌接口有兩種方式:編程方式和採用Log標籤庫方式。
l 以編程方式訪問通用日誌接口
l 使用Log標籤庫
Apache提供一個客戶化Log標籤庫,通過它可以在JSP文件中方便地訪問通用日誌接口,無需編寫程序代碼。使用Log標籤庫的前提條件是通用日誌接口必須採用Log4J作爲日誌實現,步驟如下:
1. 下載Log標籤庫,jakarta-taglibs-log-current.zip文件,解壓後,把其中的tld文件複製到WEB-INF下,jar文件複製到WEB-INF/lib下
2. 在web.xml聲明中對Log標籤庫的引用
<taglib> <taglib-uri>/WEB-INF/taglibs-log.tld</taglib-uri> <taglib-location>/WEB-INF/taglibs-log.tld</taglib-location> </taglib> |
3. 在JSP文件中訪問Log標籤庫:
<%@ taglib uri=”/WEB-INF/taglibs-log.tld” prefix=”log” %> <log:debug message=”This is a debug message using the log tag” /> <log:info message=”This is an info message using the log tag” /> <log:warn message=”This is a warn message using the log tag” /> |
Log標籤庫還包含一個<log:dump>標籤,它能夠輸出特定範圍內所有對象的信息,它的scope屬性指定對象的範圍。
1.6 小結
通用日誌接口的屬性文件爲commons-logging.properties,SimpleLog的屬性文件爲simplelog.properties,Log4J的屬性文件爲log4j.properties,這三個文件均位於/WEB-INF/classes目錄下
在Java程序中,先通過LogFactory獲得Log實例,然後再調用Log實例的各種輸出日誌方法
在JSP中,可以通過Log標籤庫來訪問通用日誌接口,但是必須採用Log4J日誌器。