概述:java
第1部分 建立Logger對象apache
第2部分 日誌級別tomcat
第3部分 Handler服務器
第5部分 自定義測試
參考 操作系統
要使用J2SE的日誌功能,首先要取得java.util.logging.Logger實例,這能夠經過Logger類的兩個靜態getLogger()方法來取得:命令行
static Logger getLogger(String name) 查找或建立一個logger。 static Logger getLogger(String name, String resourceBundleName) 爲指定子系統查找或建立一個logger。
注意:name是Logger的名稱,當名稱相同時候,同一個名稱的Logger只建立一個。3d
下面是簡單範例:
1 public class LoggingDemo { 2 public static void main(String[] args){ 3 Logger logger = Logger.getLogger("LoggingDemo"); 4 5 try{ 6 System.out.println(args[0]); 7 }catch(ArrayIndexOutOfBoundsException e){ 8 logger.warning("沒有提供執行時的自變量!"); 9 } 10 } 11 }
執行結果:
在進行信息的記錄時,依信息程序的不一樣,會設定不一樣等級的信息輸出。Java log比log4j的級別詳細,所有定義在java.util.logging.Level裏面。
各級別按降序排列以下:
此外,還有一個級別OFF,可用來關閉日誌記錄,使用級別ALL啓用全部消息的日誌記錄。
logger默認的級別是INFO,比INFO更低的日誌將不顯示。
Logger的默認級別定義是在jre安裝目錄的lib下面。
# Limit the message that are printed on the console to INFO and above.
java.util.logging.ConsoleHandler.level = INFO
能夠經過操做Logger上的幾個方法來獲得不一樣等級的信息輸出。以下列範例:
1 public class LoggingDemo { 2 public static void main(String[] args){ 3 Logger logger = Logger.getLogger("LoggingDemo"); 4 5 logger.severe("嚴重信息"); 6 7 logger.warning("警示信息"); 8 9 logger.info("通常信息"); 10 11 logger.config("設定方面的信息"); 12 13 logger.fine("細微的信息"); 14 15 logger.finer("更細微的信息"); 16 17 logger.finest("最細微的信息"); 18 } 19 20 }
執行結果:
此示例中config()方法及如下的信息並無顯示出來,這是由於Logger的默認等級是INFO,比這個等級更低的信息,Logger並不會將信息輸出。
Logger的默認等級是定義在執行環境的屬性文件logging.properties中,這個文件位於JRE安裝目錄的lib目錄下。部份內容以下:
# Limit the message that are printed on the console to INFO and above. java.util.logging.ConsoleHandler.level = INFO java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
Logger默認的輸出媒介控制器(Handler)是java.util.logging.ConsolerHandler,也就是將信息輸出至控制檯。一個Logger能夠擁有多個handler,每一個handler能夠有本身的日誌級別,在經過Logger的級別限制後,實際上還要再通過handler的級別限制。因此在上面的範例中若是想要看到全部的信息,則必須同時設定Logger與!ConsoleHandler的級別。下面的範例示範瞭如何設定:
1 public class LoggingDemo { 2 public static void main(String[] args){ 3 Logger logger = Logger.getLogger("LoggingDemo"); 4 5 //顯示全部等級的信息 6 logger.setLevel(Level.ALL); 7 ConsoleHandler consoleHandler = new ConsoleHandler(); 8 //顯示全部等級的信息 9 consoleHandler.setLevel(Level.ALL); 10 //設定Handler爲!ConsoleHandler 11 logger.addHandler(consoleHandler); 12 logger.severe("嚴重信息"); 13 logger.warning("警示信息"); 14 logger.info("通常信息"); 15 logger.config("設定方面的信息"); 16 logger.fine("細微的信息"); 17 logger.finer("更細微的信息"); 18 logger.finest("最細微的信息"); 19 } 20 21 }
執行結果:
Level.ALL表示顯示全部的信息,全部這一次的執行結果可顯示全部等級的信息。若是要關閉全部的信息,能夠設定爲Level.OFF。
Logger的Severe(),warning(),info()等方法,其實是個便捷的方法。也能夠直接使用log()方法並指定等級來執行相同的做用,如:
public class LoggingDemo { public static void main(String[] args){ Logger logger = Logger.getLogger("LoggingDemo"); logger.log(Level.SEVERE, "嚴重信息test"); } }
結果:
Handler對象從Logger中獲取日誌信息,並將這些信息導出。例如,它可將這些信息寫入控制檯或文件中,也能夠將這些信息發送到網絡日誌服務中,或將其轉發到操做系統日誌中。
Logger默認的輸出處理者是ConsoleHandler。!ConsoleHandler的輸出是使用System.err對象,而信息的默認等級是INFO,這能夠在JRE安裝目錄下lib目錄的logging.properties中看到:
# Limit the message that are printed on the console to INFO and above.
java.util.logging.ConsoleHandler.level = INFO
Java SE實現了5個Handler:
(1) java.util.logging.ConsoleHandler 以System.err輸出日誌。
(2) java.util.logging.FileHandler 將信息輸出到文件。
(3) java.util.logging.!StreamHandler以指定的!OutputStream實例輸出日誌。
(4) java.util.logging.!SocketHandler將信息經過Socket傳送至遠程主機。
(5) java.util.logging.!MemoryHandler將信息暫存在內存中。
如下代碼將信息輸出至文件中:
1 public class LoggingDemo { 2 public static void main(String[] args){ 3 Logger logger = Logger.getLogger("LoggingDemo"); 4 5 try { 6 FileHandler fileHandler = new FileHandler("D:\\test/3.txt"); 7 logger.addHandler(fileHandler); 8 logger.info("測試信息"); 9 } catch (SecurityException e) { 10 e.printStackTrace(); 11 } catch (IOException e) { 12 e.printStackTrace(); 13 } 14 } 15 16 }
執行結果:
D:\test\3.text內容以下:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE log SYSTEM "logger.dtd"> <log> <record> <date>2014-11-25T10:53:49</date> <millis>1416884029723</millis> <sequence>0</sequence> <logger>LoggingDemo</logger> <level>INFO</level> <class>com.ConcurrentContainer.LoggingDemo</class> <method>main</method> <thread>1</thread> <message>測試信息</message> </record> </log>
fileHandler默認的輸出格式是XML格式。輸出格式由java.util.logging.Formatter來控制,下一節詳細介紹Formatter。
Formatter爲格式化LogRecords提供支持。
通常來講,每一個Handler都有關聯的Formatter。Formatter接受LogRecord,並將它轉換爲一個字符串。
默認提供了兩種Formatter:
1.java.util.logging.SimpleFormatter:標準日誌格式,就是咱們一般在啓動一些諸如 Tomcat、 JBoss之類的服務器的時候常常能在控制檯下看到的那種形式,就像這樣:
2004-12-20 23:08:52 org.apache.coyote.http11.Http11Protocol init
信息: Initializing Coyote HTTP/1.1 on http-8080
2.java.util.logging.XMLFormatter:XML形式的日誌格式,若是爲Logger添加了一個new XMLFormatter(),那麼就會以XML形式輸出,不過更經常使用的是使用上面介紹的FileHandler輸出到XML文件中。
從上一節的例子可知,FileHandler的默認格式是java.util.logging.XMLFormatter,而ConsolerHandler的默認格式是java.util.logging.SimpleFormatter,可使用Handler實例的setFormatter()方法來設定信息的輸出格式。例如:
fileHandler.setFormatter(new SimpleFormatter());
FileHandler的Formatter設定爲SimpleFormatter,則輸出的日誌文件內容就是簡單的文字信息,打開文件後會發現與命令行模式下看到的信息內容相同。
一、Handler
用戶能夠定製本身輸出媒介控制器,繼承Handler便可,一般只須要實現Handler中三個未定義的抽象方法:
publish:主要方法,把日誌記錄寫入你須要的媒介。
flush:清除緩衝區並保存數據。
close:關閉控制器。
經過重寫以上三個方法能夠很容易實現一個新的輸出媒介控制器。
二、Formatter
除了XMLFormatter與!SimpleFormatter以外,也能夠自定義日誌的輸出格式,只要繼承抽象類Formatter,並從新定義其format()方法便可。format()方法會傳入一個java.util.logging.LogRecord對象做爲參數,可使用它來取得一些與程序執行有關的信息。'
三、日誌級別
Java的一個日誌級別對應一個整數值,Level有9個內置的級別,分別是:
類型 對應的整數
OFF 最大整數( Integer. MAX_VALUE)
SEVERE 1000
WARNING 900
INFO 800
CONFIG 700
FINE 500
FINER 400
FINEST 300
ALL 最小整數(Integer. MIN_VALUE)
你也能夠定義本身的日誌級別,經過繼承Level的方式,譬如:
1 /** 2 * 自定義日誌級別 3 * @ClassName: AlertLevel 4 * TODO 5 * @author xingle 6 * @date 2014-11-25 上午9:54:23 7 */ 8 public class AlertLevel extends Level{ 9 10 /** 11 * @param name 12 * @param value 13 */ 14 protected AlertLevel(String name, int value) { 15 super(name,value); 16 } 17 18 public static void main(String[] args){ 19 Logger logger = Logger.getAnonymousLogger(); 20 //低於INFO(800),顯示不出來,由於默認的配置 java.util.logging.ConsoleHandler.level = INFO 21 logger.log(new AlertLevel("ALERT",950), "自定義 lever!"); 22 } 23 }
執行結果:
在使用Logger的靜態getLogger()方法取得Logger實例時,給getLogger()方法的名稱是有意義的。若是給定a,實際上將從根(Root)logger繼承一些特性,像日誌級別(Level)以及根logger的輸出媒介控制器。若是再取得一個Logger實例,並給定名稱a.b,則此次取得的Logger將繼承pku這個Logger上的特性。從如下範例能夠看出Logger在名稱上的繼承關係:
1 /** 2 * Logger的層次關係 3 * @ClassName: LoggerHierarchyDemo 4 * TODO 5 * @author xingle 6 * @date 2014-11-25 上午10:04:54 7 */ 8 public class LoggerHierarchyDemo { 9 public static void main(String[] args){ 10 Logger onlyfunLogger = Logger.getLogger("a"); 11 Logger caterpillarLogger = Logger.getLogger("a.b"); 12 System.out.println("root logger:"+onlyfunLogger.getParent()); 13 System.out.println("onlyfun logger:" + caterpillarLogger.getParent().getName()); 14 System.out.println("caterpillar Logger:" + caterpillarLogger.getName() + "\n"); 15 onlyfunLogger.setLevel(Level.WARNING); 16 caterpillarLogger.info("caterpillar ' info"); 17 caterpillarLogger.setLevel(Level.INFO); 18 caterpillarLogger.info("caterpillar ' info"); 19 } 20 }
執行結果:
getParent()方法能夠取得Logger上的上層父Logger,根Logger並無名稱,因此直接調用它的toString()以取得字符串描述。當Logger沒有設定等級時,則使用父Logger的等級設定,因此在上面的範例中,onlyfunLogger設定等級爲WARNING時,caterpillarLogger調用info()方法時並不會有信息顯示(由於WARNING等級比INFO高)。