Log4j
Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
一、配置log4j
文中的部分截图和配置代码取自最近接触到的一个工程,代码结构使用maven管理。
首先在项目目录下边建立log4j.properties文件,然后在里面配置相关属性,可看截图中的例子。下面详细解释一下相关属性配置。
1. 属性配置
1.1配置根rootLogger
语法:log4j.rootLogger = [level ] , appenderName, appenderName, …
案例:log4j.rootLogger = info, CONSOLE, errorFile
将等级为info的日志信息输出到CONSOLE和errorFile这两个目的地(目的地可以配置多个)。CONSOLE和errorFile的具体含义由下边的代码定义,名字随意定,比如console也可以叫stdout。
等级可分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL。Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。INFO级别,例如对于info级别只有等于及高于这个级别的才进行处理,则应用程序中所有DEBUG级别的日志信息将不被打印出来。通过定义的级别,可以控制到应用程序中相应级别的日志信息的开关。
OFF:不打出任何信息;
INFO:只显示INFO、WARN、ERROR的log信息;
DEBUG:信息不会被显示
1.2配置日志信息输出目的地(以console为例)
1.2.1 定义console输出端的类型:
Appender 负责控制日志记录操作的输出。其语法为:
log4j.appender.appenderName =fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1 = value1
…
log4j.appender.appenderName.optionN = valueN
案例:log4j.appender.CONSOLE = org.apache.log4j.ConsoleAppender
类型有:
org.apache.log4j.ConsoleAppender(控制台),
org.apache.log4j.FileAppender(文件),
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
1.2.2 log4j.appender.CONSOLE.Threshold= INFO
1.2.3 log4j.appender.CONSOLE.Target= System.out
1.2.4 配置日志信息的格式(布局)Layoutlayout
Layout 负责格式化Appender的输出。
其语法为:
log4j.appender.appenderName.layout =fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1 =value1
…
log4j.appender.appenderName.layout.optionN =valueN
案例:log4j.appender.CONSOLE.layout = org.apache.log4j.PatternLayout
类型有:
org.apache.log4j.HTMLLayout(以HTML表格形式布局),
org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
1.2.5 使用pattern布局就要指定的打印信息的具体格式ConversionPattern
log4j.appender.CONSOLE.layout.ConversionPattern= [%-5p] %d{yyyy-MM-dd HH:mm:ss.SSS} method:%l%n%m%n
如果使用pattern布局就要指定的打印信息的具体格式ConversionPattern,打印参数如下:
%m 输出代码中指定的消息;
%M 输出打印该条日志的方法名;
%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL;
%r 输出自应用启动到输出该log信息耗费的毫秒数;
%c 输出所属的类目,通常就是所在类的全名;
%t 输出产生该日志事件的线程名;
%n 输出一个回车换行符,Windows平台为"rn”,Unix平台为"n”;
%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyyy-MM-ddHH:mm:ss,SSS},输出类似:2002-10-18 22:10:28,921;
%l 输出日志事件的发生位置,及在代码中的行数;
[QC]是log信息的开头,可以为任意字符,一般为项目简称。
蓝色的代码含义参照上文
log4j.appender.errorFile= org.apache.log4j.DailyRollingFileAppender
log4j.appender.errorFile.File= /iflytek/sgy/qlsp/qlsp_schedule_error.log
log4j.appender.errorFile.DatePattern= '.'yyyy-MM-dd
log4j.appender.errorFile.Threshold= ERROR
##log4j.appender.dailyFile.Append=true
log4j.appender.errorFile.layout= org.apache.log4j.PatternLayout
log4j.appender.errorFile.layout.ConversionPattern= [%-5p] %d{yyyy-MM-dd HH:mm:ss.SSS}
1.2.6 使用log4j显示其他信息,只要将log4j.logger.后的内容换为自己使用的包名即可:
例1:使用log4j显示quartz的info信息
log4j.logger.org.quartz=INFO
例2:使用log4j显示数据库连接等的debug信息
log4j.logger.java.sql.Connection = debug
log4j.logger.java.sql.Statement = debug
log4j.logger.java.sql.PreparedStatement = debug
log4j.logger.java.sql.ResultSet = debug
例3. 配置spring的包
log4j.logger.org.springframework=DEBUG
例4.配置hibernate的包
log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN
log4j.logger.org.hibernate=DEBUG
1.3 如何定义及获取不同层次的记录器
任何一个记录器的使用都有两个步骤:
1.3.1在配置文件中定义相应的记录器。
在配置文件中定义记录器的格式有两种
定义根记录器的格式为
log4j.rootLogger = [ level ], appendName1,appendName2, …appendNameN
定义一个非根记录器的格式为
log4j.logger.loggerName1 = [ level ],appendName1,…appendNameN
……
log4j.logger.loggerNameM = [ level ],appendName1, …appendNameN
我们可以定义任意个非根记录器。
1.3.2 在代码中调用Logger类的取得记录器方法取得相应的记录器对象。
要取得根记录器对象可通过Logger.getRootLogger()函数,要取得非根记录器可通过Logger.getLogger()函数。
2.在代码中的具体使用(项目管理工具使用maven)
2.1 在javaSE中
1.引入 包
2.复制或者自己写一个 log4j.properties文件
3.在类中的使用:
1、导入所有需的commons-logging类:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
2、在自己的类中定义一个org.apache.commons.logging.Log类的私有类成员:
private Logger logger =LoggerFactory.getLogger(this.getClass());
参数使用的是当前类的class。
3、输出日志信息:
logger.info("+++++++++++++++++++++++++++");
其他的Logger方法:
1 publicvoid debug(Object message)
这种方法打印使用 Level.DEBUG 消息级别
2 publicvoid error(Object message)
这种方法打印使用 Level.ERROR 消息级别
3 publicvoid fatal(Object message);
这种方法打印使用 Level.FATAL 消息级别
4 publicvoid info(Object message);
这种方法打印使用 Level.INFO 消息级别
5 publicvoid warn(Object message);
这种方法打印使用 Level.WARN 消息级别
6 publicvoid trace(Object message);
这种方法打印使用Level.TRACE消息级别
附一个网上down的代码事例:
package TestLog4j;
import org.apache.log4j.Logger;
importorg.apache.log4j.PropertyConfigurator;
import org.apache.log4j.Priority;
importTestLog4j.TestLog4j2.TestLog4j2;
public class TestLog4j
{
static Logger logger =Logger.getLogger(TestLog4j.class.getName());//(2)
public TestLog4j(){}
public static void main(String[]args)
{
//同时输出到控制台和一个文件的实例并实现了Logger的继承
PropertyConfigurator.configure("F:\\nepalon\\log4j2.properties");
logger.debug("Start of themain() in TestLog4j");
logger.info("Just testing a logmessage with priority set to INFO");
logger.warn("Just testing a logmessage with priority set to WARN");
logger.error("Just testing alog message with priority set to ERROR");
logger.fatal("Just testing alog message with priority set to FATAL");
logger.log(Priority.WARN,"Testing a log message use a alternate form");
logger.debug(TestLog4j.class.getName());
TestLog4j2 testLog4j2 = newTestLog4j2();//(1)
testLog4j2.testLog();
}
}
在类TestLog4j中我们调用了另一个类TestLog4j2,下面看一下类TestLog4j2的代码。
例4-b:
package TestLog4j.TestLog4j2;
import org.apache.log4j.Logger;
importorg.apache.log4j.PropertyConfigurator;
import org.apache.log4j.Priority;
public class TestLog4j2
{
static Logger logger =Logger.getLogger(TestLog4j2.class.getName());//(1)
public TestLog4j2(){}
public void testLog()
{
//同时输出到控制台和一个文件的实例
PropertyConfigurator.configure("F:\\nepalon\\log4j2.properties");
logger.debug("2Start of themain()");
logger.info("2Just testing alog message with priority set to INFO");
logger.warn("2Just testing alog message with priority set to WARN");
logger.error("2Just testing alog message with priority set to ERROR");
logger.fatal("2Just testing alog message with priority set to FATAL");
logger.log(Priority.DEBUG,"Testing a log message use a alternate form");
logger.debug("2End of themain()");
}
}
log4j2.properties文件内容:
log4j.rootLogger = debug, stdout,R
log4j.logger.TestLog4j= , R
log4j.logger.TestLog4j.TestLog4j2=WARN
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p[%t] (%F:%L) - %m%n
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=F:\\nepalon\\classes\\TestLog4j\\example.log
log4j.appender.R.MaxFileSize=100KB
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-ddhh:mm:ss}:%p %t %c - %m%n
2.2 servlet中的使用
importorg.apache.log4j.PropertyConfigurator;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
/**
* log4j.jar的初始化类,参考web.xml
*/
public class Log4jInit extendsHttpServlet
{
public void init()
{
//通过web.xml来动态取得配置文件
String prefix =getServletContext().getRealPath("/");
String file =getInitParameter("log4j-init-file");
// 如果没有给出相应的配置文件,则不进行初始化
if(file != null)
{
PropertyConfigurator.configure(prefix+file);//(1)
}
}
public void doGet(HttpServletRequestreq, HttpServletResponse res)
{}
}
下面来看一下这个Servlet在web.xml中的定义。
例5-b:
<servlet>
<servlet-name>log4j-init</servlet-name>
<servlet-class>TestLog4j.Log4jInit</servlet-class>
<init-param>
<param-name>log4j-init-file</param-name>
<param-value>sort.properties</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
因为log4j的初始化要在所有的log4j调用之前完成,所以在web.xml文件中,我们一定要把对应的Servlet定义的load-on-startup应设为1,以便在Web容器启动时即装入该Servlet。
完成了这两个步骤这后,我们就可以象在application开发中一样在web application任何地方应用log4j了。下面是在javabean中的应用的一个例子。
import org.apache.log4j.Logger;
public class InfoForm
{
static Logger logger =Logger.getLogger(InfoForm.class);
protected String title;
protected String content;
public InfoForm() {}
public void setTitle(Object value)
{
logger.debug("nepalon:title =" + title);
title = value;
}
public String getTitle()
{
logger.debug("nepalon:title =" + title);
return title;
}
public void setContent(String value)
{
content = value;
logger.debug("nepalon:content() = " + content);
}
public String getContent()
{
logger.debug("nepalon: content= \n" + content);
return content;
}
}