隨筆-71  評論-4  文章-0  trackbacks-0
          1. 概述

          1.1. 背景
             在應(yīng)用程序中添加日志記錄總的來說基于三個目的:監(jiān)視代碼中變量的變化情況,周期性的記錄到文件中供其他應(yīng)用進(jìn)行統(tǒng)計分析工作;跟蹤代碼運(yùn)行時軌跡,作為日后審計的依據(jù);擔(dān)當(dāng)集成開發(fā)環(huán)境中的調(diào)試器的作用,向文件或控制臺打印代碼的調(diào)試信息。

             最普通的做法就是在代碼中嵌入許多的打印語句,這些打印語句可以輸出到控制臺或文件中,比較好的做法就是構(gòu)造一個日志操作類來封裝此類操作,而不是讓一系列的打印語句充斥了代碼的主體。

          1.2. Log4j簡介

            在強(qiáng)調(diào)可重用組件開發(fā)的今天,除了自己從頭到尾開發(fā)一個可重用的日志操作類外,Apache為我們提供了一個強(qiáng)有力的日志操作包-Log4j。  Log4j是Apache的一個開放源代碼項目,通過使用Log4j,我們可以控制日志信息輸送的目的地是控制臺、文件、GUI組件、甚至是套接口服務(wù)器、NT的事件記錄器、UNIX Syslog守護(hù)進(jìn)程等;我們也可以控制每一條日志的輸出格式;通過定義每一條日志信息的級別,我們能夠更加細(xì)致地控制日志的生成過程。最令人感興趣的就是,這些可以通過一個配置文件來靈活地進(jìn)行配置,而不需要修改應(yīng)用的代碼。

             此外,通過Log4j其他語言接口,您可以在C、C++、.Net、PL/SQL程序中使用Log4j,其語法和用法與在Java程序中一樣,使得多語言分布式系統(tǒng)得到一個統(tǒng)一一致的日志組件模塊。而且,通過使用各種第三方擴(kuò)展,您可以很方便地將Log4j集成到J2EE、JINI甚至是SNMP應(yīng)用中。

             本文介紹的Log4j版本是1.2.3。作者試圖通過一個簡單的客戶/服務(wù)器Java程序例子對比使用與不使用Log4j1.2.3的差別,并詳細(xì)講解了在實(shí)踐中最常使用Log4j的方法和步驟。在強(qiáng)調(diào)可重用組件開發(fā)的今天,相信Log4j將會給廣大的設(shè)計開發(fā)人員帶來方便。加入到Log4j的隊伍來吧!

          2. 一個簡單的例子

             我們先來看一個簡單的例子,它是一個用Java實(shí)現(xiàn)的客戶/服務(wù)器網(wǎng)絡(luò)程序。剛開始我們不使用Log4j,而是使用了一系列的打印語句,然后我們將使用Log4j來實(shí)現(xiàn)它的日志功能。這樣,大家就可以清楚地比較出前后兩個代碼的差別。

          2.1. 不使用Log4j

          2.1.1. 客戶程序

          package log4j ;

          import java.io.* ;
          import java.net.* ;

          /**
           *
           * <p> Client Without Log4j </p>
           * <p> Description: a sample with log4j</p>
           * @version 1.0
           */
          public class ClientWithoutLog4j {

              /**
               *
               * @param args
               */
              public static void main ( String args [] ) {

                  String welcome = null;
                  String response = null;
                  BufferedReader reader = null;
                  PrintWriter writer = null;
                  InputStream in = null;
                  OutputStream out = null;
                  Socket client = null;

                  try {
                      client = new Socket ( "localhost", 8001 ) ;
                      System.out.println ( "info: Client socket: " + client ) ;
                      in = client.getInputStream () ;
                      out = client.getOutputStream () ;
                  } catch ( IOException e ) {
                      System.out.println ( "error: IOException : " + e ) ;
                      System.exit ( 0 ) ;
                  }

                  try{
                      reader = new BufferedReader( new InputStreamReader ( in ) ) ;
                      writer = new PrintWriter ( new OutputStreamWriter ( out ), true ) ;

                      welcome = reader.readLine () ;
                      System.out.println ( "debug: Server says: '" + welcome + "'" ) ;

                      System.out.println ( "debug: HELLO" ) ;
                      writer.println ( "HELLO" ) ;
                      response = reader.readLine () ;
                      System.out.println ( "debug: Server responds: '" + response + "'") ;

                      System.out.println ( "debug: HELP" ) ;
                      writer.println ( "HELP" ) ;
                      response = reader.readLine () ;
                      System.out.println ( "debug: Server responds: '" + response + "'" ) ;

                      System.out.println ( "debug: QUIT" ) ;
                      writer.println ( "QUIT" ) ;
                  } catch ( IOException e ) {
                      System.out.println ( "warn: IOException in client.in.readln()" ) ;
                      System.out.println ( e ) ;
                  }
                  try{
                      Thread.sleep ( 2000 ) ;
                  } catch ( Exception ignored ) {}
              }
          }

          2.1.2. 服務(wù)器程序

          package log4j ;

          import java.util.* ;
          import java.io.* ;
          import java.net.* ;

          /**
           *
           * <p> Server Without Log4j </p>
           * <p> Description: a sample with log4j</p>
           * @version 1.0
           */
          public class ServerWithoutLog4j {

              final static int SERVER_PORT = 8001 ; // this server's port

              /**
               *
               * @param args
               */
              public static void main ( String args [] ) {
                  String clientRequest = null;
                  BufferedReader reader = null;
                  PrintWriter writer = null;
                  ServerSocket server = null;
                  Socket socket = null;
                  InputStream in = null;
                  OutputStream out = null;

                  try {
                      server = new ServerSocket ( SERVER_PORT ) ;
                      System.out.println ( "info: ServerSocket before accept: " + server ) ;
                      System.out.println ( "info: Java server without log4j, on-line!" ) ;

                      // wait for client's connection
                      socket = server.accept () ;
                      System.out.println ( "info: ServerSocket after accept: " + server )  ;

                      in = socket.getInputStream () ;
                      out = socket.getOutputStream () ;

                  } catch ( IOException e ) {
                      System.out.println( "error: Server constructor IOException: " + e ) ;
                      System.exit ( 0 ) ;
                  }
                  reader = new BufferedReader ( new InputStreamReader ( in ) ) ;
                  writer = new PrintWriter ( new OutputStreamWriter ( out ) , true ) ;

                  // send welcome string to client
                  writer.println ( "Java server without log4j, " + new Date () ) ;

                  while ( true ) {
                      try {
                          // read from client
                          clientRequest = reader.readLine () ;
                          System.out.println ( "debug: Client says: " + clientRequest ) ;
                          if ( clientRequest.startsWith ( "HELP" ) ) {
                              System.out.println ( "debug: OK!" ) ;
                              writer.println ( "Vocabulary: HELP QUIT" ) ;
                          }
                          else {
                              if ( clientRequest.startsWith ( "QUIT" ) ) {
                                  System.out.println ( "debug: OK!" ) ;
                                  System.exit ( 0 ) ;
                              }
                              else{
                                  System.out.println ( "warn: Command '" + clientRequest + "' not understood." ) ;
                                  writer.println ( "Command '" + clientRequest + "' not understood." ) ;
                              }
                          }
                      } catch ( IOException e ) {
                          System.out.println ( "error: IOException in Server " + e ) ;
                          System.exit ( 0 ) ;
                      }
                  }
              }
          }

          2.2. 遷移到Log4j

          2.2.1. 客戶程序

          package log4j ;

          import java.io.* ;
          import java.net.* ;

          // add for log4j: import some package
          import org.apache.log4j.PropertyConfigurator ;
          import org.apache.log4j.Logger ;
          import org.apache.log4j.Level ;

          /**
           *
           * <p> Client With Log4j </p>
           * <p> Description: a sample with log4j</p>
           * @version 1.0
           */
          public class ClientWithLog4j {

              /*
              add for log4j: class Logger is the central class in the log4j package.
              we can do most logging operations by Logger except configuration.
              getLogger(...): retrieve a logger by name, if not then create for it.
              */
              static Logger logger = Logger.getLogger(ClientWithLog4j.class.getName () ) ;

              /**
               *
               * @param args : configuration file name
               */
              public static void main ( String args [] ) {

                  String welcome = null ;
                  String response = null ;
                  BufferedReader reader = null ;
                  PrintWriter writer = null ;
                  InputStream in = null ;
                  OutputStream out = null ;
                  Socket client = null ;

                  /*
                  add for log4j: class BasicConfigurator can quickly configure the package.
                  print the information to console.
                  */
                  PropertyConfigurator.configure ( "ClientWithLog4j.properties" ) ;

                  // add for log4j: set the level
                  //logger.setLevel ( ( Level ) Level.DEBUG ) ;

                  try{
                      client = new Socket( "localhost" , 8001 ) ;

                      // add for log4j: log a message with the info level
                      logger.info ( "Client socket: " + client ) ;

                      in = client.getInputStream () ;
                      out = client.getOutputStream () ;
                  } catch ( IOException e ) {

                      // add for log4j: log a message with the error level
                      logger.error ( "IOException : " + e ) ;

                      System.exit ( 0 ) ;
                  }

                  try{
                      reader = new BufferedReader ( new InputStreamReader ( in ) ) ;
                      writer = new PrintWriter ( new OutputStreamWriter ( out ), true ) ;

                      welcome = reader.readLine () ;

                      // add for log4j: log a message with the debug level
                      logger.debug ( "Server says: '" + welcome + "'" ) ;

                      // add for log4j: log a message with the debug level
                      logger.debug ( "HELLO" ) ;

                      writer.println ( "HELLO" ) ;
                      response = reader.readLine () ;

                      // add for log4j: log a message with the debug level
                      logger.debug ( "Server responds: '" + response + "'" ) ;

                      // add for log4j: log a message with the debug level
                      logger.debug ( "HELP" ) ;

                      writer.println ( "HELP" ) ;
                      response = reader.readLine () ;

                      // add for log4j: log a message with the debug level
                      logger.debug ( "Server responds: '" + response + "'") ;

                      // add for log4j: log a message with the debug level
                      logger.debug ( "QUIT" ) ;

                      writer.println ( "QUIT" ) ;
                  } catch ( IOException e ) {

                      // add for log4j: log a message with the warn level
                      logger.warn ( "IOException in client.in.readln()" ) ;

                      System.out.println ( e ) ;
                  }
                  try {
                      Thread.sleep ( 2000 ) ;
                  } catch ( Exception ignored ) {}
              }
          }

          2.2.2. 服務(wù)器程序

          package log4j;

          import java.util.* ;
          import java.io.* ;
          import java.net.* ;

          // add for log4j: import some package
          import org.apache.log4j.PropertyConfigurator ;
          import org.apache.log4j.Logger ;
          import org.apache.log4j.Level ;

          /**
           *
           * <p> Server With Log4j </p>
           * <p> Description: a sample with log4j</p>
           * @version 1.0
           */
          public class ServerWithLog4j {

              final static int SERVER_PORT = 8001 ; // this server's port

              /*
              add for log4j: class Logger is the central class in the log4j package.
              we can do most logging operations by Logger except configuration.
              getLogger(...): retrieve a logger by name, if not then create for it.
              */
              static Logger logger = Logger.getLogger 
          ( ServerWithLog4j.class.getName () ) ;

              /**
               *
               * @param args
               */
              public static void main ( String args[]) {
                  String clientRequest = null ;
                  BufferedReader reader = null ;
                  PrintWriter writer = null ;
                  ServerSocket server = null ;
                  Socket socket = null ;

                  InputStream in = null ;
                  OutputStream out = null ;

                  /*
                  add for log4j: class BasicConfigurator can quickly configure the package.
                  print the information to console.
                  */
                  PropertyConfigurator.configure ( "ServerWithLog4j.properties" ) ;

                  // add for log4j: set the level
                  // logger.setLevel ( ( Level ) Level.DEBUG ) ;

                  try{
                      server = new ServerSocket ( SERVER_PORT ) ;

                      // add for log4j: log a message with the info level
                      logger.info ( "ServerSocket before accept: " + server ) ;

                      // add for log4j: log a message with the info level
                      logger.info ( "Java server with log4j, on-line!" ) ;

                      // wait for client's connection
                      socket = server.accept() ;

                      // add for log4j: log a message with the info level
                      logger.info ( "ServerSocket after accept: " + server ) ;

                      in = socket.getInputStream() ;
                      out = socket.getOutputStream() ;

                  } catch ( IOException e ) {

                      // add for log4j: log a message with the error level
                      logger.error ( "Server constructor IOException: " + e ) ;
                      System.exit ( 0 ) ;
                  }
                  reader = new BufferedReader ( new InputStreamReader ( in ) ) ;
                  writer = new PrintWriter ( new OutputStreamWriter ( out ), true ) ;

                  // send welcome string to client
                  writer.println ( "Java server with log4j, " + new Date () ) ;

                  while ( true ) {
                      try {
                          // read from client
                          clientRequest = reader.readLine () ;

                          // add for log4j: log a message with the debug level
                          logger.debug ( "Client says: " + clientRequest ) ;

                          if ( clientRequest.startsWith ( "HELP" ) ) {

                              // add for log4j: log a message with the debug level
                              logger.debug ( "OK!" ) ;

                              writer.println ( "Vocabulary: HELP QUIT" ) ;
                          }
                          else {
                              if ( clientRequest.startsWith ( "QUIT" ) ) {

                                  // add for log4j: log a message with the debug level
                                  logger.debug ( "OK!" ) ;

                                  System.exit ( 0 ) ;
                              }
                              else {

                                  // add for log4j: log a message with the warn level
                                  logger.warn ( "Command '" + clientRequest + "' not understood." ) ;

                                  writer.println ( "Command '"+ clientRequest + "' not understood." ) ;
                              }
                          }
                      } catch ( IOException e ) {

                          // add for log4j: log a message with the error level
                          logger.error( "IOException in Server " + e ) ;

                          System.exit ( 0 ) ;
                      }
                  }
              }
          }

          2.2.3. 配置文件

          2.2.3.1. 客戶程序配置文件

          log4j.rootLogger=INFO, A1

          log4j.appender.A1=org.apache.log4j.ConsoleAppender

          log4j.appender.A1.layout=org.apache.log4j.PatternLayout

          log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n

          2.2.3.2. 服務(wù)器程序配置文件

          log4j.rootLogger=INFO, A1

          log4j.appender.A1=org.apache.log4j.ConsoleAppender

          log4j.appender.A1.layout=org.apache.log4j.PatternLayout

          log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n

          2.3. 比較

             比較這兩個應(yīng)用可以看出,采用Log4j進(jìn)行日志操作的整個過程相當(dāng)簡單明了,與直接使用System.out.println語句進(jìn)行日志信息輸出的方式相比,基本上沒有增加代碼量,同時能夠清楚地理解每一條日志信息的重要程度。通過控制配置文件,我們還可以靈活地修改日志信息的格式,輸出目的地等等方面,而單純依靠System.out.println語句,顯然需要做更多的工作。

          下面我們將以前面使用Log4j的應(yīng)用作為例子,詳細(xì)講解使用Log4j的主要步驟。

          3. Log4j基本使用方法

              Log4j由三個重要的組件構(gòu)成:日志信息的優(yōu)先級,日志信息的輸出目的地,日志信息的輸出格式。日志信息的優(yōu)先級從高到低有ERROR、WARN、INFO、DEBUG,分別用來指定這條日志信息的重要程度;日志信息的輸出目的地指定了日志將打印到控制臺還是文件中;而輸出格式則控制了日志信息的顯示內(nèi)容。

          3.1.定義配置文件

              其實(shí)您也可以完全不使用配置文件,而是在代碼中配置Log4j環(huán)境。但是,使用配置文件將使您的應(yīng)用程序更加靈活。Log4j支持兩種配置文件格式,一種是XML格式的文件,一種是Java特性文件(鍵=值)。下面我們介紹使用Java特性文件做為配置文件的方法:

          配置根Logger,其語法為:

          log4j.rootLogger = [ level ] , appenderName, appenderName, …
               其中,level 是日志記錄的優(yōu)先級,分為OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定義的級別。Log4j建議只使用四個級別,優(yōu)先級從高到低分別是ERROR、WARN、INFO、DEBUG。通過在這里定義的級別,您可以控制到應(yīng)用程序中相應(yīng)級別的日志信息的開關(guān)。比如在這里定義了INFO級別,則應(yīng)用程序中所有DEBUG級別的日志信息將不被打印出來。appenderName就是指定日志信息輸出到哪個地方。您可以同時指定多個輸出目的地。

          配置日志信息輸出目的地Appender,其語法為

          log4j.appender.appenderName = fully.qualified.name.of.appender.class
          log4j.appender.appenderName.option1 = value1

          log4j.appender.appenderName.option = valueN
          其中,Log4j提供的appender有以下幾種:
          org.apache.log4j.ConsoleAppender(控制臺),
          org.apache.log4j.FileAppender(文件),
          org.apache.log4j.DailyRollingFileAppender(每天產(chǎn)生一個日志文件),
          org.apache.log4j.RollingFileAppender(文件大小到達(dá)指定尺寸的時候產(chǎn)生一個新的文件),
          org.apache.log4j.WriterAppender(將日志信息以流格式發(fā)送到任意指定的地方)

          配置日志信息的格式(布局),其語法為:

          log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
          log4j.appender.appenderName.layout.option1 = value1

          log4j.appender.appenderName.layout.option = valueN
          其中,Log4j提供的layout有以下幾種:
          org.apache.log4j.HTMLLayout(以HTML表格形式布局),
          org.apache.log4j.PatternLayout(可以靈活地指定布局模式),
          org.apache.log4j.SimpleLayout(包含日志信息的級別和信息字符串),
          org.apache.log4j.TTCCLayout(包含日志產(chǎn)生的時間、線程、類別等等信息)

          3.2.在代碼中使用Log4j

          下面將講述在程序代碼中怎樣使用Log4j。

          3.2.1.得到記錄器

          使用Log4j,第一步就是獲取日志記錄器,這個記錄器將負(fù)責(zé)控制日志信息。其語法為:
          public static Logger getLogger( String name),
          通過指定的名字獲得記錄器,如果必要的話,則為這個名字創(chuàng)建一個新的記錄器。Name一般取本類的名字,比如:
          static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () ) ;
          3.2.2.讀取配置文件

              當(dāng)獲得了日志記錄器之后,第二步將配置Log4j環(huán)境,其語法為:
          BasicConfigurator.configure (): 自動快速地使用缺省Log4j環(huán)境。
          PropertyConfigurator.configure ( String configFilename) :讀取使用Java的特性文件編寫的配置文件。
          DOMConfigurator.configure ( String filename ) :讀取XML形式的配置文件。

          3.2.3.插入記錄信息(格式化日志信息)

              當(dāng)上兩個必要步驟執(zhí)行完畢,您就可以輕松地使用不同優(yōu)先級別的日志記錄語句插入到您想記錄日志的任何地方,其語法如下:

          Logger.debug ( Object message ) ;
          Logger.info ( Object message ) ;
          Logger.warn ( Object message ) ;
          Logger.error ( Object message ) ;

          4. 參考資料

          如果您想更深入地了解Log4j,請經(jīng)常訪問下面提及的相關(guān)鏈接。
          Log4j項目主頁------------------------------------------------------www.log4j.org
          Log4j FAQ -------------------------------------------------------www.log4j.org/log4j/faq.html

          posted on 2006-01-12 12:40 zjw_albert 閱讀(117) 評論(0)  編輯  收藏

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


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 自治县| 贵州省| 大丰市| 沅江市| 额尔古纳市| 奈曼旗| 凌云县| 五指山市| 卫辉市| 阳江市| 岳阳县| 林州市| 龙海市| 陆河县| 汝州市| 安义县| 涿鹿县| 乌兰县| 广元市| 周宁县| 万年县| 武安市| 都兰县| 利川市| 高雄市| 江津市| 兴隆县| 尼木县| 余江县| 昭苏县| 西充县| 称多县| 宜兴市| 望城县| 达孜县| 宜川县| 天气| 涿州市| 集贤县| 塔河县| 大庆市|