Struts中使用Log4j

在应用程序中输出日志有三个目的:

监视代码中变量的变化情况,把数据周期性地记录到文件中供其他应用进行统计分析工作。

跟踪代码运行时轨迹,作为日后审计的依据。

担当集成开发环境中的调试器,向文件或控制台打印代码的调试信息。

本章将介绍如何在Struts应用中使用Apache通用日志包,来输出各种级别的日志,并且控制日志的输出地点和输出格式。

Apache通用日志包概述

Apache通用日志包(Commons Logging Package)是Apache的一个开放源代码的项目,它提供了一组通用的日志接口,用户可以自由地选择实现日志接口的第三方软件。通用日志包目前支持以下日志实现:

Log4j日志器(下载地址: http://jakarta.apache.org/log4j)

JDK1.4Logging日志器(在JDK1.4中自带了该日志器)

SimpleLog日志器(把日志消息输出到标准的系统错误流System.err)

NoOpLog日志器(不输出任何日志消息)

通用日志包中的两个常用接口为LogFactory和Log,下面分别介绍它们的用法。

 

Log接口

通用日志包把日志消息分为6种级别:FATAL、ERROR、WARN、INFO、DEBUG和TRACE。其中FATAL级别最高,TRACE级别最低。通用日志包采用日志级别机制,可以灵活控制输出的日志内容。

org.apache.commons.logging.Log接口代表日志器,它提供了一组输出日志的方法:

fatal(Object message):输出FATAL级别的日志消息。

error(Object message):输出ERROR级别的日志消息。

warn(Object message):输出WARN级别的日志消息。

info(Object message):输出INFO级别的日志消息。

debug(Object message):输出DEBUG级别的日志消息。

trace(Object message):输出TRACE级别的日志消息。

对于以上输出日志的方法,只有当它输出日志的级别大于或等于日志器配置的日志级别时,这个方法才会被真正执行。例如,如果日志器的日志级别为WARN,那么在程序中,他的fatal()、error()和warn()方法会被执行,而info(),debug()和trace()方法不会被执行。

提示:如何指定日志器的日志级别,这依赖于具体的日志器实现。

Log接口还提供了一组判断是否允许输出特定级别的日志消息的方法:

isFatalEnabled()

isErrorEnabled()

isWarnEnabled()

isInfoEnabled()

isDebugEnabled()

isTraceEnabled()

在程序中输出某种级别的日志消息之前,提倡先调用以上方法来判断该级别的日志是否允许输出,这有助于提高应用的性能。例如以下代码先把日志消息添加到StringBuffer中,最后在调用日志器的debug()方法输出日志:

StringBuffer buf = new StringBuffer();

buf.append(“Login Successfful -”);

buf.append(“Name:”);

buf.appand(userView.getFirstName());

buf.appand(“ ”);

buf.appand(userView.getLastName());

buf.appand(“-”);

buf.appand(“Email:”);

buf.appand(userView.getEmailAddress());

 

//Log the information for auditing purpose

log.debug(buf.toString());

 

对于以上代码,如果日志器实际上不允许输出DEBUG级别的日志,那么执行日志器的debug()方法不会输出任何消息,此时向StringBuffer中添加消息的一大串操作都将是多余的。为了提高性能,可以合理地使用isDebugEnabled()方法,避免应用执行多余到的操作:

if(log.isDebugEnabled()){

       StringBuffer buf = new StringBuffer();

buf.append(“Login Successfful -”);

buf.append(“Name:”);

buf.appand(userView.getFirstName());

buf.appand(“ ”);

buf.appand(userView.getLastName());

buf.appand(“-”);

buf.appand(“Email:”);

buf.appand(userView.getEmailAddress());

 

       //Log the information for auditing purpose

log.debug(buf.toString());

 

}

 

LogFactory接口

org.apache.commons.logging.LogFactory接口提供了获得日志器实例的两个静态方法:

public static Log getLog(String name)throws LogConfigurationException;

public static Log getLog(Class class)throws LogConfigurationException;

第一个getLog()方法以name参数作为日志器的名字;第二个getLog()方法以class参数指定的类的名字作为日志器的名字,以下是第二个getLog()方法的一种实现方式:

public static Log getLog(Class class)throws LogConfigurationException{

       //call getLog(String name)

       getLog(class.getName());

}

 

常用的日志实现

本节将介绍几种常用的日志实现:

NoOpLog日志器

SimpleLog日志器

Log4J日志器

NoOpLog日志器

在通用包中自带了org.apache.commons.logging.impl.NoOpLog日志实现类,它实现了Log接口,但是它的输出日志方法不执行任何操作:

public void trace(Object message){}

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){}

SimpleLog日志器

在通用日志包中自带了org。apache.commons.logging.impl.SimpleLog日志实现类,它实现了Log接口,它把日志消息输出到标准的系统错误流System.err,在SimpleLog初始化的过程中,从名为simplelog.properties的属性文件中读取以下属性:

org.apache.commons.logging.simplelog.defaultlog:为SimpleLog的所有实例设置默认的日志级别,可选值包括:fatal、error、warn、info、debug和tarce。如果没有设置这个属性,其默认值为info。

org.apache.commons.logging.simplelog.showSortLogname:如果为true,表示在输出的日志消息中应包含当前日志器实例的简写名字。默认值为true。

org.apache.commons.logging.simplelog.showdatatime:如果为true,表示在输出的日志消息中应包含当前时间信息。默认值为false。

SimpleLog将根据以上属性来控制日志输出级别和输出格式。在它的输出日志方法中,先判断是否允许输出该级别的日志,当判断结果为true时,才输出日志。以下是它的debug()方法的代码:

public final void debug(Object message){

       if(isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG)){

              log(SimpleLog.LOG_LEVEL_DEBUG, message, null);

       }

}

以上debug()方法先调用isLevelEnabled()方法来判断是否允许输出该级别的日志。以下是isLevelEnabled()方法的代码,其中currentLogLevel变量代表当前日志器的日志级别:

protected Boolean isLevelEnabled(int logLevel){

       //log level are numerically ordered so can use simple numeric

       //comparison

       return(logLevel >= currentLogLevle);

}

Log4J日志器

Log4J是Apache的一个开放源代码的项目,它是一个日志操作包。Log4J允许灵活的制定日志消息输出的目的地(如控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器和UNIX Syslog守护进程等),还可以控制每一条日志的输出格式。此外,通过定义日志消息的级别,能够非常细致的控制日志的输出。最令人感兴趣的是,这些功能可以通过一个配置文件来灵活的进行配置,而不需要修改应用程序的代码。

Log4J主要由三大组件构成:

Logger:负责生成日志,并根据配置的日志级别来决定什么日志消息应该被输出,什么日志消息应该被忽略。

Appender:定义日志消息输出的目的地,指定日志消息应该被输出到什么地方,这些地方可以是控制台、文件和网络设备等。

Layout:指定日志消息的输出格式。

这三个组件协同工作,使得开发者能够依据日志消息类别来输出日志,并能够在程序运行期间,控制日志消息的输出格式以及日志存放地点。

配置通用日志接口

在Web应用中使用通用日志包,首先需要进行以下配置:

准备有关的Jar文件

在commons-logging.properties属性文件中指定日志器(即日志实现类)

为特定的日志器设置日志级别、输出格式和输出地点等属性。

准备Jar文件

通用日志包的单独下载网址为: http://jakarta.apache.org/commons/logging/。包文件名为commons-logging.jar。如果Web应用中使用了通用日志接口,应该把commons-logging.jar文件复制到WEB-INF/lib目录下。

如果选用Tomcat5.0.24作为Web容器,则在<CATALINA_HOME>/bin目录下已经包含了commons-logging-api.jar文件,当Tomcat启动时,会自动加载这个文件中的类。因此可以不必把commons-logging.jar文件复制到web应用的WEB-INF/lib目录下。

commons-logging.jar文件只包含了SimpleLog和NoOpLog两种日志实现。如果Web应用采用了其他第三方的日志实现,如Log4J,则应该到Apache网站上单独下载它的包文件,把Log4J的JAR文件复制到WEB-INF/lib目录下。

指定日志器

通用日志日志接口从名为”commons-logging.properties”的属性文件中获取实现日志接口的日志器信息,这个文件位于WEB-INF/classes目录下。

在该文件中的“org.apache.commons.logging.Log”属性指定日志实现类。例如,如果日志实现类为SimpleLog,则配置代码如下:

org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog

在运行时,通用日志接口会检索commons-logging.properties文件,并且实例化由org.apache.commons.logging.Log属性指定的日志实现类。

如果采用Log4J日志器,只需重新设置org.apache.commons.logging.Log属性即可:

org.apche.commons.logging.Log=org.apache.commons.logging.impl.Log4JCategoryLog

设置日志器的属性

多数日志器都允许以配置的方式,指定日志的输出格式、地点或者级别等。下面讲述如何为SimpleLog设置属性。此外,由于配置Log4J的属性比较复杂,因此单独介绍Log4J的配置。

1.  配置SimpleLog日志器

如果采用SimpleLog作为日志器,那么其日志输出地点是固定的,为System.err,无需配置。可以在Simplelog.properties属性文件中设置其日志级别。例如以下代码指定SimpleLog的日志级别为info:

org.apache.commons.logging.simplelog.defaultlog=info

应该把simplelog.properties文件放在WEB-INF/classes目录下。

配置Log4J

Log4J由三个重要的组件构成:Logger、Appender和Layout。Log4J支持在程序中以编程方式设置这些组件,还支持通过配置文件来配置组件,而后一种方式更为灵活。

Log4J支持两种配置文件格式:一种是XML格式文件,一种是Java属性文件,采用键=值得形式。下面介绍如何以Java属性文件的格式来创建Log4J的配置文件。

配置Log4J的一般步骤

配置Log4J,需要分别设置它的Logger、Appender和Layout的属性。

配置Logger组件

Logger组件支持继承关系,所有的Logger组件都直接或间接继承rootLogger。配置rootLogger的语法为:

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

其中,priority是日志级别,可选值包括OFF,FATAL,ERROR,WARN,INFO,DEBUG,TRACE,ALL。通过在这里定义级别,可以控制应用程序中相应级别的日志消息的开关。比如在这里定义了INFO级别,则应用程序中所有的DEBUG和TRACE级别的日志消息将不被打印出来。

appenderName指定Appender组件,用户可以同时指定多个Appender组件。例如,以下代码指定rootLogger的日志级别为INFO,它有两个Appender,名为console和file:

log4j.rootLogger=INFO,console,file

配置Appender组件

配置日志消息输出目的地Appender,其语法为:

log4j.appender.appenderName=full.qualified.name.of.appender.class

log4j.appender.appenderName.option1=value1



log4j.appender.appenderName.optionN=valueN

Log4J提供的Appender有以下几种:

org.apache.log4j.ConsoleAppender(控制台)

org.apache.log4j.FileAppender(文件)

org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)

org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)

org.apache.log4j.WriterAppender(将日志消息以流格式发送到任意指定的地方)

例如,以下代码定义了一个名为file的Appender,它把日志消息输出到log.txt文件:

log4j.appender.file=org.apache.log4j.RollingFileAppender

log4j.appender.file.File=log.txt

配置Layout组件

配置Layout组件的语法为:

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

log4j.appender.appenderName.layout.option1=value1



log4j.appender.appenderName.layout.optionN=valueN

Log4J提供的Layout有以下几种:

org.apache.log4j.HTMLLayout(以HTML表格形式布局)

org.apache.log4j.PatternLayout(可以灵活地指定布局模式)

org.apache.log4j.SimpleLayout(包含日志消息的级别和信息字符串)

org.apahce.log4j.TTCCLayout(包含日志产生的时间、线程和类别等信息)

PatternLayout可以让开发者依照ConversionPattern去定义输出格式。ConversionPattern

有点像C语言的print打印函数,开发者可以通过一些预定义的符号来指定日志的内容和格式,这些符号的说明参见表19-1.

%r 自程序开始后消耗的毫秒数

%t 表示日志记录请求生成的线程

%p 表示日志语句的优先级别

%c 日志消息所在的类名

%m%n 表示日志消息的内容

例如,如果为名为file的Appender配置PatternLayout布局,则可以采用如下配置代码:

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

log4j.appender.file.layout.ConversionPattern=%t %p - %m%n

采用以上PatternLayout布局,从日志文件中看到输出日志的形式如下:

http8080-Processor24 INFO – This is an info message

在以上的日志内容中,%t对应http8080-Processor24, %p 对应INFO,%m%n对应后面具体的日志消息。

 

Log4J的配置样例

假定根据实际需要,要求程序中的日志消息既能输出到程序运行的控制台上,又能输出到指定的文件中,并且当日志消息输出到控制台时采用SimpleLayout布局,当日志消息输出到文件时采用PatternLayout布局,此时Logger,Appender和Layout这三个组件的关系如图所示。

根据如图所示创建如下名为log4j.properties的属性文件,该文件位于WEB-INF/classes目录下:

##LOGGERS##

#define a logger named helloAppLogger

log4j.rootLogger=INFO,console,file

 

##APPENDERS##

#define an appender named console, which is set to be a ConsoleAppender

log4j.appender.console=org.apache.log4j.ConsoleAppender

 

#define an appender named file, which is set to be a RollingFileAppender

log4j.appender.file=org.apache.log4j.RollingFileAppender

log4j.appender.file.File=log.txt

 

##LAYOUTS##

#assign a SimpleLayout to console appender

log4j.appender.console.layout=org.apache.log4j.SimpleLayout

 

#assign a Pattern Layout to file appender

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

log4j.appender.file.layout.ConversionPattern=%t %p - %m%n

以上配置代码指定rootLogger的日志级别为INFO,日志输出地点为控制台和log.txt文件。当日志输出到控制台时,采用SimpleLayout布局,当日志输出到文件时,采用PatternLayout布局。

Log4J对应用性能的影响

如果在程序运行中输出大量日志,显然会对应用性能造成一定的影响。Log4J对性能的影响程度取决于以下因素:

日志输出目的地:例如把日志输出到控制台的速度和输出到文件系统的速度是不一样的。

日志输出格式:例如采用SimpleLayout输出日志消息比采用Patternlayout简单,因此速度更快。

日志级别:日志级别设置得越低,输出的日志内容越多,对性能的影响越大。

在产品测试阶段,可以把日志级别设置得低一些,便于跟踪和调试程序,而在产品发布阶段,应该把日志级别设置得高一些。

在运用log4j时,应该充分考虑它对应用性能的影响,合理地配置log4J的各种属性。
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值