posts - 15,  comments - 34,  trackbacks - 27

          許多應用, 特別是企業應用, 都需要日志記錄程序。應用日志有助于服務工程師解決這個領域的難題, 并且能為安全分析提供審計跟蹤。

          最初, Java 平臺包含了很少可用于應用日志記錄的資源。被迫面對日志文件中的println語句的開發人員和系統管理員,有的設法發明自家的解決方案,有的轉而采用由商業開發商或者開放源碼開發者生產的眾多優秀(但互不兼容)的日志記錄產品中的一種。Java 2版本1.4 改變了這種局面,因為它引入了java.util.logging包。

          本期技巧簡要地解釋了Java日志記錄的基本知識,并提供了示例代碼,演示如何通過Java消息服務 (JMS)發送應用日志消息到某個獨立客戶端端。如果您不熟悉JMS, 參看2003年4月15 日那一期的“Publish/Subscribe Messaging With JMS Topics”以及 2003年3月11 日那一期的“使用JMS Queues(Using JMS Queues)”。

          java.util.logging

          Java logging包最初是作為Java Specification Request (JSR-047)創建的,現在是Java 2, Standard Edition (J2SE)的一部份。它的需求包括以下特性:

          • 最小的運行時性能影響。
          • 運行時啟用/禁用日志記錄。
          • 細粒度控制。
          • 運行時日志記錄服務注冊。
          • 與現有日志記錄服務的互操作性, 比如,系統日志和遺留日志記錄方案。
          • 在合適的時候向用戶顯示高優先級消息。
          • 能夠處理國際化的日志記錄消息。
          • 能夠記錄對象, 而不只是記錄字符串 。

          由于logging包是J2SE 的一部分, 它在其他Java 平臺也是可用的, 包括J2EE。具體地,Java logging可以用于應用客戶端、servlets 、JSP 頁面、企業bean 和連接器。

          Logging類和接口

          日志記錄程序的主要類是 Logger。 Logger表示一種通道,記錄(logging)消息可以通過它進行發送。通常,每個類有它自己的Logger。

          Logger 用Level來配置,這是一個指明問題嚴重性的類,用于指明所報告的問題的嚴重性和/或該類需要的詳情級別。每一條發送到Logger的消息都有一個關聯 Level。 Logger 只報告那些Level比該Logger高或者與之相同的錯誤。

          最高的日志記錄 Level 是 SEVERE, 表明碰到了一個嚴重問題—— 經常指的是一個致命錯誤。其他 Level 值(以遞減順序) 是 WARNING 和 INFO, 分別為可恢復的錯誤和信息類消息。 CONFIG 級別表明, 配置事件(比如正在讀一個屬性文件) 發生過。編程人員可以使用 的Level 值有: FINE、FINER 和 FINEST ,以連續報告更加細粒度的登錄消息。服務工程師可以使用這些 Level值來隱藏外部細節, 或在類到類(class-by-class)的基礎上增加日志記錄細節的級別。Logger的缺省 Level 是 INFO。

           LogRecord 是一個表示應該寫入日志的一條消息的對象。它包含各種各樣的信息, 包括被打印的消息, 最初發送給Logger的名字, Level 和所發送消息的創建時間與日期, 以及調用者的線程id。

          一個叫做 Handler的抽象類表示一個知道如何以一種有用方式表示 LogRecord的類。logging包包含一些 Handler類 (比如 ConsoleHandler、FileHandler、StreamHandler 和 SocketHandler) ,它們報告 LogRecords 各種類型的目標。每一 Logger都可以有多 個Handler。 每個 Handler 還可以有一個 Level, 摒除任何 LogRecord ,其Level 在它自己之下。因此, 例如, 單個 Logger 可能有二個Handler: 一個用于在磁盤上寫入日記文件,而另一個用于將日志消息發送到系統管理員的尋呼機。磁盤日志 Handler 可以用Level FINEST來配置,因此它將所有日志消息寫入磁盤。相反, 尋呼機日志 Handler可能只報告 SEVERE 日志消息。

           Formatter類(及其所定義的任何子類)將LogRecord轉換為String以便打印。例如, Formatter 的XMLFormatter 子類將LogRecord 寫為格式良好的XML。開發人員可以編寫定制的 Formatter 類。

          最后, Filter 接口允許編程人員編寫方法(isLoggable),該方法允許進行規劃性的控制,在這種控制下丟棄或者打印LogMessages。

          示例代碼

          本技巧的示例代碼示范了如何設置 Logger, 并使用它發送XML 格式的日志消息,從Web層,通過JMS,到達一個獨立JMS 客戶。

          本技巧的示例代碼包含一個servlet 和一個獨立客戶端端。servlet 稱作 LogDemoServlet。獨立客戶端端稱作LoggingReceiver。獨立客戶端端監聽正發布給JMS主題的消息, 并打印接收到任何TextMessages。示例應用包含一個用戶向LogDemoServlet張貼數據的HTML表單。

          òa?÷1

          注意, 表單提示用戶下載一個JAR文件,然后運行該文件作為一個獨立客戶端。在通過表單張貼數據之前,用戶需要完成這些步驟。

          servlet 通過向Topic發布一條XML 格式的消息來作出響應。如果 LoggingReceiver正在運行, 用戶會看到在屏幕上打印出一條XML 格式的消息。

          例如:

             <?xml version="1.0" encoding="MacRoman" standalone="no"?>
            <!DOCTYPE log SYSTEM "logger.dtd">
            <log>
            <record>
               <date>2003-05-05T23:51:20</date>
               <millis>1052200280257</millis>
               <sequence>0</sequence>
               <logger>com.elucify.tips.may2003.LogDemoServlet</logger>
               <level>INFO</level>
               <class>com.elucify.tips.may2003.LogDemoServlet</class>
               <method>doPost</method>
               <thread>10</thread>
               <message>quest= { 'Johnny' }
                FavoriteColor= { 'Violet' }
                name= { 'Johnny' }
            </message>
            </record>

          示例代碼中的關鍵部分是servlet LogDemoServlet。這個servlet 簡單地將它的POST參數格式化為一個字符串, 并在servlet每次被調用時將該字符記錄到Logger 中。方法doPost的開始處設置了 Logger:

              // Handle post request
             public void doPost(HttpServletRequest req,
                 HttpServletResponse res)
                 throws IOException, ServletException {
                 res.setContentType("text/html");
                 PrintWriter pw = res.getWriter();
                 // Get POST parameters and write them as
                 // "variable=value" to a ByteArrayOutputStream
                 String postParams = getPostParams(req);
                 ByteArrayOutputStream bos =
                     new ByteArrayOutputStream();
                 Logger logger = Logger.getLogger(
                     this.getClass().getName());

          servlet 設置內容類型、獲得一個Writer, 并格式化POST參量。然后它通過調用靜態方法 Logger.getLogger(this.getClass().getName())來創建了一個Logger。這個方法返回該名稱現有的Logger, 或者如果不存在的話,就創建一個。代碼使用了servlet 類的完全限定名。這是一個公共約定,以確保系統中各種Logger的名稱不會發生沖突。

          缺省情況下,Logger將它所創建的任何消息寫入到標準輸出,而不管運行什么代碼。例如,Web層消息通常寫入Web服務器日志文件。

          doPost方法的第二部分向Logger添加一個新的 Handler 。每次消息記錄到Logger時, Logger發送消息到兩個 Handlers (假設消息的日志級別足夠高) 。下面是的doPost方法的第二部分 :

                // Format logging messages as XML,
                 // store in byte array
                 StreamHandler sh = new StreamHandler(
                     bos, new XMLFormatter());
                 logger.addHandler(sh);
                 logger.log(Level.INFO, postParams);
                 sh.flush();


                 // Send contents of buffer as JMS message
                 // to listeners
                 publish(bos.toString());
                 pw.println(
                     "Logging messages sent to subscribers");
             }

          StreamHandler 是一個使用Formatter 來將LogRecord 格式化為字符串,并將它寫入OutputStream的處理程序。在本例中, OutputStream 是 ByteArrayOutputStream, 因此日志記錄結果被寫入內存。這個方法還使用一個 XMLFormatter,以便 LogRecords 被寫作XML文件 。對addHandler的調用將新的StreamHandler添加到Logger,然后將包含格式化POST參數的日志消息發送到 Logger。Logger 發送消息到它的所有Handlers,包括新的StreamHandler。對flush()的調用確保了所有已寫入字節被刷新到ByteArrayOutputStream。最后, ByteArrayOutputStream 被轉換成XML字符串。再通過發布方法將字符串發布給一個JMS Topic。關于如何將消息發送到JMS Topic的詳細描述(使用同樣的發布方法) ,請參看2003年4月15 日那一期的技巧“Publish/Subscribe Messaging With JMS Topics”。

          posted on 2005-02-04 11:25 jacky 閱讀(351) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          <2025年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          常用鏈接

          留言簿(10)

          隨筆檔案

          文章分類

          文章檔案

          相冊

          收藏夾

          java

          搜索

          •  

          最新評論


          主站蜘蛛池模板: 永胜县| 铜川市| 滦平县| 松江区| 色达县| 永清县| 改则县| 延川县| 平邑县| 梅河口市| 田阳县| 福鼎市| 澎湖县| 贵德县| 镇康县| 沂水县| 涞水县| 慈利县| 临沭县| 河北区| 舞钢市| 东乡族自治县| 名山县| 明水县| 白河县| 长宁区| 汕头市| 绥江县| 陈巴尔虎旗| 建始县| 理塘县| 巧家县| 隆化县| 陵川县| 洞头县| 抚顺市| 农安县| 海伦市| 敖汉旗| 盐山县| 武强县|