配置详细的日志输出,能帮助我们迅速定位有问题的代码位置,特别是当项目部署到服务器上,更需要一些日志对代码进行定位。
Log4J:
Log4j中有四个主要的组件,它们分别是 Logger(记录器)、Appender(输出目的地)、Layout(布局器:输出格式)和信息输出级别。日志输出即是拿到一个日志记录器(Logger),然后输出到什么地方(Appender,比如文件、控制台等等),以何种格式输出(Layout,比如HTML形式),输出级别可以来区分不同的日志信息的等级,哪些是重要的,哪些是不重要的。
Log4J三个核心概念
公共类 Logger 负责处理日志记录的大部分操作。
公共接口 Appender 负责控制日志记录的输出。
公共抽象类 Layout 负责格式化Appender的输出
1、demo
实现Log4j是需要导入一个Log4J的jar包即可:
2、Log4J配置文件
Log4J有两张配置文件:.xml和.properties格式,这里使用的是.properties格式,在第一次调用到Log4J时,Log4J会在类路径(当然也可以放在其他地方)中定位这个文件,并读入这个文件完成的配置。这个配置文件告诉Log4J以什么样的格式、把什么样的信息、输出到什么地方。
本例中Log4J.properties配置如下:
###定义输出地点stdout:Console ###
log4j.rootLogger=info, stdout, log, errorlog
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
###定义输出地点stdout:Console ###
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %d{ABSOLUTE} [ %t ] [ %p ]:%L - %m%n
###定义输出地点:log ###
log4j.appender.log = org.apache.log4j.DailyRollingFileAppender
log4j.appender.log.File = log/log.log
log4j.appender.log.Append = true
log4j.appender.log.Threshold = INFO
log4j.appender.log.DatePattern='.'yyyy-MM-dd
log4j.appender.log.layout = org.apache.log4j.PatternLayout
log4j.appender.log.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t ] %m%n
###定义输出地点:errorlog ###
log4j.appender.errorlog = org.apache.log4j.DailyRollingFileAppender
log4j.appender.errorlog.File = log/error.log
log4j.appender.errorlog.Append = true
log4j.appender.errorlog.Threshold = ERROR
log4j.appender.errorlog.DatePattern='.'yyyy-MM-dd
log4j.appender.errorlog.layout = org.apache.log4j.PatternLayout
log4j.appender.errorlog.layout.ConversionPattern =%-d{yyyy-MM-dd HH:mm:ss} [ %t ] %m%n
运行之后,项目根目录下会生成log文件夹,内容如下:
控制台输出如下:
3、记录器Logger:
Log4j允许开发人员定义多个Logger,每个Logger拥有自己的名字,Logger之间通过名字来表明隶属关系,子名有父名作为前缀,用点号.分隔。如:x.y是x.y.z的父亲,并且子类可以继承父类的属性,当然也可以进行覆盖。有一个Logger称为Root,它永远存在,且不能通过名字检索或引用,可以通过Logger.getRootLogger()静态方法获得,其它Logger通过Logger.getLogger(String name)方法,其中name一般以类的所在位置来命名Logger实例,这样很好区分,保证唯一性。
4、信息输出级别:
Log4J中将要输出的Log信息定义了5种级别,依次为DEBUG、INFO、WARN、ERROR和FATAL,这五个级别是有顺序的:all<debug < info < warn < error < fatal<off(关闭日志),用来指定一条日志的重要程度。例如上面代码中使用log.debug("debug"),即是以debug级别输出"debug"字符串,其余同理。这里Log4J有一个规则:假设Logger级别为P,如果在Logger中发生了一个级别Q比P高,则可以启动,否则屏蔽掉。假设你定义的级别是info,那么error和warn的日志可以显示而比它低的debug信息就不显示了,即输出流不会输出该日志。
5、分析Log4J.properties文件:
log4j.rootLogger=[level],appendername,appendername,.....
其中[level]表示root的输出级别,例如上述配置文件中,配置为info,因为Logger具有继承关系,且所有的Logger都是从根root继承下去,故所有Logger的输出级别都是info,除非其进行覆盖。当配置为info时,在输出级别中debug < info < warn < error < fatal,故低于该级别不会输出,高于该级别才输出(示例代码中没有任何的"bug"字符串输出)。appenderName就是指把日志信息输出到哪个地方。可以同时指定多个输出目的地,例如上述例子我们制定了stdout、log和errorlog这三个地方(这是由自己定义的,便于下文使用。类似于new一个实例)。例如刚刚的appendername是stdout,再分析下面两行代码
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
其中,配置了stdout这个输出目的地的位置,即是ConsoleAppender,输出目标是控制台。Log4j提供的appender有以下几种:
- org.apache.log4j.ConsoleAppender(控制台)
- org.apache.log4j.FileAppender(文件)
- org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
- org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
- org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
<span style="font-family:SimSun;">log4j.appender.log = org.apache.log4j.DailyRollingFileAppender
log4j.appender.log.File = log/log.log</span>
即是将输出放在项目根目录下的log目录下的log.log文件中,没有该目录则新建。
再看log4j.appender.log.Append = true这句,true表示在原输出文件后追加日志,false则表示清除掉原日志,再写日志。默认为true。
再看log4j.appender.log.Threshold = INFO即是指定日志的输出级别,前面介绍了root是info级别,若不配置该属性,即为继承root的属性,也可用log4j.appender.log.Threshold = error进行覆盖,设置自己的输出级别为error。
再分析最后三句:
log4j.appender.log.DatePattern='.'yyyy-MM-dd
log4j.appender.log.layout = org.apache.log4j.PatternLayout
log4j.appender.log.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t ] %m%n
即是给log配置输出格式layout,第一句是配置日期的输出格式,log4j的layout有以下几种:
- org.apache.log4j.HTMLLayout(以HTML表格形式布局)
- org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
- org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
- org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
第三句是向这个layout中注入ConversionPattern参数,能将输出进行格式化,其中Log4J采用类似C语言中的printf函数的打印格式格式化日志信息,如下:
- %m 输出代码中指定的消息
- %p 输出优先级,即debug、info、warn、error、fatal
- %r 输出自应用启动到输出该log信息耗费的毫秒数
- %c 输出所属的类目,通常就是所在类的全名
- %t 输出产生该日志事件的线程名
- %n 输出一个回车换行符
- %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss ,SSS}
- %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)
对这上述示例中的配置及控制台输出,应该很好明白其中的对应关系。