Log4j 是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事 件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就 是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
如此强大的优越性,实际上手并不难,尤其在spring框架下,使用log4j更是容易,下面介绍一下spring下的log4j应用。
<一>如何配置日志环境
(1)在web工程冲导入log4j-xxx.jar
(2)在spring的配置文件web.xml加入如下配置
<!-- 配置日志监听器 -->
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>weChat.root</param-value>
</context-param>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j.properties</param-value><!--指定日志配置文件的所在位置-->
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
说明: 在上文的配置里,在上文的配置里,Log4jConfigListener会去WEB- INF/props/log4j.propeties 读取配置文件;
开一条watchdog线程每60秒扫描一下配置文件的变化(这样在web服务启动后再去修改配置文件也不用重新启动web服务了);
并把 web目录的路径压入一个叫webapp.root的系统变量(webapp.root将在log4j.properties文件中使用)。
(3)在项目中加入日志配置文件(放入上面配置中指定的位置)
log4j.properties内容如下:
#将ibatis log4j运行级别调到DEBUG可以在控制台打印出ibatis运行的sql语句
#trace<debug<info<warn<error<fatal
#指定日志有的输出的级别和要输出的方式
log4j.rootLogger=info,stdout,logfile,db
#指定日志输出到控制台
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
#log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout
#指定日志输出到文件
log4j.appender.logfile=org.apache.log4j.FileAppender
#指定日志输出的位置(这里使用${weChat.root}指定当前项目根目录)
log4j.appender.logfile.File=${weChat.root}/logs/mylog.log
#指定日志文件的大小
log4j.appender.logfile.MaxFileSize=1024KB
#指定日志输出的布局
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
#指定日志的输出内容
log4j.appender.logfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %F %p %m%n
#指定将日志写入数据库中
log4j.appender.db = com.cdjp.util.Log4jJDBCAppender
#缓存,这里是有一条日志就存入数据库(较浪费性能)
log4j.appender.db.BufferSize=1
#指定数据库的驱动
log4j.appender.db.driver=oracle.jdbc.driver.OracleDriver
#指定数据库的链接
log4j.appender.db.URL=jdbc:oracle:thin:@localhost:1521:xe
#指定数据库的用户名
log4j.appender.db.user=system
#指定数据库的密码
log4j.appender.db.password=123456
#写入数据的sql语句
log4j.appender.db.sql=insert into reslog(logId,class,method,createDate,logLevel,msg) values(reslog_seq.nextval,'%C','%M',
to_date('%d{yyyy-MM-dd HH:mm:ss}','yyyy-MM-dd HH24:mi:ss'),'%p','%m')
#指定日志的输出布局方式
log4j.appender.db.layout=org.apache.log4j.PatternLayout
注意:
原本上面这个属性 log4j.appender.db = org.apache.log4j.jdbc.JDBCAppender
可是将数据写入数据库时,部分数据中存在单引号(需要转义),这样在够构成写入数据库的sql语句就会产生错误。例如%m中含有单引号,因而就如发生SQLException:缺失逗号。
这里错误的原因是JDBCAppender这个类,官方已经不建议使用,它不会对数据中的单引号进行特殊处理(原理网上有,不过我看不懂,大家自行研究)
建议重写org.apache.log4j.jdbc.JDBCAppender, 代码如下:
1.就是自己写一个类扩展LoggingEvent,重写它的getThreadName方法,代码如下:
public class BPSLoggingEvent extends LoggingEvent { private static final long serialVersionUID = -1405129465403337629L; public BPSLoggingEvent(String fqnOfCategoryClass, Category logger, Priority level, Object message, Throwable throwable) { super(fqnOfCategoryClass, logger, level, message, throwable); } public String getThreadName() { String thrdName=super.getThreadName(); if(thrdName.indexOf("'")!=-1){ thrdName=thrdName.replaceAll("'", "''"); } return thrdName; } public String getRenderedMessage() { String msg=super.getRenderedMessage(); if(msg.indexOf("'")!=-1){ msg=msg.replaceAll("'", "''"); } return msg; } }
2.扩展JDBCAPPend了,覆盖里面的getLogStatement方法,代码如下:
public class BPSJDBCAppender extends JDBCAppender { protected String getLogStatement(LoggingEvent event) { String fqnOfCategoryClass=event.fqnOfCategoryClass; Category logger=Category.getRoot(); Priority level=event.level; Object message=event.getMessage(); Throwable throwable=null; BPSLoggingEvent bEvent=new BPSLoggingEvent(fqnOfCategoryClass,logger,level,message,throwable); return super.getLogStatement(bEvent); } }
3. log4j.appender.db = org.apache.log4j.jdbc.JDBCAppender 指定成上面BPSJDBCAppender(全称),就可以了。
<二>日志文件配置相关说明
log4j使用的几个关键点
根记录器(rootLogger),输出端(appenders)和布局(layouts)
a)定义根记录器的格式为
log4j.rootLogger = [ level ], appendName1, appendName2, …appendNameN。同一个记录器可有多个输出端。
PS:level的级别(此级别可以自定义,系统默认提供了以下级别)
◆debug//调试信息
◆info//一般信息
◆warn//警告信息
◆error//错误信息
◆fatal//致命错误信息
上面列出的就是所谓log4j的输出级别,log4j建议只使用4个级别,它们从上到下分别为ERROR、WARN、INFO、DEBUG,假设你定义的级别是info,
那么error和warn的日志可以显示而比他低的debug信息就不显示了。
b)定义一个appender的输出目的地的格式为
log4j.appender.appenderName = fully.qualified.name.of.appender.class。log4j提供了以下几种常用的输出目的地:
◆org.apache.log4j.ConsoleAppender,将日志信息输出到控制台
◆org.apache.log4j.FileAppender,将日志信息输出到一个文件
◆org.apache.log4j.DailyRollingFileAppender,将日志信息输出到一个,并且每天输出到一个新的日志文件
◆org.apache.log4j.RollingFileAppender,将日志信息输出到一个文件,通过指定文件的的尺寸,当文件大小到达指定尺寸的时候会自动把文件改名,如名为example.log的文件会改名为 example.log.1,同时产生一个新的example.log文件。如果新的文件再次达到指定尺寸,又会自动把文件改名为 example.log.2,同时产生一个example.log文件。依此类推,直到example.log. MaxBackupIndex, MaxBackupIndex的值可在配置文件中定义。
◆org.apache.log4j.WriterAppender,将日志信息以流格式发送到任意指定的地方。
◆org.apache.log4j.jdbc.JDBCAppender,通过JDBC把日志信息输出到数据库中。
c)输出格式(布局)layout
Log4j提供了一下几种布局:
◆org.apache.log4j.HTMLLayout,以HTML表格形式布局
◆org.apache.log4j.PatternLayout,可以灵活地指定布局模式
◆org.apache.log4j.SimpleLayout,包含日志信息的级别和信息字符串
定义一个PatternLayout布局的语句为:
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1} - %m%n
PS:ConversionPattern参数的格式含义
%c 输出日志信息所属的类的全名
%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy-MM-dd HH:mm:ss },输出类似:2002-10-18- 22:10:28
%f 输出日志信息所属的类的类名
%l 输出日志事件的发生位置,即输出日志信息的语句处于它所在的类的第几行
%m 输出代码中指定的信息,如log(message)中的message
%n 输出一个回车换行符,Windows平台为“ ”,Unix平台为“ ”
%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL。如果是调用debug()输出的,则为DEBUG,依此类推
%r 输出自应用启动到输出该日志信息所耗费的毫秒数
%t 输出产生该日志事件的线程名
ps:这些记录大多是抄录于他人(给出了具体原理,自行观看)
抄录一:Spring 配置log4j和简单介绍Log4J的使用
抄录二:log4j重写