在工作中,日誌功能是必不可少的元件,它爲我們提供了方便快捷的日誌記錄功能。藉此機會,總結下java專案中常用的第三方日誌介面與實現。
commons-logging 是Apache基金會下開發的一款日誌系統介面,通過其API可以整合不同的日誌系統實現,其主要用於爲整個軟件系統提供統一抽象的日誌操作,避免由於不同日誌系統實現所帶來的學習與遷移成本。從廣義的角度來說,即是面向介面開發理念。
既然談到commons-logging是一個介面,那麼我們如何在java專案中爲其指定對應的日誌實現呢。從官方文件中,我們可以看到commons-logging一共提供了五種查詢日誌實現的策略,優先順序從上到下依次遞減:
建議在commons-logging.properties檔案中定義此屬性,以明確選擇Log實現。
通過以上5種方式,commons-logging便完成了介面與實現的銜接。
接着,我們來談下commons-logging介面的使用方法。由於其是第三方元件,所以第一件事便是通過Maven將其引入到專案依賴中。其設定如下所示:
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
然後,便可以採用LogFactory建立一個Log物件,開啓日誌之旅,如下所示:
package org.example;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Commons-logging
*
*/
public class App
{
public static void main( String[] args )
{
Log log = LogFactory.getLog(App.class);
log.info("this is info!");
}
}
Commons Logging定義了6個日誌級別:
預設級別是INFO,在專案中,我們可以根據實際需求選擇我們需要的日誌登記。
2.log4j:
log4j 全稱爲log for(4) java, 即一個java日誌元件。從使用者角度來看,log4j主要由三大部分組成:
Logger, Appender, Formatter。
爲了使用log4j,同樣需要在maven中引入其依賴:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
Logger:簡而言之,logger就是一個用於獲取日誌物件,並寫入日誌的類,獲取該物件的方法也有多種,如下所示:
//Shorthand for getLogger(clazz.getName()).
static Logger getLogger(Class clazz)
//Retrieve a logger named according to the value of the name parameter.
static Logger getLogger(String name)
//Like getLogger(String) except that the type of logger instantiated depends on the type returned by the
static Logger getLogger(String name, LoggerFactory factory)
// method of the factory parameter.
LoggerFactory.makeNewLoggerInstance(java.lang.String)
//Return the root logger for the current logger repository.
static Logger getRootLogger()
Logger類是日誌包的核心,Logger的名稱是大小寫敏感的,並且名稱之間有繼承關係。子名由父名做字首,用點號「.」分隔,如x.y是x.y.z的父親Logger。
Logger系統中有個根logger,是所有logger的祖先,它總是存在的,並且不可以通過名字獲取,可以通過Logger.getRootLogger()來獲取。
並且一個Logger可以擁有多個Appender,這樣同一條日誌訊息可以輸出到多個地方。每個logger都有一個日誌級別,用來控制日誌的 輸出。未分配級別的logger將自動繼承它最近的父logger的日誌級別。Logger的由低到高級別如下:
ALL<DEBUG<INFO<WARN<ERROR<FATAL<OFF
Appender:在程式語言中,append方法往往出現在容器類中,用於給容器新增特定物件。同樣,在log4j中,可以將不同的日誌輸出目的地看作不同的日誌容器,比如控制檯、檔案、郵箱、數據庫等。這樣當給一個logger物件指定相應的appender時,便可以將相關日誌輸出到對應的目的地中。Log4j提供了以下幾個實現:
org.apache.log4j.ConsoleAppender(控制檯)
org.apache.log4j.FileAppender(檔案)
org.apache.log4j.DailyRollingFileAppender(每天都產生一個日誌檔案)
org.apache.log4j.RollingFileAppender(檔案大小達到指定尺寸時產生一個新的日誌檔案,檔名稱上會自動新增數位序號。)
org.apache.log4j.WriterAppender(將日誌資訊以流的格式發送到任意指定的地方)
預設情況下,子logger將繼承父logger的所有appenders。rootlogger擁有目標爲system.out的consoleAppender,故預設情況下,所有的logger都將繼承該appender。
Formatter:爲了便於閱讀,那麼格式化便是必不可少的工作,而這部分功能便由Formatter來提供。log4j提供了以下幾種formatter實現:
org.apache.log4j.HTMLLayout(以HTML表格形式佈局)
org.apache.log4j.PatternLayout(可以靈活地指定佈局模式)
org.apache.log4j.SimpleLayout(包含日誌資訊的級別和資訊字串)
org.apache.log4j.TTCCLayout(包含日誌產生的時間、執行緒、類別等資訊)
那麼使用者該怎麼設定來獲取自己想要的日誌輸出物件呢?Log4j爲我們提供來一個叫做log4j.properties檔案(需要放在class-path下)讓我們設定我們想要的日誌功能。首先來看看一個典型的組態檔:
1 ### logger的設定 ###
2 #設定根logger
3 log4j.rootLogger=INFO,stdout
4 #設定子logger:org.lavasoft(在org.lavasoft包中類的日誌在沒有指定子logger名的情況下使用這個logger)
5 log4j.logger.org.lavasoft=ERROR,file
6 #設定子logger:org.lavasoft.test(在org.lavasoft.test包中類的日誌在沒有指定子logger名的情況下使用這個logger)
7 log4j.logger.org.lavasoft.test=ERROR,file1,stdout
8
9 ### direct log messages to stdout ### (標準的終端輸出)
10 #控制檯輸出
11 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
12 #自定義輸出佈局
13 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
14 #輸出的格式
15 log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
16
17 ### direct messages to file ttt.log ### (輸入到檔案ttt.log的設定)
18 #輸出到卷動檔案
19 log4j.appender.file=org.apache.log4j.RollingFileAppender
20 #輸出檔案最大爲10M
21 log4j.appender.file.MaxFileSize=10MB
22 #輸出檔案最大序號爲10
23 log4j.appender.file.MaxBackupIndex=10
24 #輸出檔案路徑
25 log4j.appender.file.File=C:/ttt.log
26 #自定義輸出佈局
27 log4j.appender.file.layout=org.apache.log4j.PatternLayout
28 #輸出格式
29 log4j.appender.file.layout.ConversionPattern=%d %-5p [%t] (%13F:%L) %3x - %m%n
30
31 ### direct messages to file ttt.log ### (輸入到檔案ttt1.log的設定)
32 #輸出到卷動檔案
33 log4j.appender.file1=org.apache.log4j.RollingFileAppender
34 #輸出檔案最大爲10M
35 log4j.appender.file1.MaxFileSize=10MB
36 #輸出檔案最大序號爲10
37 log4j.appender.file1.MaxBackupIndex=10
38 #輸出檔案路徑
39 log4j.appender.file1.File=C:/ttt1.log
40 #自定義輸出佈局
41 log4j.appender.file1.layout=org.apache.log4j.PatternLayout
42 #輸出格式
43 log4j.appender.file1.layout.ConversionPattern=%d %-5p [%t] (%13F:%L) %3x - %m%n
下面 下麪對以上的檔案解說,並給出一個應用例子:
logger的設定語法爲:級別,輸入終端1,輸出終端2,…
根logger的設定項爲:log4j.rootLogger
子logger的設定項爲:
log4j.logger.<子logger名>
在上面的設定項中,設定了一個根logger和兩個子logger,名稱爲:org.lavasoft和org.lavasoft.test,通過該名稱,利用Logger.getLogger(String name)可以獲取這兩個logger物件。
子logger的名字一般都以包名來設定,這樣當在程式通過類名獲取logger的物件就是與本類包名相同的子logger,這樣可以方便控制某個包下面 下麪logger的輸出。
但是一般不建議設定子logger,一個通用的根logger足夠用了。由於繼承關係,並且可以在任何地方通過子logger的名字獲取logger物件,這樣容易導致混亂,比如在org.lavasoft包下的類直接獲取了名爲org.lavasoft.test子logger的物件,這是不合理的(雖然日誌可以列印出來),因爲如果直接在類中用Logger.getLogger(Class clazz)方式來獲取Logger物件,則獲取到的應該是名爲org.lavasoft的logger物件,而不會得到名爲org.lavasoft.test的logger物件。
以上的組態檔純粹是爲了說明問題才那麼寫的。
最後再列出一個典型的組態檔,以供大家實際專案中使用:
### 設定根 debug level,後面均爲定義的appender###
log4j.rootLogger = debug,console ,fileAppender,dailyRollingFile,ROLLING_FILE,MAIL,DATABASE
### 設定輸出sql的級別,其中logger後面的內容全部爲jar包中所包含的包名,這樣logger的appender繼承於rootlogger ###
log4j.logger.org.apache=debug
log4j.logger.java.sql.Connection=debug
log4j.logger.java.sql.Statement=debug
log4j.logger.java.sql.PreparedStatement=debug
log4j.logger.java.sql.ResultSet=debug
### 設定輸出到控制檯 ###
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = %d{ABSOLUTE} %5p %c{ 1 }:%L - %m%n
### 設定輸出到檔案 ###
log4j.appender.fileAppender = org.apache.log4j.FileAppender
log4j.appender.fileAppender.File = logs/log.log
log4j.appender.fileAppender.Append = true
log4j.appender.fileAppender.Threshold = DEBUG
log4j.appender.fileAppender.layout = org.apache.log4j.PatternLayout
log4j.appender.fileAppender.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 設定輸出到檔案,並且每天都建立一個檔案 ###
log4j.appender.dailyRollingFile = org.apache.log4j.DailyRollingFileAppender
log4j.appender.dailyRollingFile.File = logs/log.log
log4j.appender.dailyRollingFile.Append = true
log4j.appender.dailyRollingFile.Threshold = DEBUG
log4j.appender.dailyRollingFile.layout = org.apache.log4j.PatternLayout
log4j.appender.dailyRollingFile.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n### 設定輸出到檔案,且大小到達指定尺寸的時候產生一個新的檔案 ###log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender log4j.appender.ROLLING_FILE.Threshold=ERROR log4j.appender.ROLLING_FILE.File=rolling.log log4j.appender.ROLLING_FILE.Append=true log4j.appender.ROLLING_FILE.MaxFileSize=10KB log4j.appender.ROLLING_FILE.MaxBackupIndex=1 log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
### 設定輸出到郵件 ###
log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
log4j.appender.MAIL.Threshold=FATAL
log4j.appender.MAIL.BufferSize=10
[email protected]
log4j.appender.MAIL.SMTPHost=mail.hollycrm.com
log4j.appender.MAIL.Subject=Log4J Message
[email protected]
log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
### 設定輸出到數據庫 ###
log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test
log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
log4j.appender.DATABASE.user=root
log4j.appender.DATABASE.password=
log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n')
log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A1.File=SampleMessages.log4j
log4j.appender.A1.DatePattern=yyyyMMdd-HH'.log4j'
log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout