風(fēng)行天下

          JAVA太極
          posts - 4, comments - 10, trackbacks - 0, articles - 55
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          Apache commons簡介

          Posted on 2005-04-26 10:55 風(fēng)太少 閱讀(4911) 評論(0)  編輯  收藏

          Apache Commons是一個(gè)非常有用的工具包,解決各種實(shí)際的通用問題,下面是一個(gè)簡述表,詳細(xì)信息訪問http://jakarta.apache.org/commons/index.html

          BeanUtils
          Commons-BeanUtils 提供對 Java 反射和自省API的包裝

          Betwixt
          Betwixt提供將 JavaBean 映射至 XML 文檔,以及相反映射的服務(wù).

          Chain
          Chain 提供實(shí)現(xiàn)組織復(fù)雜的處理流程的“責(zé)任鏈模式”.

          CLI
          CLI 提供針對命令行參數(shù),選項(xiàng),選項(xiàng)組,強(qiáng)制選項(xiàng)等的簡單API.

          Codec
          Codec 包含一些通用的編碼解碼算法。包括一些語音編碼器, Hex, Base64, 以及URL encoder.

          Collections
          Commons-Collections 提供一個(gè)類包來擴(kuò)展和增加標(biāo)準(zhǔn)的 Java Collection框架

          Configuration
          Commons-Configuration 工具對各種各式的配置和參考文件提供讀取幫助.

          Daemon
          一種 unix-daemon-like java 代碼的替代機(jī)制

          DBCP
          Commons-DBCP 提供數(shù)據(jù)庫連接池服務(wù)

          DbUtils
          DbUtils 是一個(gè) JDBC helper 類庫,完成數(shù)據(jù)庫任務(wù)的簡單的資源清除代碼.

          Digester
          Commons-Digester 是一個(gè) XML-Java對象的映射工具,用于解析 XML配置文件.

          Discovery
          Commons-Discovery 提供工具來定位資源 (包括類) ,通過使用各種模式來映射服務(wù)/引用名稱和資源名稱。.

          EL
          Commons-EL 提供在JSP2.0規(guī)范中定義的EL表達(dá)式的解釋器.

          FileUpload
          FileUpload 使得在你可以在應(yīng)用和Servlet中容易的加入強(qiáng)大和高性能的文件上傳能力

          HttpClient
          Commons-HttpClient 提供了可以工作于HTTP協(xié)議客戶端的一個(gè)框架.

          IO
          IO 是一個(gè) I/O 工具集

          Jelly
          Jelly是一個(gè)基于 XML 的腳本和處理引擎。 Jelly 借鑒了 JSP 定指標(biāo)簽,Velocity, Cocoon和Xdoclet中的腳本引擎的許多優(yōu)點(diǎn)。Jelly 可以用在命令行, Ant 或者 Servlet之中。

          Jexl
          Jexl是一個(gè)表達(dá)式語言,通過借鑒來自于Velocity的經(jīng)驗(yàn)擴(kuò)展了JSTL定義的表達(dá)式語言。.

          JXPath
          Commons-JXPath 提供了使用Xpath語法操縱符合Java類命名規(guī)范的 JavaBeans的工具。也支持 maps, DOM 和其他對象模型。.

          Lang
          Commons-Lang 提供了許多許多通用的工具類集,提供了一些java.lang中類的擴(kuò)展功能

          Latka
          Commons-Latka 是一個(gè)HTTP 功能測試包,用于自動化的QA,驗(yàn)收和衰減測試.

          Launcher
          Launcher 組件是一個(gè)交叉平臺的Java 應(yīng)用載入器。 Commons-launcher 消除了需要批處理或者Shell腳本來載入Java 類。.原始的 Java 類來自于Jakarta Tomcat 4.0 項(xiàng)目

          Logging
          Commons-Logging 是一個(gè)各種 logging API實(shí)現(xiàn)的包裹類.

          Math
          Math 是一個(gè)輕量的,自包含的數(shù)學(xué)和統(tǒng)計(jì)組件,解決了許多非常通用但沒有及時(shí)出現(xiàn)在Java標(biāo)準(zhǔn)語言中的實(shí)踐問題.

          Modeler
          Commons-Modeler 提供了建模兼容JMX規(guī)范的 Mbean的機(jī)制.

          Net
          Net 是一個(gè)網(wǎng)絡(luò)工具集,基于 NetComponents 代碼,包括 FTP 客戶端等等。

          Pool
          Commons-Pool 提供了通用對象池接口,一個(gè)用于創(chuàng)建模塊化對象池的工具包,以及通常的對象池實(shí)現(xiàn).

          Primitives
          Commons-Primitives提供了一個(gè)更小,更快和更易使用的對Java基本類型的支持。當(dāng)前主要是針對基本類型的 collection。.

          Validator
          The commons-validator提供了一個(gè)簡單的,可擴(kuò)展的框架來在一個(gè)XML文件中定義校驗(yàn)器 (校驗(yàn)方法)和校驗(yàn)規(guī)則。支持校驗(yàn)規(guī)則的和錯(cuò)誤消息的國際化。

          10:20 | 評論 (0)

          2005年3月17日

          JAR 文件就是 Java Archive File,是 Java 的文檔格式。JAR 文件非常類似 ZIP 文件——準(zhǔn)確的說,它就是 ZIP 文件,所以叫它文件包。JAR 文件與 ZIP 文件唯一的區(qū)別就是在 JAR 文件的內(nèi)容中,包含了一個(gè) META-INF/MANIFEST.MF 文件,這個(gè)文件是在生成 JAR 文件的時(shí)候自動創(chuàng)建的。

          創(chuàng)建可運(yùn)行的 JAR 文件包 
          制作一個(gè)可執(zhí)行的 JAR 文件包來發(fā)布你的程序是 JAR 文件包最典型的用法。 創(chuàng)建可執(zhí)行的 JAR 文件包,需要使用帶 cvfm 參數(shù)的 jar 命令,以 Example 目錄為例,命令如下: 

          jar cvfm Example.jar manifest.mf Example 

          這里 Example.jar 和 manifest.mf 兩個(gè)文件,分別是對應(yīng)的參數(shù) f 和 m,其重點(diǎn)在 manifest.mf。因?yàn)橐獎(jiǎng)?chuàng)建可執(zhí)行的 JAR 文件包,光靠指定一個(gè) manifest.mf 文件是不夠的,因?yàn)?nbsp;MANIFEST 是 JAR 文件包的特征,可執(zhí)行的 JAR 文件包和不可執(zhí)行的 JAR 文件包都包含 MANIFEST。關(guān)鍵在于可執(zhí)行 JAR 文件包的 MANIFEST,其內(nèi)容包含了 Main-Class 一項(xiàng)。這在 MANIFEST 中書寫格式如下: 
          Main-Class: 可執(zhí)行主類全名(包含包名) 

          例如,假設(shè) HelloWorld.class 是屬于 Examples包的,而且是可執(zhí)行的類 (定義了 public static void main(String[]) 方法),那么這個(gè) manifest.mf 可以編輯如下: 
          Main-Class: Example.HelloWorld <回車> 

          這個(gè) manifest.mf 可以放在任何位置,也可以是其它的文件名,只需要有 Main-Class: test.Test 一行,且該行以一個(gè)回車符結(jié)束即可。使用 jar 命令創(chuàng)建 JAR 文件包之后,這個(gè) Example.jar 就是執(zhí)行的 JAR 文件包。運(yùn)行時(shí)只需要使用 java -jar test.jar 命令即可。 
          需要注意的是,創(chuàng)建的 JAR 文件包中需要包含完整的、與 Java 程序的包結(jié)構(gòu)對應(yīng)的目錄結(jié)構(gòu),而 Main-Class 指定的類,也必須是完整的、包含包路徑的類名,如上例的 Example.HelloWorld。 
            

          15:43 | 評論 (0)

          2005年3月11日

          草稿中。。

          13:50 | 評論 (0)

          在現(xiàn)實(shí)世界中的系統(tǒng)經(jīng)常不得不同時(shí)處理多個(gè)客戶端請求。在這樣的一個(gè)典型的多線程的系統(tǒng)中,不同的線程將處理不同的客戶端。一個(gè)常見的區(qū)分每個(gè)客戶端所輸出的Logging的方法是為每個(gè)客戶端實(shí)例化一個(gè)新的獨(dú)立的Logger。這導(dǎo)致Logger的大量產(chǎn)生,管理的成本也超過了logging本身。
           
          嵌套診斷環(huán)境NDC 
          在多用戶并發(fā)的環(huán)境下,通常是由不同的線程分別處理不同的客戶端請求。此時(shí)要在日志信息中區(qū)分出不同的客戶端,區(qū)分兩個(gè)客戶的日志輸出的常用方法是單獨(dú)為每個(gè)客戶端實(shí)例化新類別。但是,該方法會增加類別數(shù)量,并增加日志記錄的管理開銷。

          Log4J巧妙地使用了Neil Harrison提出的“NDC(嵌套診斷環(huán)境)”機(jī)制來解決這個(gè)問題。Neil Harrison(請參閱參考資料)想出了一個(gè)簡便方法,可以唯一標(biāo)記從同一個(gè)客戶機(jī)交互啟動的每一個(gè)日志記錄請求。Log4J為同一類別的線程生成一個(gè)Logger,多個(gè)線程共享使用,而它僅在日志信息中添加能夠區(qū)分不同線程的信息,該信息可能是發(fā)出請求的主機(jī)名、IP地址或其它任何可以用于標(biāo)識該請求的信息。這樣,由于不同的客戶端處理線程具有不同的NDC堆棧,即使這個(gè)Servlet同時(shí)生成多個(gè)線程處理不同的請求,這些日志信息仍然可以區(qū)分出來,就好像Log4J為每一個(gè)線程都單獨(dú)生成了一個(gè)Logger實(shí)例一樣。

          在Log4J中是通過org.apache.log4j.NDC實(shí)現(xiàn)這種機(jī)制的。使用NDC的方法也很簡單,步驟如下: 
          1. 在進(jìn)入一個(gè)環(huán)境時(shí)調(diào)用NDC.push(String),然后創(chuàng)建一個(gè)NDC; 
          2. 所做的日志操作輸出中包括了NDC的信息; 
          3. 離開該環(huán)境時(shí)調(diào)用NDC.pop方法; 
          4. 當(dāng)從一個(gè)線程中退出時(shí)調(diào)用NDC.remove方法,以便釋放資源。 

          下面是一個(gè)模擬記錄來自不同客戶端請求事件的例子,代碼如下: 

          import org.apache.log4j.Logger;
          import org.apache.log4j.NDC;
          public class TestNDC {
           static Logger log = Logger.getLogger(TestNDC.class.getName());
           public static void main(String[] args) {
            log.info("Make sure %x is in your layout pattern!");
            // 從客戶端獲得IP地址的例子
            String[] ips = {"192.168.0.10","192.168.0.27"};
            for (int i = 0; i  {
             // 將IP放進(jìn) NDC中
             NDC.push(ips[i]);
             log.info("A NEW client connected, who's ip should appear in this log message.");
             NDC.pop();
            }
            NDC.remove();
            log.info("Finished.");
           }
          }


          注意配置文件中的布局格式中一定要加上%x。系統(tǒng)輸出如下: 
          INFO   - Make sure %x is in your layout pattern!
          INFO  192.168.0.10 - A NEW client connected, who's ip should appear in this log 
          message.
          INFO  192.168.0.27 - A NEW client connected, who's ip should appear in this log 
          message.
          INFO   - Finished.

          在Web應(yīng)用中使用 
          在Web應(yīng)用中,應(yīng)該在哪兒對Log4J進(jìn)行配置呢?首先要明確,Log4J必須在應(yīng)用的其它代碼執(zhí)行前完成初始化。因?yàn)镾ervlet是在Web服務(wù)器啟動時(shí)立即裝入的,所以,在Web應(yīng)用中一般使用一個(gè)專門的Servlet來完成Log4J的配置,并保證在web.xml的配置中,這個(gè)Servlet位于其它Servlet之前。下面是一個(gè)例子,代碼如下: 

          package org.javaresearch.log4j;
          import java.io.*;
          import javax.servlet.*;
          import org.apache.log4j.*;
          public class Log4JInit extends HttpServlet {
           public void init() throws ServletException {
            String prefix = getServletContext().getRealPath("/");
            String file = getServletConfig().getInitParameter("log4j-config-file");
            // 從Servlet參數(shù)讀取log4j的配置文件 
            if (file != null) {
             PropertyConfigurator.configure(prefix + file);
            }
           }
           public void doGet(HttpServletRequest request,HttpServletResponse response)throws 
          IOException, ServletException {}
           public void doPost(HttpServletRequest request,HttpServletResponse response)throws 
          IOException, ServletException {}
          }


            log4jinit 
             org.javaresearch. log4j.Log4JInit        
             
              log4j-config-file  
             /properties/log4j.properties 
             

             1
            


          注意:上面的load-on-startup應(yīng)設(shè)為1,以便在Web容器啟動時(shí)即裝入該Servlet。log4j.properties文件放在根的properties子目錄中,也可以把它放在其它目錄中。應(yīng)該把.properties文件集中存放,這樣方便管理。 

          Use log4j in J2EE

              在J2EE 服務(wù)器中使用log4j包需要注意的是:1)基于J2EE服務(wù)器jar包加載機(jī)制的特殊性,必須將log4j的jar包拷貝到%JAVAHOME\jre\lib\ext\目錄下。僅僅放到CLASSPATH中是不起作用的。2)因?yàn)镴2EE服務(wù)器對文件操作進(jìn)行了嚴(yán)格的控制,所以Log文件時(shí)只能寫到%J2EE_HOME%\logs目錄下,除非修改server.policy文件指定別的可寫目錄。下面我舉這個(gè)很簡單的例子說明一下如何在J2EE服務(wù)器中使用上log4j開發(fā)工具包,例子中涉及的文件如下:

          bonus.html



          Bonus Calculation


          ACTION="BonusAlias">


          Enter social security Number:




          Enter Multiplier:











          上面的bonus.html接受用戶輸入的社會保險(xiǎn)號和投保金額。
          BonusServlet.java
          import javax.servlet.*;
          import javax.servlet.http.*;
          import java.io.*;
          import javax.naming.*;
          import javax.rmi.PortableRemoteObject;
          import Beans.*;
          public class BonusServlet extends HttpServlet {
          CalcHome homecalc;
          public void init(ServletConfig config)
          throws ServletException{
          //Look up home interface
          try{
          InitialContext ctx = new InitialContext();
          Object objref = ctx.lookup("calcs");
          homecalc =(CalcHome)PortableRemoteObject.narrow(
          objref,CalcHome.class);
          } catch (Exception NamingException) {
          NamingException.printStackTrace();
          }
          }
          public void doGet (HttpServletRequest request,HttpServletResponse response)
          throws ServletException, IOException {
          String socsec = null;
          int multiplier = 0;
          double calc = 0.0;
          PrintWriter out;
          response.setContentType("text/html");
          String title = "EJB Example";
          out = response.getWriter();
          out.println("");
          try{
          Calc theCalculation;
          //Get Multiplier and Social Security Information
          String strMult = request.getParameter("MULTIPLIER");
          Integer integerMult = new Integer(strMult);
          multiplier = integerMult.intValue();
          socsec = request.getParameter("SOCSEC");
          //Calculate bonus
          double bonus = 100.00;
          theCalculation = homecalc.create();
          calc = theCalculation.calcBonus(multiplier, bonus);
          } catch(Exception CreateException){
          CreateException.printStackTrace();
          }
          //Display Data
          out.println("

          Bonus Calculation

          ");
          out.println("

          Soc Sec: " + socsec + "

          ");
          out.println("

          Multiplier: " + multiplier + "

          ");
          out.println("

          Bonus Amount: " + calc + "

          ");
          out.println("");
          out.close();
          }
          public void destroy() {
          System.out.println("Destroy");
          }
          }


          BonusServlert.java得到從bonus.html中傳過來的社會保險(xiǎn)號和金額,并調(diào)用EJB程序?qū)?shù)據(jù)進(jìn)行處理并將結(jié)果顯示給客戶端。

          EJB 的Home接口:

          package Beans;
          import java.rmi.RemoteException;
          import javax.ejb.CreateException;
          import javax.ejb.EJBHome;
          public interface CalcHome extends EJBHome {
          Calc create() throws CreateException,RemoteException;
          }

          EJB 的Remote 接口:
          package Beans;
          import javax.ejb.EJBObject;
          import java.rmi.RemoteException;
          public interface Calc extends EJBObject {
          public double calcBonus(int multiplier,double bonus)
          throws RemoteException;
          }

          EJB 的業(yè)務(wù)處理邏輯:
          package Beans;
          import java.rmi.RemoteException;
          import javax.ejb.SessionBean;
          import javax.ejb.SessionContext;
          public class CalcBean implements SessionBean {
          public double calcBonus(int multiplier,double bonus) {
          double calc = (multiplier*bonus);
          return calc;
          }
          //These methods are described in more
          //detail in Lesson 2
          public void ejbCreate() { }
          public void setSessionContext(
          SessionContext ctx) { }
          public void ejbRemove() { }
          public void ejbActivate() { }
          public void ejbPassivate() { }
          public void ejbLoad() { }
          public void ejbStore() { }
          }

              成功發(fā)布后就可以在代碼中加入Log4j的測試代碼了。想詳細(xì)了解上面的應(yīng)用程序的發(fā)布步驟請叁照我最近寫的一篇文章“Say ‘Hello World’ to EJB”。接下來我們在EJB中使用Log4j包(由于Servlet 中使用Log4j的方法和前面提到的例子中的使用方法相同,這里不在重復(fù))。
          1. 首先在EJB的Remote接口中增加名為logtest的方法聲明:
          package Beans;
          import javax.ejb.EJBObject;
          import java.rmi.RemoteException;
          public interface Calc extends EJBObject {
          public double calcBonus(int multiplier,double bonus)
          throws RemoteException;
          public void logtest() throws RemoteException;
          }

          2.在 EJB的業(yè)務(wù)處理Bean中實(shí)現(xiàn)logtest()方法:
          package Beans;
          import java.rmi.RemoteException;
          import javax.ejb.SessionBean;
          import javax.ejb.SessionContext;
          import org.apache.log4j.Category;
          import org.apache.log4j.Logger;
          import org.apache.log4j.*;
          import org.apache.log4j.NDC;

          public class CalcBean implements SessionBean {
          static Logger logger = Logger.getLogger(CalcBean.class.getName());
          public double calcBonus(int multiplier,double bonus) {
          logger.debug("Entering calcBeans() method"); 
          logtest();
          double calc = (multiplier*bonus);
          logger.debug("Exitint calcBeans() method");
          return calc;
          }
          public void logtest(){
          logger.debug("Enter logtest method");
          NDC.push("Client #45890"); 
          logger.debug("Exiting logtest method.");
          }
          //These methods are described in more
          //detail in Lesson 2
          public void ejbCreate() { 
          PropertyConfigurator.configure("F:/example.properties"); 
          }
          public void setSessionContext(
          SessionContext ctx) { }
          public void ejbRemove() { }
          public void ejbActivate() { }
          public void ejbPassivate() { }
          public void ejbLoad() { }
          public void ejbStore() { }
          }


          這里假設(shè)log配置文件為F:盤下的example.properties文件。
          接下來就是配置文件的設(shè)置問題了。
          Example.properties
          # Attach appender A1 to root. Set root level to Level.DEBUG.
          log4j.rootLogger=DEBUG, A1

          # A1 is set to be a FileAppender sending its output to
          # a log file. However, only error messages and above will be printed
          # in A1 because A1's threshold is set to Level.ERROR.

          # The fact that the root level is set to Prority.DEBUG only influences
          # log requests made to the root logger. It has no influence on the
          # *appenders* attached to root.
          # Appender A1 writes to the file "test" in J2EE's allow write DIR ex logs direstory.
          log4j.appender.A1=org.apache.log4j.FileAppender
          log4j.appender.A1.File=E:/j2sdkee1.3/logs/test.log

          # Truncate 'test' if it aleady exists.
          log4j.appender.A1.Append=false

          # Appender A1 uses the PatternLayout.
          log4j.appender.A1.layout=org.apache.log4j.PatternLayout
          log4j.appender.A1.layout.ConversionPattern=%5r %-5p [%t] %c{2} - %m%n
          # Set the level of the logger named "Beans.CalcBean" to 
          # Level.DEBUG(also INFO WARN ERROR etc.),auto attach appender A1.
          log4j.category.Beans.CalcBean=debug


          這樣重新發(fā)布這個(gè)EJB就回在%J2EE_HOME%\logs 目錄下生成名為test.log的log文件。

          13:48 | 評論 (0)

          2005年3月1日

          背景
          對于有經(jīng)驗(yàn)的開發(fā)者來說,日志記錄的重要性顯而易見。例如程序中的異常處理和安全性都依賴于Logging的功能來幫助履行它們的指責(zé)。應(yīng)用程序中的日志記錄主要基于三個(gè)目的:監(jiān)視代碼中變量的變化情況,周期性的記錄到文件中供其他應(yīng)用進(jìn)行統(tǒng)計(jì)分析工作;跟蹤代碼運(yùn)行時(shí)軌跡,作為日后審計(jì)的依據(jù);擔(dān)當(dāng)集成開發(fā)環(huán)境中的調(diào)試器的作用,向文件或控制臺打印代碼的調(diào)試信息。經(jīng)驗(yàn)表明日志記錄是開發(fā)周期中的重要組成部分。

          最簡單的做法就是在代碼中嵌入許多的打印語句,但是這樣打印語句會充斥代碼的主體,顯然不是一個(gè)好方法。因此,使用成熟的框架例如Log4j,則會更具靈活性。

          Log4j簡介
          Log4j 框架是用 Java 語言編寫的標(biāo)準(zhǔn)日志記錄框架。作為 Jakarta 項(xiàng)目的一部分,它在 Apache 軟件許可證(Apache Software License)下分發(fā),以速度和靈活性為中心概念:Log4j 環(huán)境是完全可配置的,通過使用Log4j,我們可以控制日志信息輸送的目的地是控制臺、文件、GUI組件、甚至是套接口服務(wù)器、NT的事件記錄器、UNIX Syslog守護(hù)進(jìn)程等;我們也可以控制每一條日志的輸出格式;通過定義每一條日志信息的級別,我們能夠更加細(xì)致地控制日志的生成過程。

          Log4j由三個(gè)重要的部件構(gòu)成:記錄器(Loggers)、輸出源(Appenders)和布局(Layouts)。

          記錄器按照布局中指定的格式把日志信息寫入一個(gè)或多個(gè)輸出源。輸出源可以是控制臺、文本文件、XML文件或Socket,甚至還可以把信息寫入到Windows事件日志或通過電子郵件發(fā)送。我們可以通過配置文件來部署這些組件。

          其實(shí)您也可以完全不使用配置文件,而是在代碼中配置Log4j環(huán)境。但是,使用配置文件將使您的應(yīng)用程序更加靈活。本文從描述 log4j 體系結(jié)構(gòu)的主要組件著手。然后是描述基本用法和配置的簡單示例。

          定義配置文件
          Log4j支持兩種配置文件格式,一種是XML格式的文件,一種是Java特性文件(鍵=值)。下面我們介紹使用Java特性文件做為配置文件的方法:

          一、 配置記錄器。

          Log4j允許程序員定義多個(gè)記錄器,每個(gè)記錄器有自己的名字。但有一個(gè)記錄器叫根記錄器,它永遠(yuǎn)存在,且不能通過名字檢索或引用,在配置文件中,可以如下定義根記錄器:

            log4j.rootLogger = [ level ] , appenderName, appenderName, … 

          Level是記錄器的級別,它是日志記錄的優(yōu)先級,分為OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定義的級別。Log4j建議只使用四個(gè)級別:ERROR、WARN、INFO、DEBUG:

            DEBUG  <  INFO  <  WARN  <  ERROR  <  FATAL

          右邊的級別比左邊的高。如果一條log信息的級別,大于等于記錄器的級別值,那么記錄器就會記錄它。例如level被設(shè)置為INFO級別,那么應(yīng)用程序中所有的DEBUG的日志信息將不被打印出來。通過在這里定義的級別,您可以控制到應(yīng)用程序中相應(yīng)級別的日志信息的開關(guān)。

           appenderName是輸出源的名字,它指定日志信息輸出到哪個(gè)地方。您可以為一個(gè)記錄器指定多個(gè)輸出源。

          在一些配置文件中,你可能會看到下面的語句:

            log4j.rootCategory = [ level ] , appenderName, appenderName, … 

          在早期的Log4j版本中,org.apache.Category實(shí)現(xiàn)了記錄器的功能,為了提高向后兼容性,Logger擴(kuò)展了Category,因此rootCategory和rootLogger是可以互換的,但最后Category將從類庫中刪除,因此請使用Logger類。

          除了根記錄器之外,log4j允許程序員定義多個(gè)記錄器,每個(gè)記錄器有自己的名字:

            log4j.logger.loggerName = [ level ] , appenderName, appenderName, … 

          在Log4J中Logger是具有層次關(guān)系的,Log4j支持配置的記錄器之間的“父子關(guān)系”,記錄器之間通過名字來表明隸屬關(guān)系(或家族關(guān)系),它們有一個(gè)共同的根,位于最上層,其它Logger遵循類似包的層次:記錄器a.b,與記錄器a.b.c之間是父子關(guān)系,而記錄器a與a.b.c之間是祖先與后代的關(guān)系。例如:

              static Logger root = Logger.getRootLogger();
                 static Logger log1 = Logger.getLogger("cc");
                 static Logger log2 = Logger.getLogger("cc.ejb");
                 static Logger log3 = Logger.getLogger("cc.ejb.my.TestApp");
           
          上面代碼中,log1是log2的父親,是log3的祖先,而root是所有l(wèi)og1、log2、log3的祖先,它們都從root中繼承。所以,一般情況下,僅需要配置好rootLogger,其它子記錄器都會從中繼承rootLogger的配置。如果修改了rootLogger的配置,其它所有的子記錄器也會繼承這種變化。這樣就大大地方便了配置。
           
          如果一個(gè)應(yīng)用中包含了上千個(gè)類都需要日志,那么我們是否需要配置上千個(gè)Logger呢?我們通過一個(gè)簡單的辦法來解決這個(gè)問題: 用每一個(gè)java類文件名(包含該類的包名)定義一個(gè)記錄器,這是一種有用并且直觀的記錄器實(shí)例名的定義方式。例如在配置文件中定義了一個(gè)com.foo的記錄器:
            log4j.logger.com.foo=WARN
          在com.foo中的一個(gè)java類bar,我們通過其本類的名字獲得一個(gè)記錄器“com.foo.Bar”:

          package com.foo;
          class Bar{
          static Logger log=Logger.getLogger(bar.Class.getName());
          .....
          }

          由于記錄器com.foo.Bar 沒有指定的級別,它從com.foo(在配置文件中其級別設(shè)置成WARN) 繼承級別。并且這樣我們就能方便的從大量log信息中判斷出它們各自的來源。當(dāng)然了,這不是硬性規(guī)定的,實(shí)際上Log4j沒有對設(shè)置記錄器的實(shí)例名做什么限制,程序員可以根據(jù)自己的喜好隨意定義。

          二、日志信息輸出源Appender
          log4j 還允許日志記錄請求打印到多個(gè)輸出目的地,按 log4j 的叫法是輸出源。一個(gè)記錄器可以有多個(gè)輸出源。一條log信息如果可被這個(gè)記錄器處理,則該記錄器會把這條信息送往每個(gè)它所擁有的輸出源,以及層次結(jié)構(gòu)中更高級的輸出源。例如,根記錄器以控制臺作為輸出源,則所有可被紀(jì)錄的日志都將至少打印到控制臺。

          配置日志信息輸出源,其語法為:

            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)生一個(gè)日志文件)
          • org.apache.log4j.RollingFileAppender(文件大小到達(dá)指定尺寸的時(shí)候產(chǎn)生一個(gè)新的文件) 
          • org.apache.log4j.WriterAppender(將日志信息以流格式發(fā)送到任意指定的地方) 
          • org.apache.log4j.SocketAppender (Socket)
          • org.apache.log4j.NtEventLogAppender   (NT的Event Log) 
          • org.apache.log4j.JMSAppender   (電子郵件)

          請注意,可以通過覆蓋缺省行為,這樣就不再附加累積的輸出源:

            log4j.additivity.loggerName=false

          注意,不要把一個(gè)輸出源附加到多個(gè)記錄器上,否則會得到“Attempted to append to closed appender named xxx”的信息。


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

            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)生的時(shí)間、線程、類別等等信息)

          如果采用了PatternLayout, 則Log4J采用類似C語言中的printf函數(shù)的打印格式格式化日志信息,打印參數(shù)如下:

          • %m 輸出代碼中指定的消息
          • %p 輸出優(yōu)先級,即DEBUG,INFO,WARN,ERROR,F(xiàn)ATAL 
          • %r 輸出自應(yīng)用啟動到輸出該log信息耗費(fèi)的毫秒數(shù) 
          • %c 輸出所屬的類目,通常就是所在類的全名 
          • %t 輸出產(chǎn)生該日志事件的線程名 
          • %n 輸出一個(gè)回車換行符,Windows平臺為“\r\n”,Unix平臺為“\n”
          • %d 輸出日志時(shí)間點(diǎn)的日期或時(shí)間,默認(rèn)格式為ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},輸出類似:2002年10月18日 22:10:28,921 
          • %l 輸出日志事件的發(fā)生位置,包括類目名、發(fā)生的線程,以及在代碼中的行數(shù)。舉例:Testlog4.main(TestLog4.java:10) 

          四、例子
          下面是一個(gè)完整的Log4j配置文件,這個(gè)配置文件指定了兩個(gè)輸出源stdout和R。前者把日志信息輸出到控制臺,后者是一個(gè)輪轉(zhuǎn)日志文件。最大的文件是100KB,當(dāng)一個(gè)日志文件達(dá)到最大尺寸時(shí),Log4J會自動把example.log重命名為example.log.1,然后重建一個(gè)新的example.log文件,依次輪轉(zhuǎn)。

          log4j.rootLogger=debug, stdout, R

          log4j.appender.stdout=org.apache.log4j.FileAppender
          log4j.appender.stdout.File=System.out
          log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

          # Pattern to output the caller's file name and line number.
          log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

          log4j.appender.R=org.apache.log4j.RollingFileAppender
          log4j.appender.R.File=example.log

          log4j.appender.R.MaxFileSize=100KB
          # Keep one backup file
          log4j.appender.R.MaxBackupIndex=1

          log4j.appender.R.layout=org.apache.log4j.PatternLayout
          log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n

          log4j.logger.cc.ejb.my=error,out

          log4j.appender.out=org.apache.log4j.ConsoleAppender
          log4j.appender.out.layout=org.apache.log4j.PatternLayout
          log4j.appender.out.layout.ConversionPattern=%p %t %c - %m%n

          log4j.logger.cc.ejb.my.son=debug
          log4j.additivity.cc.ejb.my.son=false

          在代碼中使用Log4j 

          一、得到記錄器
          使用Log4j,第一步就是獲取日志記錄器,這個(gè)記錄器將負(fù)責(zé)控制日志信息。其語法為: 

            public static Logger getLogger( String name) 

          通過指定的名字獲得記錄器,如果必要的話,則為這個(gè)名字創(chuàng)建一個(gè)新的記錄器。Name一般取本類的名字,比如: 

            static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () )

          二、讀取配置文件 
          當(dāng)獲得了日志記錄器之后,第二步將配置Log4j環(huán)境,其語法為:

            BasicConfigurator.configure (): 自動快速地使用缺省Log4j環(huán)境。
            PropertyConfigurator.configure ( String configFilename) :讀取使用Java的特性文件編寫的配置文件。
            DOMConfigurator.configure ( String filename ) :讀取XML形式的配置文件。

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

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

          四、例子

          我們通過下面這個(gè)簡單的例子,來演示在程序如何使用Log4j,您可以修改配置文件以得到不同日志信息。

          package cc.ejb.my;
          import org.apache.log4j.Logger;
          import org.apache.log4j.PropertyConfigurator;
          import my.son.Foo;
          public class TestApp {

              static Logger logger=Logger.getLogger(TestApp.class.getName());

              public static void main(String[] args) {
                 
                  PropertyConfigurator.configure("log4j.properties");
                  logger.info("Applcaiton Starts");
                  logger.warn("Bar Starts");
                  Bar bar=new Bar();
                  logger.error("Bar Errors");
                  bar.doIt();
                  logger.warn("Bar  Exits");
                  logger.info("Foo Starts");
                  Foo foo=new Foo();
                  logger.error("Foo Errors");
                  foo.doit();
                  logger.warn("Foo exits ");
                  logger.info("Applcaition Exits");
                 
              }

          }

          class Bar
          {
              static Logger logger = Logger.getLogger(Bar.class.getName());
              public void doIt() {
                logger.debug("Did it again!");
              }
            }

          package cc.ejb.my.son;

          import org.apache.log4j.Logger;

          public class Foo {
              private Logger log=Logger.getLogger(Foo.class.getName());
              public Foo() {
                  log.info("Foo Initialzie");
              }
              public void doit()
              {
                  log.debug("Do it in Foo");
              }

          }


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


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 丘北县| 台前县| 乌拉特前旗| 广饶县| 武强县| 苍溪县| 遂平县| 卓尼县| 鄂尔多斯市| 浮山县| 华坪县| 大厂| 望江县| 乌拉特后旗| 慈溪市| 司法| 墨竹工卡县| 吕梁市| 贞丰县| 甘谷县| 福泉市| 尉氏县| 泽州县| 苗栗市| 遂平县| 乡宁县| 小金县| 上高县| 九龙县| 和龙市| 织金县| 忻州市| 高陵县| 阳原县| 东港市| 岐山县| 建水县| 聂荣县| 南江县| 西安市| 阿勒泰市|