1.1描写properties文件。
这个描述文件一般放在可以放在两个地方:(1)WEB-INF/classes目录下,或者放在在/project_root/,也就是你的web_app的根目录下。利用这个控制日志纪录的配置,当然也可以通过xml文件配置,这里我们暂且说说properties的配置。
建立文件名log4j.properties文件。放在%tomca_home%/web_app/fcxtest/目录下。
文件内容如下:(fcxtest为自己建立的web app目录)

#--------------------------------
# 设定logger的root level为DEBUG,指定的输出目的地(appender)为A1
log4j.rootLogger=DEBUG, A1

# 设定调试信息的输出位置,此处设定输出为控制台
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# 设定调试信息的输出位置,此处设定输出为fcxtest.log文件
# log4j.appender.A1=org.apache.log4j.RollingFileAppender
# log4j.appender.A1.File=fcxtest.log
# log4j.appender.A1.MaxFileSize=1000KB

# 设定制定的A1使用的PatternLayout.
# 有关ConversionPattern中的转意字符的含义参考说明
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d %-5p [%t] %C{2} (%F:%L) - %m%n
#--------------------------------

1.2建立测试用的Servlet类
这个测试的com.fcxlog.LogShow类主要是显示如何使用log4j。

package com.fcxlog;

import javax.servlet.*;
import javax.servlet.http.*;

import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.PropertyConfigurator;

public class LogShow extends javax.servlet.http.HttpServlet{

protected String configfile = "log4j.properties";

public void init() throws ServletException{
ServletContext sct = getServletContext();
System.out.println("[Log4j]: The Root Path: " + sct.getRealPath("/"));
//指定自己的properties文件
//以前使用的是BasicConfigurator.configure(),现在使用PropertyConfigurator替代
org.apache.log4j.PropertyConfigurator.configure(sct.getRealPath("/") + configfile);
}

public void service(javax.servlet.http.HttpServletRequest req,javax.servlet.http.HttpServletResponse res){

//初始化Logger,以前使用Category,现在改用Logger替代
//org.apache.log4j.Category log = org.apache.log4j.Category.getInstance(LogShow.class);
org.apache.log4j.Logger log = ora.apache.log4j.Logger.getLogger(LogShow.class);
log.info("调试信息");

}
}

1.3 测试了
至于如何测试,发布,就不说了。

在此说明:
(1)本篇可能错误不少,一方面是参考《Short introduction to log4j》着翻译了一点,有诸多言辞不妥之处,还望指正。一方面,凭借自己的理解,所以难免有不全的地方,还望各位补充。
(2)因为时间有限,每天只能写一点,本文主要是介绍有关Logger及Logger level相关概念的
(3)有关Log4j介绍(一),请参阅:http://www.javaren.com/bbs/cgi-bin/topic.cgi?forum=1&topic=12766&show=0#lastviewpost


概述:
本文主要是简要的介绍了Log4j的api,以及其一些特征和设计原理。它本身是一个开源的软件,允许开发者任意的操纵应用系统日志信息。Log4j的使用通过外部配置文件进行配置。

任何大型应用系统都有其自己的系统日志管理或跟踪的API,所以在1996年的时候,E.U. SEMPER项目组(http://www.semper.org/)也开发其自己的日志管理API,后来经过无数次的修改和补充,发展成了现在的log4j,一个给予java的日志管理工具包。有关最新的版本信息和源码,请访问http://jakarta.apache.org/log4j/docs/index.html
把纪录语句放在代码之中,是一种低端的调试方法,不过有时却不得不说是很有效,也是必需的。毕竟很多时候,调试器并不见得很适用。特别是在多线程应用程序(multithread application)或分布式应用程序(distributed application)

经验告诉我们,在软件开发生命周期中,日志系统是一个非常重要的组件。当然,日志系统也有其自身的问题,过多的日志纪录会降低系统运行的速度。

(一)Log4j的三个重要组件?? Loggers, Appenders, Layouts

这三个组件协同的工作,使得开发者能够依据信息类别和级别去纪录信息,并能够运行期间,控制信息记录的方式已经日志存放地点。

(二)记录器层次(Logger hierarchy)

几乎任何纪录日志的API得功能都超越了简单的System.out.print语句。允许有选择控制的输出日志信息,也就是说,某的时候,一些日志信息允许输出,而另一些则不允许输出。这就假设日志纪录信息之间是有分别的,根据开发者自己定义的选择标准,可以对日志信息加以分类。

纪录器的命名是依据实体的。下面有一段有点绕口的解释,我就直抄了,各位可以看看:(Name Hierarchy)A logger is said to be an ancestor of another logger if its name followed by a dot is a prefix of the descendant logger name. A logger is said to be a parent of a child logger if there are no ancestors between itself and the descendant logger.
(形象的解释,比如存在记录器 a.b.c,记录器a.b,记录器a。那么a就是a.b的ancestor,而a.b就是a.b.c的parent,而a.b.c就是a.b的child)

根纪录器(root logger)是记录器层次的顶端。它有两个独特点:(1)总是存在的(2)能够被重新找回。可以通过访问类的静态方法 Logger.getRootLogger 重新得到。其他的纪录器通过访问静态方法 Logger.getLogger 被实例话或被得到,这个方法将希望获得的记录器的名称作为参数。一些Logger类的方法描述如下:
public class Logger {
// Creation & retrieval methods:
public static Logger getRootLogger();
public static Logger getLogger(String name);
// printing methods:
public void debug(Object message);
public void info(Object message);
public void warn(Object message);
public void error(Object message);
public void fatal(Object message);

// generic printing method:
public void log(Level l, Object message);
}

记录器被赋予级别,这里有一套预定的级别标准:DEBUG, INFO, WARN, ERROR and FATAL ,这些是在 org.apache.log4j.Level 定义的。你可以通过继承Level类定义自己的级别标准,虽然并不鼓励这么做。
如果给定的记录器没有被赋予级别,则其会从离其最近的拥有级别的ancestor处继承得到。如果ancestor也没有被赋予级别,那么就从根记录器继承。所以通常情况下,为了让所有的记录器最终都能够被赋予级别,跟记录器都会被预先设定级别的。比如我们在操作properties文件中,会写这么一句:log4j.rootLogger=DEBUG, A1 。实际上就这就指定了root Logger和root Logger level。

Appenders
Log4j允许记录信息被打印到多个输出目的地,一个输出目的地叫做Appender。目前的Log4j存在的输出目的地包括:控制台(Console),文件(File),GUI Componennt,Remote Socket Server,JMS,NT Event Logger,and Remote Unix Syslog daemons。
多个Appender可以绑定到一个记录器上(Logger)。

通过方法 addAppender(Logger.addAppender) 可以将一个Appender附加到一个记录器上。每一个有效的发送到特定的记录器的记录请求都被转送到那个与当前记录器所绑定的Appender上。(Each enabled logging request for a given logger will be forwarded to all the appenders in that logger as well as the appenders higher in the hierarchy),换句话说,Appender的继承层次是附加在记录器继承层次上的。举个例子:如果一个Console Appender被绑定到根记录器(root Logger),那么所有的记录请求都可以至少被打印到Console。另外,把一个file Appender绑定到记录器C,那么针对记录器C(或C的子孙)的记录请求都可以至少发送到Console Appender和file Appender。当然这种默认的行为方式可以跟改,通过设定记录器的additivity flag(Logger.setAdditivity)为false,从而可以使得Appender的不再具有可加性(Additivity)。
下面简要介绍一下Appender Additivity。

Appender Additivity:记录器C所记录的日志信息将被发送到与记录器C以及其祖先(ancestor)所绑定的所有Appender。
但是,如果记录器C的祖先,叫做P,它的additivity flag被设定为false。那么,记录信息仍然被发送到与记录器C及其祖先,但只到达P这一层次,包括P在内的记录器的所有Appender。但不包括P祖先的。
通常,记录器的additivity flag的被设置为true。


Layouts
这一块主要是介绍输出格式的。PatternLayout,Log4j标准的分配器,可以让开发者依照conversion patterns去定义输出格式。Conversion patterns有点像c语言的打印函数。
参看配置文件的java properties,如下面的两行:
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d %-5p [%t] %C{2} (%F:%L) - %m%n
第一行就指定了分配器,第二行则指定了输出的格式。
有关输出格式的定义可以参考/org/apache/log4j/PatternLayout.html
更基础的知识,可以到田贯升门诊室,另有一篇偏重基础的介绍~