用于指定 appender 将日志语句写入日志目的地所采用的格式。appender 能够用来格式化输出结果的各类布局包括:简单布局、模式布局和 HTML 布局。
[1]先看看Log4j的包目录结构:
org.apache.log4j:log4j主要的类、接口以及特殊的Appender类、Layout、Level和Logger
org.apache.log4j.spi:包含了针对SPI的一部分扩展【SPI——System Programming Interface】
org.apache.log4j.chainsaw:基于Java Swing的一个GUI日志查看器:
org.apache.log4j.config:用来设置或者获取某些组件的相关属性
org.apache.log4j.helpers:仅仅被log4j库内联使用的多个Class的集合,通常状况下不对外
org.apache.log4j.jdbc:一个Appender用来记录JDBC链接的相关事件
org.apache.log4j.jmx:在JMX开发的时候能够配置的基于JMX的日志记录,可是目前该包里面的类还不是特别稳定
org.apache.log4j.lf5:【目前不多用,我也不知道这部分用途,没用过】
org.apache.log4j.net:用来进行远程日志记录的Appender,主要用于JMS、SMTP以及基于Socket的日志记录,用于向一个log4j服务器发送日志进行远程的日志记录
org.apache.log4j.nt:Java本地接口的应用【JNI】,接口用Java,实现用C代码,用来记录Windows NT系统事件日志的Appender组件
org.apache.log4j.or:根据对象类型来对对象进行Render操做的帮助类
org.apache.log4j.performance:性能测试代码
org.apache.log4j.xml:包含了多个XML组件,使用DOM Tree的结构在Log4j环境里面用来记录XML格式的日志
org.apache.log4j.varia:包含了多个Appender以及Filters和其余相关组件
[2]Log4j的安装:
Log4j下载下来事后须要进行简单的安装,先保证原来的系统环境和Java环境是正常的:
- 下载log4j的jar包,上边已经提供了下载地址
- 将这些包解压到一个目录里面,【*:通常对于开发人员最好将jar的包分类放在不一样的目录下边方便使用。】
- 将包下边的log4j-1.2.15.jar放入开发的CLASSPATH里面,关于Java里面CLASSPATH的一些问题留到开发用Java里面去讲解
- 还须要下载两个辅助解析XML的jar,下载地址http://archive.apache.org/dist/xml/xerces-j/,这里我下载的最新版本2.9.0,取出里面的xercesImpl.jar和xml-apis.jar两个jar文件放到CLASSPATH里面。【*:在IDE环境下有专程针对CLASSPATH的设置,这种状况防止jar冲突最好的方式就是保持CLASSPATH里面只有java标准的环境】
2)Log4j的核心概念:
[1]Log4j中的Logger:
Logger在Log4j中是一个很核心的概念,它是日志进程里面的核心组件,在Log4j里面,Logger总共分为六个日志记录级别,其定义位于org.apache.log4j.Level类里:
- TRACE:这种细粒度信息时间不只仅针对调试,
- DEBUG:指出细粒度信息事件对调试应用程序是很是有帮助的,该级别的日志主要用于辅助开发人员调试;
- INFO:该级别代表消息上细粒度上突出强调了应用程序的运行过程
- WARN:代表有可能会出现潜在错误的情形
- ERROR:代表虽然程序发生了错误事件,可是仍然不影响系统的继续运行
- FATAL:该级别代表了每一个严重的错误时间,将会致使应用程序的退出。
根据API里面的描述还存在两个很特殊的级别:
- ALL:这是最低级别,用于打开全部的日志记录
- OFF:这是最高级别,用于关闭全部的日志记录
通常状况下,推荐开发过程只使用ERROR、WARN、INFO、DEBUG四个级别,下图说明了这几个级别相互之间的关系:
从上图能够知道,只有当日志记录器Logger的日志级别高于或者等于输出消息的等级的时候,该日志消息才会被输出。默认状况下,Logger的级别是Debug,若是咱们须要建立一个Logger,有如下几种方式:
建立根日志器:
Logger logger = Logger.getRootLogger();
建立一个新的日志器:
Logger logger = new Logger("MyLogger");
建立一个基于类的日志器:
Logger logger = new Logger(MyClass.class);
在Log4j里面设置一个日志的级别使用语句:
logger.setLevel(Level.DEBUG);
【*:在1.2版本以前,Log4j里面没有使用Logger类,主要是使用Category类,从版本1.2开始才使用Logger类,就上边的方式建立Logger】
这里先看一段代码,而后对Category进行一个详细说明,实际上从版本1.2开始Category和Logger是父子关系,Logger从Category类继承而来;在该版本以前咱们通常使用Category来建立日志记录器,在前边的版本里面Category就等同于如今咱们所见到的Logger。在版本1.2中,Category被标记为deprecated,而直接使用Logger替代它,通常状况下Java里面被标记为deprecated的方法和类都有替代方法以及类来进行对应功能的版本更新,咱们通常在开发过程当中尽可能避免使用标记为deprecated的类或者方法。下边的代码是升级的改动:
// 被抛弃的代码形式:
Category cat = Category.getInstance("foo.bar");
// 目前使用的建立Logger的形式:
Logger logger = Logger.getInstance("foo.bar");
为了使得上边的图形里面的内容更加容易理解,这里提供另一段代码:
package org.susan.java.logging;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
class Foo{}
public class Log4jLevelTester {
public static void main(String args[]){
Logger logger = Logger.getLogger(Foo.class);
logger.setLevel(Level.INFO);
// 该请求是被容许的,由于 WARN >= INFO
logger.warn("Low fuel level.");
// 该请求时背禁止的,由于 DEBUG < INFO
logger.debug("Starting search for nearest gas station.");
}
}
上边这段代码很好说明了logger在对待LEVEL的时候的用法,在setLevel的时候Logger设置了日志器自己的Level,而后在使用里面对应的warn、debug方法的时候会判断使用的方法和日志记录器设置的Level进行详细的比较,当知足上边图示的判断条件的时候才会输出日志信息。在这里还有一点须要注意的是方法warn和debug,这两个方法都不是Logger类所具备的方法,而是从它的父类继承过来的Category的方法,在使该方法的时候会针对咱们最初设置的日志的Level进行一个比较和判断,最终决定是否要被记录下来。那么在环境配置好的状况下,咱们执行该程序。
【异常】这里会遇到一个初学Log4j的常见问题,咱们会发现控制台只有这句话输出:
log4j:WARN No appenders could be found for logger (org.susan.java.logging.Foo).
log4j:WARN Please initialize the log4j system properly.
这句话的意思是在系统环境里面没有找到咱们所须要的配置文件,通常理解是缺少log4j.properties属性文件,在此处,若是咱们不使用配置文件的方式就将下边的代码修改为:
package org.susan.java.logging;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
class Foo{}
public class Log4jLevelTester {
public static void main(String args[]){
BasicConfigurator.configure();
Logger logger = Logger.getLogger(Foo.class);
logger.setLevel(Level.INFO);
// 该请求是被容许的,由于 WARN >= INFO
logger.warn("Low fuel level.");
// 该请求时背禁止的,由于 DEBUG < INFO
logger.debug("Starting search for nearest gas station.");
}
}
修改为上边这段代码事后,咱们就能够直接在没有log4j.properties配置文件的状况下直接运行上边的程序,该代码将会有如下输出:
0 [main] WARN org.susan.java.logging.Foo - Low fuel level.
经过这里咱们就能够知道Log4j里面的Level的排序为:DEBUG < INFO < WARN < ERROR < FATAL,等到后边再来分析上边的代码若是不使用BasicConfigurator.configure();而是使用咱们开发经常使用的属性文件log4j.properties
进行日志记录的相关配置,关于配置文件的详细内容等介绍完Layout和Appender了事后再说明。
[2]Log4j中的Appender:
Log4j里面的Appender相似于JDK 1.4 Logging Framework里面的Handler组件,其主要目的是管理咱们日志记录的结果,描述了这些日志怎样进行输出,下边列举了比较经常使用的一些Appender的快照:
- ConsoleAppender:这种Appender会管理咱们的日志消息,将日志事件记录到控制台以System.out或者System.err做为输出机制,它默认的输出为System.out;
- RollingFileAppender:这种Appender从FileAppender继承过来,大部分属性和FileAppender是相似的,当日志记录的文件到达文件容量的最大值的时候,会自动建立一个新的日志文件
- FileAppender:将日志输出到普通文本文件【这里有点须要说明,好像从版本1.2开始该Appender将会标记为禁用,替代的方案为该类的类:WriterAppender和ConsoleAppender】
- DailyRollingFileAppender:该Appender从FileAppender继承而来,可以按照必定的频度滚动日志记录文件
- WriterAppender:根据用户的选择将日志的信息以数据流的方式发送到任何用户指定的地方
- SMTPAppender:在特殊的事件日志发生的时候,发送一封Email到指定的邮件地址,通常状况下是针对ERROR级别以及FATAL级别的错误进行这种Appender的配置
- SocketAppender:将发送一个LoggingEvent对象到一个远程的日志服务器,通常状况下是一个SocketNode对象
- SocketHubAppender:将发送一个LoggingEvent对象的集合到一个远程的日志服务器,通常状况下是一个SocketNodes
- SyslogAppender:将日志记录消息发送到配置好的一个syslog远程服务器上
- TelnetAppender:该Appender和SocketHubAppender相似,也是向服务器发送日志信息,可是不是一个SocketNode对象或者SocketNode对象列,通常发送的是Category【1.1版】输出的结果。
整个org.apache.log4j包结构里面,Appender的结构图以下:[I]标识接口,[A]标识抽象类,[C]标识具体类
接口:
Appender[I]
类层次结构:
AppenderSkeleton[A]
|—AsyncAppender[C]
|—org.apache.log4j.jdbc.JDBCAppender[C]
|—org.apache.log4j.net.JMSAppender[C]
|—org.apache.log4j.lf5.LF5Appender[C]
|—org.apache.log4j.nt.NTEventAppender[C]
|—org.apache.log4j.varia.NullAppender[C]
|—org.apache.log4j.net.SMTPAppender[C]
|—org.apache.log4j.net.SocketAppender[C]
|—org.apache.log4j.net.SocketHubAppender[C]
|—org.apache.log4j.net.SyslogAppender[C]
|—org.apache.log4j.net.TelnetAppender[C]
|—WriterAppender[C]
|—ConsoleAppender[C]
|—FileAppender[C]
|—RollingFileAppender[C]
|—org.apache.log4j.varia.ExternallyRolledFileAppender[C]
|—DailyRollingFileAppender[C]
AsyncAppender:该Appender将会使用异步的方式来进行日志记录,并且该Appender会将咱们在日志记录中记录下来的相关信息,一旦发现有其余的Appender与之相关,就会将这些信息发送给相对应的Appender。这种Appender和其余Appender不同的地方在于它在进行日志记录的过程当中会开启一条新的线程(Thread)来完成日志记录。
【*:AsyncAppender是不能像其余日志记录器同样经过log4j.properties文件来配置,这个Appender只能使用DOMConfigurator经过编码的方式来进行配置】
这里提供一段使用AsyncAppender的代码:
package org.susan.java.logging;
import org.apache.log4j.AsyncAppender;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.TTCCLayout;
public class AsyncLogging {
private static Logger logger = Logger.getLogger("org.susan.java.logging.AsyncLogging");
private AsyncAppender asyncAppender = null;
private ConsoleAppender consoleAppender = null;
public AsyncLogging(){
try{
logger.setAdditivity(false);
asyncAppender = new AsyncAppender();
TTCCLayout layout = new TTCCLayout("yyyy-MM-dd");
consoleAppender = new ConsoleAppender(layout,"System.out");
asyncAppender.setName("Async");
asyncAppender.setBufferSize(5);
asyncAppender.setLocationInfo(true);
asyncAppender.setBlocking(false);
asyncAppender.activateOptions();
asyncAppender.addAppender(consoleAppender);
logger.addAppender(asyncAppender);
}catch(Exception ex){
ex.printStackTrace();
}
}
public void doLogging(){
logger.debug("Hello One");
logger.debug("Hello Two");
logger.debug("Hello Three");
}
public static void main(String args[]){
AsyncLogging demo = new AsyncLogging();
demo.doLogging();
}
}
上边这段代码,建立了一个AsyncAppender,而且将她与一个ConsoleAppender链接起来,实现日志记录的异步操做,运行上边这段代码将会获得如下结果:
2009-09-17 [main] DEBUG org.susan.java.logging.AsyncLogging - Hello One
2009-09-17 [main] DEBUG org.susan.java.logging.AsyncLogging - Hello Two
2009-09-17 [main] DEBUG org.susan.java.logging.AsyncLogging - Hello Three
须要注意的是下边的代码:
asyncAppender.addAppender(consoleAppender);
该代码段的就能够将咱们所须要的Appender和AsyncAppender链接起来进行异步方式的日志记录。
这里遇到过一个问题,由于我查了不少资料没有找到相关的文档,就是这里AsyncAppender的异步方式的原理。
我我的以为:AsyncAppender可使得和它相关的全部链接的Appender进行关联事后异步操做,那么一旦在AsyncAppender里面添加了一个Appender事后,该日志记录会和AsyncAppender结合在一块儿实现异步日志记录,并且添加的每一个Appender都是使用了和AsyncAppender相关的异步机制而使用新的线程去完整针对不一样的输出源进行彼此不影响的并发操做,每一个线程关联到不一样的输出源,也就是说Appender做为一个异步日志记录的最初入口,使得在作日志记录里面的Appender能够实现异步机制,而Log4j里面的Appender内部原理自己应该就是异步的,可是内部的原理和外部相互之间Appender之间的结构没有直接的关联。按照这样的理解,每一个AsyncAppender能够关联多个不一样的AsyncAppender,因而我修改了上边代码段:
package org.susan.java.logging;
import org.apache.log4j.AsyncAppender;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.TTCCLayout;
public class AsyncLogging {
private static Logger logger = Logger.getLogger("org.susan.java.logging.AsyncLogging");
private AsyncAppender asyncAppender = null;
private ConsoleAppender consoleAppender = null;
//这是新添加的一个Appender2做为asyncAppender去链接的一个新的ConsoleAppender
private ConsoleAppender consoleAppender2 = null;
public AsyncLogging(){
try{
logger.setAdditivity(false);
asyncAppender = new AsyncAppender();
TTCCLayout layout = new TTCCLayout("yyyy-MM-dd");
consoleAppender = new ConsoleAppender(layout,"System.out");
// 为了在Eclipse平台里面测试的时候能够更加明显知道谁在进行记录,因此第二个ConsoleAppender使用了System.err
TTCCLayout layout1 = new TTCCLayout("yyyy-MM-dd");
consoleAppender2 = new ConsoleAppender(layout1,"System.err");
asyncAppender.setName("Async");
asyncAppender.setBufferSize(5);
asyncAppender.setLocationInfo(true);
asyncAppender.setBlocking(false);
asyncAppender.activateOptions();
asyncAppender.addAppender(consoleAppender);
// 这里建立的异步Appender添加了第二个Appender与之关联起来
asyncAppender.addAppender(consoleAppender2);
logger.addAppender(asyncAppender);
}catch(Exception ex){
ex.printStackTrace();
}
}
public void doLogging(){
logger.debug("Hello One");
logger.debug("Hello Two");
logger.debug("Hello Three");
}
public static void main(String args[]){
AsyncLogging demo = new AsyncLogging();
demo.doLogging();
}
}
修改事后将会获得下边的输出:
2009-09-17 [main] DEBUG org.susan.java.logging.AsyncLogging - Hello One
2009-09-17 [main] DEBUG org.susan.java.logging.AsyncLogging - Hello One
2009-09-17 [main] DEBUG org.susan.java.logging.AsyncLogging - Hello Two
2009-09-17 [main] DEBUG org.susan.java.logging.AsyncLogging - Hello Three
2009-09-17 [main] DEBUG org.susan.java.logging.AsyncLogging - Hello Two
2009-09-17 [main] DEBUG org.susan.java.logging.AsyncLogging - Hello Three
这样咱们推测的结果就一目了然了,上边红色部分是consoleAppender2输出的结果,灰色部分是consoleAppender输出的结果
JDBCAppender:1.2版本里面的JDBCAppender未来颇有可能会被替换掉,不只仅如此,它也不会用来记录相关异常。JDBCAppender主要提供了一个机制直接将日志写入到数据库,每个Appender的调用都会添加到一个ArrayList里面做为缓冲,当这个缓冲里面填充了事件日志信息的时候,将会被JDBCAppender替代掉,而后根据相关配置生成对应的SQL脚本而且执行。在log4j.properties配置文件里面能够配置该Appender的BufferSize(缓冲区大小)、dbURL(数据库的URL地址)、User(数据库用户名)、Password(数据库密码)。在操做过程当中,能够经过使用setSql方法来设置在日志记录中须要使用的SQL语句,这个SQL语句将会发送到PatternLayout对象【固然该对象是由用户定义的】,默认状况下全部的模式转换在PatternLayout格式化过程都是会出如今生成的SQL命令里面的。
有时候咱们开发过程须要本身定义一个基于数据库的日志记录器,当JDBCAppender做为咱们使用类的父类的时候,有几个操做是必需要注意的:
- 重写方法getConnection()来获取咱们须要的链接,重写该方法主要是启用应用程序的链接池
- 重写closeConnection(Connectoin con)方法,若是咱们重写了getConnection方法,那么应该重写closeConnection方法用来关闭咱们所须要的链接,或者说将不使用的链接放入到咱们须要的链接池里面
- 重写getLogStatement(LoggingEvent event)方法用来生成动态的语句,默认状况下咱们直接使用SQL语句的可选值。
JMSAppender:在使用JMSAppender的过程当中,事件消息是做为JMS消息定义的类型ObjectMessage在传输过程进行序列化和反序列化操做完成的,其使用模式为JMS Topic方式。
LF5Appender【不了解详情】:这种Appender将会把日志记录到基于日志控制台的Swing界面上,该Swing控制台支持各类类型、多种详细试图以及一个基于全文检索的日志搜索
NTEventLogAppender:这个Appender只能使用于Windows操做系统,并且在使用该Appender的时候,须要将Log4j解压事后里面的NTEventLogAppender.dll动态连接库配置到Windows系统的PATH环境变量里面,不然咱们在开发过程将会收到JVM的错误信息:java.lang.UnsatisfiedLinkError
这里再提供一段将日志写入Windows事件查看器的代码:
package org.susan.java.logging;
import org.apache.log4j.Logger;
public class NTEventTester {
public static void main(String args[]){
Logger logger = Logger.getLogger("NTlog");
logger.info("This is the test info message");
// 只有这条记录会写入进去
logger.fatal("This is the test fatal message");
}
}
仅仅这段代码固然不够,看看这段代码的配置文件log4j.properties:
log4j.logger.NTlog = FATAL,stdout
log4j.appender.stdout=org.apache.log4j.nt.NTEventLogAppender
log4j.appender.stdout.Source=org.susan.java.logging.NTEventTester
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1};%L - %m%n
上边的配置后边会讲到,在配置章节讲log4j.properties的信息的时候,这里先不作说明,可是注意log4j.logger.NTlog里面的NTlog就是在代码里面经过Logger.getLogger("NTlog")里面的参数,并且边的等级指定了记录什么信息,运行这段代码可能控制台会有下边的输出:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no NTEventLogAppender in java.library.path
上边的错误就是上边讲到的没有配置NTEventLogAppender.dll的缘故,因此按照上边的配置方法须要将dll配置到PATH环境变量里面,这里再简单说明如下:
在32bit系统里面,能够直接把NTEventLogAppender.dll拷贝到C:/Windows/System32,这里C为安装Windows操做系统盘的盘符名称
在64bit系统里面的路径应该是:C:/Windows/SysWOW64,这一点不要搞错
配置好了事后控制台仍然没有相关输出,别着急,去Windows看看事件查看器就会出现下边的输出:
从截图能够看到,该事件的源为org.susan.java.logging.NTEventTester,也就是咱们本身将这条记录写入到事件查看器里面去的。
NullAppender:上边已经说过了org.apache.log4j.varia里面包含了多个相关组件以及Filter组件,这个Appender能够将日志记录消息发送到任意设备
SMTPAppender:使用该Appender的时候,能够配置BufferSize参数来配置有多少个日志记录消息会经过邮件发出去。
这里再提供一份发送邮件的日志记录器的测试代码:
package org.susan.java.logging;
import org.apache.log4j.Logger;
public class EmailLogging {
public static void main(String args[]){
Logger logger = Logger.getLogger("Emaillog");
logger.info("This is the test info message");
logger.fatal("This is the test fatal message");
System.out.println("Success...");
}
}
这段代码自己和上边NT记录的自己没有太大的区别,而真正的区别在于下边的配置文件项:
log4j.logger.Emaillog = WARN,stdout
log4j.appender.stdout=org.apache.log4j.net.SMTPAppender
log4j.appender.stdout.SMTPHost=smtp.126.com
log4j.appender.stdout.To=silentbalanceyh@126.com
log4j.appender.stdout.Subject=ErrorLog
log4j.appender.stdout.From=silentbalanceyh@126.com
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1};%L - %m%n
运行这段代码你就能够直接将邮件发送出去了,并且是将日志记录以邮件的形式发出去。但因为有些邮件客户端的问题,可能会遇到相似下边的错误:
log4j:ERROR Error occured while sending e-mail notification.
javax.mail.MessagingException: 503 bad sequence of commands
因为本文只着重讲日志记录,因此这个错误这里不作讲解。
SocketAppender:这种Appender将发送LoggingEvent对象到一个远程的日志服务器,通常状况下是一个SocketNode,而该Appender自己拥有下边这些属性,该Appender是客户端操做的:
- 若是发送的是SocketNode,并且这种状况下,会实现日志记录的实时同步。换句话说,这些事件日志会在同一个时间戳进行记录,并且在这种状况下,有些日志会在本地被本地客户端保存下来。
- SocketAppender在使用过程当中不须要使用Layout,它会直接把LoggingEvent对象序列化到服务器上
- 远程日志记录使用TCP协议,所以若是服务器是可达到的,那么事件日志最终将直接被送到服务器上
- 若是远程服务器出了问题,发送日志记录的请求将会暂停。尽管如此,若是当服务器恢复正常的时候,日志记录将会继续发送该请求,当可以继续链接服务器的时候,这种重链接会被一个connector线程启动。
- 事件日志将会被本地TCP实现进行缓冲存储。意思就是若是链接到服务器的速度很慢可是比日志记录产生日志的速度快的时候,该日志记录客户端将不会由于网速很慢而受影响;可是若是网速很慢比起日志记录客户端产生日志的速度都慢的时候,该日志记录客户端只能使用该网速的速录来进行日志记录。
- SocketAppender若不关联到任何类型,它将不会被connector线程内的垃圾回收器回收。并且connector线程仅仅会在服务器出问题的状况下才会存在,为了不垃圾回收的问题,咱们应该在编程过程当中显示调用close()方法,
- 若是JVM主机的SocketAppender在它显示关闭或者被垃圾回收器回收以前退出,这种状况下可能使得数据通道里面的数据丢失,这是Windows系统的一个常见问题。因此为了不数据丢失,最好是在该应用程序退出以前显示调用SocketAppender的close()方法或者直接调用LogManager.shutdown()方法。
SocketHubAppender:这个Appender和SocketAppender不一样的地方是,该Appender是服务端操做的,该Appender一旦运行起来了就开始对外发送相关消息,不管有没有接收者,其相关特性和SocketAppender差很少,可是因为该Appender不负责输出信息,一样的也是不须要设置Layout的。
SyslogAppender:该Appender主要是负责向远程syslog服务器发送事件日志记录的
TelnetAppender:该Appender主要负责向一个只读端口发送时间日志,并且在整个过程是能够基于TCP/IP进行监控的。客户端能够经过telnet链接到该端口收取日志记录。
WriterAppender:WriterAppender能够将事件日志发送到用户选择的任何一个地方,输出类为基于Writer和OutputStream的相关设备。
ConsoleAppender:这种Appender会管理咱们的日志消息,将日志事件记录到控制台以System.out或者System.err做为输出机制,它默认的输出为System.out;
FileAppender:该Appender能够将事件日志写入到一个文件里面,它支持java.io.Writer和Console的方式,在1.2的说明里面,未来可能会被WriterAppender和ConsoleAppender替代。
RollingFileAppender:这种Appender从FileAppender继承过来,大部分属性和FileAppender是相似的,当日志记录的文件到达文件容量的最大值的时候,会自动建立一个新的日志文件
ExternallyRolledFileAppender:该Appender用于监听某个端口号上边的“RollOver”消息【设置配置里面的Port】。
DailyRollingFileAppender:该Appender从FileAppender继承而来,可以按照必定的频度滚动日志记录文件。
[3]Log4j中的Layout:
Log4j中的Layout相似于JDK Logging里面的格式化输出,只是Log4j在输出过程将这些内容规范化了,从Log4j的总体结构上来说,主要有五个子类的Layout
- HTMLLayout:输出为HTML的表格方式,若是没有指定编码格式的话,该输出的编码格式为UTF-8或UTF-16
- SimpleLayout:输出为最简单的格式,仅仅打印一个“Level名 - 日志记录信息”,例如:“DEBUG - Hello World”
- DataLayout:该类是一个抽象类,主要是经过可选项来定制输出,该类有一个子类TTCCLayout
|—TTCCLayout:TTCC的格式主要包含了时间、线程、分类、嵌套内容信息,这四个内容都是能够经过人为编程的方式进行关闭和打开的,时间格式依赖DateFormat类
176 [main] INFO org.apache.log4j.examples.Sort - Populating an array of 2 elements in reverse order.
225 [main] INFO org.apache.log4j.examples.SortAlgo - Entered the sort method.
262 [main] DEBUG org.apache.log4j.examples.SortAlgo.OUTER i=1 - Outer loop.
276 [main] DEBUG org.apache.log4j.examples.SortAlgo.SWAP i=1 j=0 - Swapping intArray[0] = 1 and intArray[1] = 0
290 [main] DEBUG org.apache.log4j.examples.SortAlgo.OUTER i=0 - Outer loop.
304 [main] INFO org.apache.log4j.examples.SortAlgo.DUMP - Dump of interger array:
该Layout的第一个字段是该程序执行的时间,以毫秒为单位,第二个字段主要输出的执行的线程,其次是相关日志记录的登记,第四个字段是该语句出现的位置以及相关类型。最后一个字段表示嵌套内容相关信息
【*:不要在不一样的Appender里面使用同一个TTCCLayout实例,由于TTCCLayout是非线程安全的,最好的用法是一个Appender使用惟一的一个TTCCLayout实例。】
这里先看一段TTCCLayout的实例代码:
package org.susan.java.logging;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.NDC;
import org.apache.log4j.TTCCLayout;
/**
*针对TTCCLayout的一个简单应用
**/
public class TTCCLayoutDemo {
private static Logger logger = Logger.getLogger("TestTTCC");
private ConsoleAppender appender = null;
private TTCCLayout layout = null;
public TTCCLayoutDemo()
{
logger.setAdditivity(false);
// 初始化定义的TTCCLayout
layout = new TTCCLayout("yyyy-MM-dd");
// 初始化该Layout对应的Appender,这里使用的ConsoleAppender
appender = new ConsoleAppender(layout,"System.out");
// 将Appender添加到定义的Logger
logger.addAppender(appender);
}
public void computeSquareRoot(double number){
NDC.push(new Double(number).toString());
double sqrt = Math.sqrt(number);
logger.info("The sqrt value: " + sqrt);
NDC.pop();
}
public static void main(String args[]){
TTCCLayoutDemo demo = new TTCCLayoutDemo();
demo.computeSquareRoot(22);
demo.computeSquareRoot(44);
}
}
不须要log4j.properties文件,这里会获得下边的输出:
2009-09-17 [main] INFO TestTTCC 22.0 - The sqrt value: 4.69041575982343
2009-09-17 [main] INFO TestTTCC 44.0 - The sqrt value: 6.6332495807108
【*:这里须要注意的是输出和上边讲解遇到的TTCCLayout的输出不同,由于咱们在初始化构造TTCCLayout的时候使用的不一样的参数的缘故。】
- XMLLayout:该Layout会按照XML格式输,其定义文件为log4j.dtd,该格式化输出输出的不是一个标准的良好格式的XML文档,通常格式以下:
<?xml version="1.0" ?>
<!DOCTYPE log4j:eventSet SYSTEM "log4j.dtd" [<!ENTITY data SYSTEM "abc">]>
<log4j:eventSet vertion="1.2" xmlns:log4j="http://jakarta.apache.org/log4j/">
&data;
</log4j:eventSet>
该格式输出的编码通常是UTF-8或者UTF-16
- PatternLayout:这是Layout里面相对复杂的一个Layout这种状况下日志的格式是由模式字符串来进行设置的,主要依赖全局的format方法来格式化一个LoggingEvent而后经过模式转化将日志的格式输出,输出结果是须要依赖模式转换的
[4]模式转换:
模式转换常用在C语言的printf函数里面,模式转换就是定义必定的转化模式,而后将对应日志输出的值用转换模式进行匹配而后转换为字符串输出。在Log4j里面,全部的转换模式都是由一个%开始,而后跟着相对的模式符号,并且该模式可使用在log4j.properties属性文件里面。
举个例子,若是使用了模式“%-5p [%t]: %m%n”模式,看下边代码段:
root.debug("Hello Debug!");
root.info("Hello Info!");
上边这段代码咱们将会获得下边的输出:
DEBUG [main]: Hello Debug!
INFO [main]: Hello Info!
那么这些模式里面的模式表示什么意思呢?接下来看一张模式转换表:
模式参数 |
用法描述 |
举例 |
%c |
列出logger名字空间的名称 |
假设当前logger的名空间为“org.java.susan.logging” %c——org.java.susan.logging %20c——若名空间长度小于20的时候,则左边用空格填充 %-20c——若名空间长度小于20的时候,右边填充空白 %.40c——若名空间长度超过40就截去多余的字符 %20.40c——若名空间小于20,左边用空白填充,若是超过40就截去多余字符 %-20.40c——若名空间小于20,右边用空白填充,若是超过40就截去多余字符 %c{2}——susan.logging %c{4}——org.java.susan.logging |
%C |
列举出logger的类全名(包含包路径) |
假设当前类是org.java.susan.logging.PatternTester %C——org.java.susan.logging.PatternTester %C{1}——PatternTester |
%d |
显示日志记录的时间,{<日期格式>}使用ISO8601定义的日期格式 |
%d{yyyy/MM/dd HH:mm:ss,SSS}—— 2009/9/17 13:25:22,134【最后三位为毫秒】 %d{ABSOLUTE}——13:25:22,134 %d{DATE}——17 Sep 2009 13:25:22,134 %d{ISO8601}——2009-9-17 13:25:22,134 |
%F |
显示调用的logger的源文件名 |
%F——PatternTester.java |
%l |
输出日志事件发生的位置,包括类目录、发生线程,以及在代码中的行数 |
%l——PatternTester.fun(PatternTester.java:45) |
%L |
输出日志事件发生的代码行 |
45 |
%m |
显示输出消息 |
%m——该消息输出的主要目的是为了进行Debug操做 |
%M |
显示调用logger的方法名 |
%M——fun |
%n |
当前平台下的换行符 |
%n——表示换行 |
%p |
显示该日志的优先级 |
%p——INFO |
%r |
显示从程序启动时到记录该条日志时已经通过的毫秒 |
%r——1435 |
%t |
输出产生该日志事件的线程名 |
%t——PatternTester |
%x |
按NDC顺序输出日志 |
假设某线程调用顺序是MyDriver调用了org.java.susan.logging.PatternTester %c %x - %m%n——MyDriver - Call org.java.susan.logging.PatternTester - Log in PatterTester MyDriver - Return to MyDriver |
%X |
按MDC输出日志。一般用于多个客户端链接同一台服务器,方便服务器区分是哪一个客户端访问留下来的日志。 |
%X{5}——(记录代号为5的客户端日志) |
%% |
显示一个百分号 |
%%——% |
[5]关于NDC和MDC:
NDC(Nested Diagnostic Context)和MDC(Mapped Diagnostic Context)是log4j中很是有用的两个类,它们用于存储应用程序的上下文信息,从而便于在log中使用这些上下文信息。
<!--[if !supportEmptyParas]--><!--[endif]-->
NDC采用了一个相似栈机制来push和pop上下文信息,每个线程都独立地存储上下文信息。好比说一个servlet就能够针对每个request建立对应的NDC,存储客户端地址等信息。当使用的时候,咱们要尽量确保在进入一个context的时候,把相关的信息使用NDC.push(message);在离开这个context的时候使用NDC.pop()将信息删除。另外因为设计上的一些问题,还须要保证在当前thread结束的时候使用NDC.remove()清除内存,不然会产生内存泄漏的问题。存储了上下文信息以后,咱们就能够在log的时候将信息输出。
使用NDC的重要好处就是,当咱们输出一些上下文信息的时候,不须要让logger去寻求这些信息,而只须要在适当的位置进行存储,而后再配置文件中修改PatternLayout。
MDC和NDC的用法相似,不一样的是MDC内部使用了相似map的机制来存储相关信息,上下文信息也是每一个线程独立存储,不一样的是信息都是以它的key值存储在“map”中。相对应的方法,MDC.put(key,value);MDC.remove(key);MDC.get(key);在配置PatternLayout的时候使用:%x{key}来输出对应的value,一样的MDC也有一个MDCMatchFilter。【*:MDC是线程独立的,可是一个子线程会自动活得一个父线程MDC的拷贝】
3)配置相关以及属性文件log4j.properties:
单独把配置独立为一个小节是由于Log4j大部分是须要进行配置使用的,从上边邮件发送以及NT事件记录器的代码Demo能够知道其实仅仅须要在Log4j.properties文件里面配置必定的属性,开发过程就简化了不少,上边两端代码基本如出一辙【NT日志记录器和Email日志记录Demo代码】,仅仅修改了配置文件。
[1]BasicConfigurator类:
BasicConfigurator类主要为Log4j提供一个基础的配置环境,经过调用BasicConfigurator.configure方法能够建立一个简单的Log4j环境,并且这个方法是经过硬编码直接将Appender设置为ConsoleAppender的,该配置的输出设置为PatternLayout类,模式为"%-4r [%t] %-5p %c %x - %m%n",日志记录的级别为Level.DEBUG,代码说明上边已经用到过了。
注意:若是不对Log4j进行任何配置的话,将会收到相似下边的警告:
log4j:WARN No appenders could be found for logger (org.susan.java.logging.Foo).
log4j:WARN Please initialize the log4j system properly.
若是咱们经过配置log4j.properties配置文件的方式来进行配置,只须要进行下边的设置:
# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1
# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
[2]log4j.properties文件:(参考连接:http://www.wangchao.net.cn/bbsdetail_60723.html)
根配置:
根日志记录器配置的语法为:[真正使用的时候,记得去掉开始的#,在properties文件里面#的含义标识行注释]
#log4j.rootLogger = [level], appenderName,appenderName,...
其中Level就是日志自己的优先级,log4j里面建议使用的级别为:ERROR,WARN,INFO,DEBUG
appenderName就是日志输出的地方,某一个Appender的类名
Appender配置:
配置日志输出目的Appender的语法为:
#log4j.appender.appenderName = className
#log4j.appender.appenderName.key = value
#log4j.appender.appenderName.key1 = value1
其中appenderName为定义一个Appender的名字、className为一个类全名
Layout配置:
布局配置格式的语法为:
#log4j.appender.appenderName.layout = className
#log4j.appender.appenderName.layout.key1 = value1
#log4j.appender.appenderName.layout.key2 = value2
关于Log4j中使用布局打印的模式以下:
#%p 输出优先级,DEBUG,INFO,WARN,ERROR,FATAL
#%r 输出自应用启动到输出该log信息耗费的毫秒
#%c 输出所属的类,一般就是在所在类的全名
#%t 输出产生该日志事件的线程名
#%n 输出一个回车换行,Windows为“/r/n”,Unix平台为“/n”
#%d 输出日志的时间点的日期或者时间,格式为ISO8601,也可使用%d{yyyy MM dd}格式化输出
#%l 输出日志发生的位置,包括类名、线程以及代码中的行
【例:配置一个名为myConsole的ConsoleAppender,其输出Layout为TTCCLayout】
log4j.appender.myConsole = org.apache.log4j.ConsoleAppender
log4j.appender.myConsole.layout = org.apache.log4j.TTCCLayout
【例:配置一个TTCCLayout的具体属性】
log4j.appender.myConsole.layout.ThreadPrinting=false
log4j.appender.myConsole.layout.ContextPrinting=false
log4j.appender.myConsole.layout.CategoryPrefixing=false
log4j.appender.myConsole.layout.DateFormat=RELATIVE
【例:配置一个自定义名称的Logger】
log4j.logger.org.susan.java.logging.mylogger=DEBUG,myConsole
这种状况下,可使用Logger logger = Logger.getLogger("org.susan.java.logging.mylogger");来获取该日志记录,而该日志记录的输出输出到myConsole这个Appender
【例:配置一个FileLayout】
log4j.appender.myConsole.layout = org.apache.log4j.PatternLayout
log4j.appender.myConsole.layout.conversionPattern=%p - %m%n
【例:配置一个SMTP的邮件记录】
log4j.logger.EmailLogger = WARN,SMTP
log4j.appender.SMTP=org.apache.log4j.net.SMTPAppender
log4j.appender.SMTP.SMTPHost=smtp.126.com
log4j.appender.SMTP.To=silentbalanceyh@126.com
log4j.appender.SMTP.Subject=ErrorLog
log4j.appender.SMTP.From=silentbalanceyh@126.com
log4j.appender.SMTP.layout=org.apache.log4j.SimpleLayout
【例:NT事件查看器配置】
log4j.logger.NTLogger = FATAL,NTEVENT
log4j.appender.NTEVENT=org.apache.log4j.nt.NTEventLogAppender
log4j.appender.NTEVENT.Source=org.susan.java.logging.NTEventTester
log4j.appender.NTEVENT.layout=org.apache.log4j.PatternLayout
log4j.appender.NTEVENT.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1};%L - %m%n
【例:Rolling文件配置】
log4j.logger.RollingLogger = FATAL,ROLLING_FILE
log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender
log4j.appender.ROLLING_FILE.Threshold=ERROR
log4j.appender.ROLLING_FILE.File=rolling.log
log4j.appender.ROLLING_FILE.Append=true
log4j.appender.ROLLING_FILE.MaxFileSize=10KB
log4j.appender.ROLLING_FILE.MaxBackupIndex=1
log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
【例:Socket相关配置】
log4j.logger.SocketLogger = INFO,SOCKET
log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender
log4j.appender.SOCKET.RemoteHost=localhost
log4j.appender.SOCKET.Port=5001
log4j.appender.SOCKET.LocationInfo=true
log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout
log4j.appender.
SOCKET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n
【例:JDBC配置】
log4j.logger.JDBCLogger = INFO,DATABASE
log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/db_rect
log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
log4j.appender.DATABASE.user=root
log4j.appender.DATABASE.password=********
log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n')
log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
【例:DailyRolling日志记录配置】
log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A1.File=SampleMessages.log4j
log4j.appender.A1.DatePattern=yyyyMMdd-HH'.log4j'
log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout
ii.Commons Logging Framework:
1)JCL基本概念[介绍版本为1.1]:
Commons Logging Framework又称为JCL(Java Common Logging),该日志记录框架和Log4j以及Java Logging(JDK 1.4 Logging Framework)存在本质区别。前两个日志记录器自己提供了详细的实现,都有一个属于本身的体系结构,而JCL自己没有。JCL能够真正称为一个日志框架,由于它提供的是一个日志接口,并且是一个轻量级的不依赖实现的日志记录的抽象接口工具包,它容许任何开发者使用工具在该抽象框架下边进行日志记录的实现层的开发。而它自己只是一个轻量级的抽象框架:
官方下载地址:
http://apache.freelamp.com/commons/logging/binaries/commons-logging-1.1.1-bin.zip
由于JCL自己的类比较少,先看看整个抽象框架的包结构:[I]标识接口,[A]标识抽象类,[C]标识具体类,[E]标识异常
org.apache.commons.logging
|—[I]Log
|—[C]LogFactory
|—[C]LogSource
|—[E]LogConfigurationException
org.apache.commons.logging.impl
|—[C]AvalonLogger
|—[C]Jdk13LumberjackLogger
|—[C]Jdk14Logger
|—[C]Log4JLogger
|—[C]LogFactoryImpl
|—[C]LogKitLogger
|—[C]NoOpLog
|—[C]ServletContextCleaner
|—[C]SimpleLog
|—[C]WeakHashtable
- Log接口:
实现该接口的实例能够被LogFactory顺利建立和初始化,若是某一个日志记录想要初始化必须调用一个带String单参数的构造函数,传入的语意为该日志记录器的名称
Log接口定义了日志的几个登记,全部实现该接口的类都须要遵循这几个等级:
trace、debug、info、warn、error、fatal
- LogFactory为一个抽象类,使用工厂模式,能够建立一个实现了Log接口的日志记录器实例,并且该记录器实现是集成了JavaAPI和JAXP
【关键:LogFactory的实现是基于SAXParserFactory和DocumentBuilderFactory的,因此在使用的时候有可能还会用到Apache Xerces[一个能够解析XML的库]】
- LogSource类【Deprecated】:
该类是原版本的建立Log实例的类,如今已经被LogFactory替代了。当LogFactory建立某个Log实例的时候,应用程序能够经过调用方法makeNewLogInstance去实例化某个类或者针对该类的实现类进行配置工做。默认状况下,若是调用方法getInstance()将会使用下列算法:
[1]若是Log4J是配置好了的,那么LogFactory会建立一个org.apache.commons.logging.impl.Log4JLogger实例
[2]若是JDK是1.4或者以上的版本,LogFactory就会建立一个org.apache.commons.logging.impl.Jdk14Logger实例
[3]如过两个都没有知足,就返回一个org.apache.commons.logging.impl.NoOpLog实例
上边是默认的配置和默认的建立实例的行为,可是咱们能够经过两种方法修改相关内容
[1]启动命令提示行,在进行java编译的时候设置自定义的org.apache.commons.logging.Log的实现类的名称
[2]在运行时调用LogSource.setLogImplementation()
- LogConfigurationException类:
当使用LogFactory建立实现了Log类接口的实例的时候,若是建立失败就会抛出该异常
- AvalonLogger类:
该类有两种用途:
[1]该类的实例能够经过AvalonLogger(Logger)方法来进行构造,在这种状况下,该类在Logger外层进行了一层简单的封装,这种用法最大的用途在于使用一个属性设置器的时候。
[2]方法setDefaultLogger(org.apache.avalon.framework.logger.Logger)的属性调用来设置Avalon类的关联
这里插入Avalon框架的一段介绍:Apache的Avalon是一个包括核心框架、工具、组件和容器的面向组件编程(COP)的完整开发平台。经过使用关键设计模式,如反向控制模式(IoC)和分离考虑模(SoC),Avalon实现了传统OOP框架的一些优势: 1.没有执行锁 2.组件之间低耦合 3.管理组件生命周期 4.配置管理和易用的API 5.组件元数据框架和工具 6.服务相关的管理独立的、J2EE或Web环境的嵌入式容器 在COP方面,可重用的组件可以被组合到容器中,以提供应用程序模块。模块能够依次使用来建立你所须要的,从客户桌面应用程序,到FTP服务器,到Web服务,等等。Avalon提供各类基本组件和缺省的应用程序模块,帮助你快速的创建你本身的应用程序解决方案。
- Jdk13LumberjackLogger:实现了接口org.apache.commons.logging.Log,封装了Lumberjack实现部分,主要用于JDK 1.4以前实现Java的日志记录,Lumberjack项目是用来进行Java日志记录的老版本的日志API
- Jdk14Logger:实现了接口org.apache.commons.logging.Log,用来封装了上边咱们讲到的JDK 1.4 Logging Framework
- Log4JLogger:实现接口org.apache.commons.logging.Log,用来封装了Log4j版本1.2里面的Logger实例,初始化该实例的配置的时候应该使用一般的初始化方式。
该类不能用于Log4j 1.3,主要缘由在于:[1]1.2版本的Logger使用的是Priority参数而不是咱们介绍的Level参数;[2]Level类是继承于Priority的,在1.3版本里面,须要修改相关优先级,可是不是继承于Priority的,因此不兼容1.3版本,具体缘由是否如此我不太清楚。
- LogFactoryImpl类:LogFactory的子类,经过必定的算法动态选择应该使用哪一种日志记录器,主要对底层的不一样的日志实现类进行简单的封装
[1]使用工厂配置属性org.apache.commons.logging.Log用来标识使用的实现类
[2]使用org.apache.commons.logging.Log系统属性用来标识使用的实现类
[3]若是Log4J是配置好了的,那么LogFactory会建立一个org.apache.commons.logging.impl.Log4JLogger实例
[4]若是JDK是1.4或者以上的版本,LogFactory就会建立一个org.apache.commons.logging.impl.Jdk14Logger实例
[5]如过两个都没有知足,就返回一个org.apache.commons.logging.impl.SimpleLog实例
不只仅如此,该类还有一个方法能够提供反向的关联,使用Log实现类的方法setLogFactory(),传入一个参数LogFactory,这种方法调用事后就能够修改实现类对应的Factory的关联项,在整个程序运行过程当中,Factory将会记录下来全部建立过的Logger实例对象,当再次调用getInstance()方法的时候就直接从记录里面激活该实例。
【我仔细思考了如下,这个地方应该使用了Logger的“池化”技术,使用工厂虽然能够反复进行实例的构造,可是使用的是Logger的name做为标识,从设计上考虑,Logger的名字通常状况下都是某个类的全名,从整个系统级别讲,若是OO设计设计得不错的话,每个类若是须要进行日志记录的话最好使用单个日志记录器,这样能够节省系统开销。】
- LogKitLogger类:实现了接口org.apache.commons.logging.Log,该类封装了avalon-logkit日志系统,仅仅将LogKit留给用户本身进行配置。
- NoOpLog类:该类将会抛出全部的相关异常信息,没有任何系统属性配置的支持,通常状况下不使用该类。
- SimpleLog类:简单实现了org.apache.commons.logging.Log接口,用来记录全部可用的日志信息,并且把全部定义好的Logger输出到System.err,下边的一些系统属性能够用来配置该Logger的一些属性:
[1]org.apache.commons.logging.simplelog.defaultlog——默认的SimpleLog的等级参数,必须是如下的值的集合(trace,debug,info,warn,error,fatal),若是没有设置默认为info
[2]org.apache.commons.logging.simplelog.log.xxxxx——定义某个名称为xxxxx实例的日志器的等级,同上值必须是一个Level的集合
[3]org.apache.commons.logging.simplelog.showlogname——若是为true在日志记录的时候须要输出name属性,若是false的话就不输出Logger的名称,默认为false
[4]org.apache.commons.logging.simplelog.showShortLogname——和上边参数同样,惟一的区别是该项是类名,而上边的参数是输出的类全名,还有不一样的是默认值为true
[5]org.apache.commons.logging.simplelog.showdatetime——为true就输出时间,若是为false就不输出时间,默认是false
[6]org.apache.commons.logging.simplelog.dateTimeFormat——设置时间的格式,该格式应该是java.text.SimpleDateFormat能够解析的时间合法格式
这种配置须要检测类加载器在路径里面是否能够找到simplelog.properties的属性文件用来配置以上的选项,或者直接在java命令后边带上相关的参数
- ServletContextCleaner类和WeakHashtable类在此不作讲解,须要了解的能够去查询该类的API,并且我没有用到过这两个类,因此也没有去了解这两个类到底作了些什么,很差意思。
2)如何配置Log4j实现