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ò)誤消息的國際化。
創(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。
嵌套診斷環(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.htmlBonus 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文件。
背景
對于有經(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");
log4j.logger.com.foo=WARN
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%nlog4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=example.loglog4j.appender.R.MaxFileSize=100KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=1log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%nlog4j.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%nlog4j.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");
}}