《Java 核心技术卷1 第10版》学习笔记------日志
日志 API 的優點:?
基本日志:
要生成簡單的日志記錄, 可以使用全局日志記錄器 (global logger ) 并調用其 info 方法 :
?
高級日志
在一個專業的應用程序中,通常是不會將所有的日志都記錄到一個全局日志記錄器中,而是可以自定義日志記錄器。
1. 創建或獲取日志記錄器
private static final Logger myLogger = Logger.getLogger("com.mycompany.myapp"); /* 未被任何變量引用的日志記錄器可能會被垃圾回收。為了防止這中情況的發生, 要像上面的例子中一樣,用一個靜態變量存儲日志記錄器的一個引用。 */與包名類似,日志記錄器也具有層次結構。事實上,與包名相比,日志記錄器的層次結構性更強。?對于包來說 , 一個包的名字與其父包的名字之間沒有語義關系, 但是日志記錄器的父與子之間將共享某些屬性 。例如 , 如果對 com.mycompany 日志記錄器設置了日志級別 ,它的子記錄器也會繼承這個級別 ,
通常日志級別有以下七個:【從左到右級別依次降低,詳細程度依次增加】
SEVERE、WARING、INFO、CONFIG、FINE、FINER、FINEST
默認情況下只記錄前三個級別【即:SEVERE、WARING、INFO】。
2. 更改日志記錄級別:
// 更改日志記錄級別 logger.setLevel(Level.FINE); // 現在可以記錄【SEVERE、WARING、INFO、CONFIG、FIINE】 // 關閉日志記錄 logger.setLevel(Level.OFF); // 開啟所有級別 logger.setLevel(Level.ALL);3. 記錄日志
// way 1 logger.waring(message); // 記錄 WARING 級別的日志 logger.fine(message); // 記錄 FINE 級別的日志 ... // way 2 logger.log(Level.FINE, message); // 記錄 FINE 級別的日志默認的日志記錄將顯示包含時間、日志調用的類名和方法名 , 如同堆棧所顯示的那樣 。但是 ,如果虛擬機對執行過程進行了優化, 就得不到準確的調用信息 。 此時 , 可以調用 logp 方法獲得調用類和方法的確切位置 , 這個方法的簽名為 :
// Logger 中的 logp 方法 void logp(Level l, String className, String methodName, String message);// 下面有一些用來跟蹤執行流的方法 void entering(String className, String methodName); void entering(String className, String methodName, Object param); void entering(String className, String methodName, Object[] params);void exiting(String className, String methodName); void exiting(String className, String methodName, Object result);// 執行流 Demo public class LogMain {private static final Logger myLogger = Logger.getLogger("com.chapter7.LogLearnMain");public static void main(String[] args) {// 測試執行流myLogger.setLevel(Level.FINER);sayWord("你好!");}public static int sayWord(String word){int result = 0;// 跟蹤執行流-進入myLogger.entering("com.chapter7.LogLearnMain", "sayWord", word);// 使用 logp 獲得調用類和方法的確切位置myLogger.logp(Level.INFO, "com.chapter7.LogLearnMain", "sayWord", "logp");if (!word.equals(null) && word.length()>0)System.out.println("Say: " + word);elseresult=-1;// // 跟蹤執行流-退出myLogger.exiting("com.chapter7.LogLearnMain", "sayWord", result);return result;} } // 這些調用將生成 FINER 級別和以字符串 ENTRY 和 RETURN 開始的日志記錄 。 // PS: 默認情況下我們是看不到以 ENTRY RETURN 開始的日志記錄的,具體原因往下看【日志處理器部分】, // 這里只給出解決辦法,修改 jre/lib/logging.properties 中的 // java.util.logging.ConsoleHandler.level = FINEST,當然由于日志級別的是 FINER 級別 // 的(不在默認的級別內),所以還要重設 logger.setLevel(Level.FINER) 才行。demo運行截圖:
記錄日志的常見用途是記錄那些不可預料的異常 。可以使用下面兩個方法提供日志記錄中包含的異常描述內容?
// 記錄異常 void throwing(String className, String methodName, Throwable t); void log(Level l, String message, Throwable t);// 典型的用法 way 1 if(...){IOException exception = new Exception(" exception info ");logger.throwing("com.mycompany.mylib.Reader", "read", exception);throw exception; }// 典型的用法 way 2 try{... }catch(IOException e){Logger.getLogger("").log(Level.WARING, "Reading image", e); }//PS: 調用 throwing 可以記錄一條 FINER 級別的記錄和一條以 THROW 開始的信息修改日志管理器配置
可以通過編輯配置文件來修改日志系統的各種屬性。默認情況下配置文件在:jre/lib/logging.properties
要想使用另一個配置文件,就要將 java.util.logging.config.file 屬性字段的值設置為自定義配置文件存儲位置,并用下列命令啟動應用程序:
java -D java.util.logging.config.file=configFile MainClass# 日志管理器【LogManager】在 JVM 啟動過程中初始化,即在 main 函數執行前完成。 # 如果在 main 中調用 System.setProperty("java.util.logging.config.file", file), # 也會調用 LogManager.readConfiguration() 來重新初始化日志管理器要想修改默認的日志記錄器級別,就需要編輯配置文件,并修改以下屬性字段
.level=INFO
可以通過添加以下內容來指定自己的日志記錄級別
com.mycompany.myapp.level=FINE
即在日志記錄器后面添加后綴 .level 即可。
在稍后可以看到 , 日志記錄并不將消息發送到控制臺上 , 這是處理器的任務 。 另外 , 處理器也有級別 。 要想在控制臺上看到 FINE 級別的消息, 就需要進行下列設置。
java.util.logging.ConsoleHandler.level = FINE
本地化
主要用于國際化程序處理,暫略。key word:?resource bundle
處理器
默認情況下日志記錄器將記錄發送到 ConsoleHandler 中, 并由它輸出到 System . err 流中 。特別是 , 日志記錄器還會將記錄發送到父處理器中 , 而最終的處理器(命名為 “ ” )有一個 ConsoleHandler 。
與日志記錄器一樣 , 處理器也有日志記錄級別 。 對于一個要被記錄的日志記錄, 它的日志記錄級別必須高于日志記錄器和處理器的閾值 。 日志管理器配置文件設置的默認控制臺處理器的日志記錄級別為 INFO。
要想記錄 FINE 級別的日志, 就必須修改配置文件中的默認日志記錄級別和處理器級別(上面Demo中的操作) 。另外 , 還可以繞過配置文件 , 安裝自己的處理器 。
// 使用自定義處理器 Logger logger = Logger.getLogger("com.mycompany.myapp"); logger.setLevel(Level.FINE); logger.setUseParentHandlers(flase); // 不使用父處理器 // 自定義處理器 Handler handler = new ConsoleHandler(); handler.setLevel(Level.FINE); // 設置處理器級別 logger.addHandler(handler); // 使用自定義處理器在默認情況下, 日志記錄器將記錄發送到自己的處理器和父處理器 。 我們的日志記錄器是原始日志記錄器 ( 命名為 “ ” )的子類 , 而原始日志記錄器將會把所有等于或高于 INFO級別的記錄發送到控制臺 。 然而 , 我們并不想兩次看到這些記錄 。 鑒于這個原因 , 應該將useParentHandlers ?設置為 false 。
要想將日志記錄發送到其他地方, 就要添加其他的處理器 。 日志 API 為此提供了兩個很有用的處理器 , 一個是 FileHandler ; 另 一個是 SocketHandler 。 SocketHandler 將記錄發送到特定的主機和端口 : ?而更令人感興趣的是 FileHandler , 它可以收集文件中的記錄 。
// 使用 FileHandler FileHandler handler = new FileHandler(); logger.addHandler(handler);這些記錄被發送到用戶主目錄的 javan.log 文件中 , n 是文件名的唯一編號 。 如果用戶系統沒有主目錄 ( 例如 , 在 Windows 95/98/ Me,) 文件就存儲在 C:\ Window 這樣的默認位置上。
在默認情況下 , 記錄被格式化為 XML 。 下面是一個典型的日志記錄的形式 :
可以通過設置 H 志管理器配置文件中的不同參數 (請參看表 7 - 1 ,?) 或者利用其他的構造器 ( 請參看本節后面給出的 APf 注釋) 來修改文件處理器的默認行為 。
也有可能不想使用默認的日志記錄文件名 , 因此, 應該使用另一種模式 , 例如, %h/myapp.log。
如果多個應用程序 ( 或者同一個應用程序的多個副本 ) 使用同一個口志文件 就應該開,啟 append 標志 。 另外 , 應該在文件名模式中使用 %u , 以便每個應用程序創建日志的唯一副本 。
開啟文件循環功能也是一個不錯的主意 。 日志文件以 myapp .log .O , myapp.log. 1 , myapp.log. 2 , 這種循環序列的形式出現 3 只要文件超出了大小限制 , 最舊的文件就會被刪除 , 其他的文件將重新命名 , 同時創建一個新文件 , 其編號為 0 。
自定義處理器
通過擴展 handler 或者是 StreamHandler 類自定義處理器。暫略
過濾器
在默認情況下 , 過濾器根據日志記錄的級別進行過濾 。 每個日志記錄器和處理器都可以有一個可選的過濾器來完成附加的過濾 。另外, 可以通過實現 Filter?接口并定義下列方法來自定義過濾器 。
boolean isLoggable(LogRecord record);在這個方法中, 可以利用自己喜歡的標準 , 對日志記錄進行分析 , 返回 true 表示這些錄應該包含在日志中 。 例如, 某個過濾器可能只對 entering 方法和 exiting 方法產生的消息感興趣 , 這個過濾器可以調用 record. getMessage() 方法 , 并査看這個消息是否用 ENTRY 或RETURN 開頭 。
要想將一個過濾器安裝到一個日志記錄器或處理器中 , 只需要調用 setFilter 方法就可以了 。 注意, 同一時刻最多只能有一個過濾器 。
格式化器
ConsoleHandler 類和 FileHandler 類可以生成文本和 XML 格式的日志記錄 。 但是, 也可以自定義格式 。 這需要擴展 Formatter 類并覆蓋下面這個方法?
String format(LogRecord record )可以根據自己的愿望對記錄中的信息進行格式化, 并返冋結果字符串。 在 format 方法中, 有可能會調用下面這個方法
String formatMessage(LogRecord record)這個方法對記錄中的部分消息進行格式化、 參數替換和本地化應用操作 。
很多文件格式 ( 如 XML ) 需要在已格式化的記錄的前后加上一個頭部和尾部在這個例子中, 要覆蓋下面兩個方法 :
最后, 調用 setFormatter 方法將格式化器安裝到處理器中 。
日志記錄說明
面對日志記錄如此之多的可選項 , 很容易讓人忘記最基本的東西。下面的 “日志說明書 ”總結了一些最常用的操作。
1. 為一個簡單的應用程序, 選擇一個日志記錄器 , 并把日志記錄器命名為與主應用程序包一樣的名字 , 例如, com . mycompany . myprog , 這是一種好的編程習慣 。 另外 , 可以通過調用下列方法得到日志記錄器 。
2.?默認的日志配置將級別等于或高于 INFO 級別的所有消息記錄到控制臺 。 用戶可以覆蓋默認的配置文件 。 但是正如前面所述 , 改變配置需要做相當多的工作 。 因此, 最好在應用程序中安裝一個更加適宜的默認配置 。
下列代碼確保將所有的消息記錄到應用程序特定的文件中 。 可以將這段代碼放置在應用程序的 main 方法中 。
if(System.getProperty("java.util.logging.config.class") == null&& System.getProperty("java.util.logging.config.file") == null){try {Logger.getLogger("").setLevel(Level.ALL);final int LOG_ROTATION_COUNT = 10;Handler handler = null;handler = new FileHandler("%h/myapp.log", 0, LOG_ROTATION_COUNT);Logger.getLogger("").addHandler(handler);} catch (IOException e) {e.printStackTrace();Logger.getLogger("").log(Level.SEVERE, "Cant't create log file handler", e);}}3.?現在, 可以記錄自己想要的內容了 。 但需要牢記 : 所有級別為 INFO 、 WARNING 和 SEVERE 的消息都將顯示到控制臺上。因此 最好只將對程序用戶有意義的消息設置為這幾個級別 。將程序員想要的日志記錄, 設定為 FINE 是一個很好的選擇 。
當調用 System. out.println 時, 實際上生成了下面的日志消息 :
logger.fine( "File open dialog canceled";)記錄那些不可預料的異常也是一個不錯的想法 , 例如 :
try{... }catch(SomeException e){logger.log(Level.FINE, "explanation", e); }?
總結
以上是生活随笔為你收集整理的《Java 核心技术卷1 第10版》学习笔记------日志的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《Java 核心技术卷1 第10版》学习
- 下一篇: 《Java 核心技术卷1 第10版》学习