Log4j概述
1 什么是Log4j
Log4j 是Apache为Java提供的日志管理工具。为了你快速理解Log4j的作用,我们用下面的代码说明Log4j的作用。
public void login(String userName,String pwd){
if (userName == null || pwd == null){
System.out.println("登录错误:用户名或者密码错误!");
return;
}
// 查询账户
UserAccount account = userAccountDao.load(userName);
System.out.println("查询的用户账号是否存在:" + (account!=null));
//校验密码是否正确
if (account != null && pwd.equals(account.getPassword())){
System.out.println("密码正确,登录成功!");
}else {
System.out.println("密码错误,登录失败!");
throw new RuntimeException("登录失败,用户名或者密码错误!");
}
}
上面例子中所有的输出语句都是用来调试程序的或者是记录一些信息的语句。这些调试代码必须在项目完成后删除,这些语句一般都是调试完后就要删除的,否则可能会影响代码的阅读和效率。
如果使用Log4j来打印这些测试代码,然后通过配置文件就能统一管理这些日志信息了;Log4j日志框架可以在配置文件中关闭所有日志,也可以在配置文件中打开所有日志,也可以打开某个级别的日志,除了这些功能,通过Log4j日志框架还可以实现管理日志出现的格式(是否加上日期和时间),以及日志输出的目标(是否为控制台,是否为文件)的控制。,总之Log4j通过修改指定的配置文件就可以实现各种各样的日志打印以及输出,是一个很好用的日志框架。
例子程序中主要引入了log4j的jar,使用的Maven的方式引入:
<!--log4j的库-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
2.Log4j的核心概念
Log4j中有三大组件:日志器(Logger)、日志输出目标(Appender)、格式化器(Layout)
-
Logger:用来输出日志消息的类,它可以输出不同级别的消息,例如错误消息、警告消息等;
-
Appender;通常我们希望日志输出到文件中,以及控制台,也可能希望日志输出数据库,该类就表示一个输出的目标;
-
Layout:对输出的消息进行格式化,例如在消息中添加日期,以及级别等。
简单的例子
创建了Logger,然后指定了Appender为Console,使用的Layout是SimpleLayout();
import org.apache.log4j.*;
import org.junit.jupiter.api.Test;
public class LogDemo {
pirvate static Logger log = Logger.getLogger(LogDemo.class);
static {
Appender appender = new ConsoleAppender(new SimpleLayout());
BasicConfigurator.configure(appender);
}
@Test
public void demo() {
log.info("Log4j Demo!");
}
}
3.日志级别
日志通常都有重要的等级之分,总不能什么日志都记录;在Log4j中日志消息分为五个级别,级别由高到低排列如下:
-
FATAL:重大错误,例如系统崩溃,内存泄漏等;
-
ERROR:错误,例如某模块出现Exception;
-
WARN:警告,程序的隐患,如果不处理,将来可能就是错误;
-
INFO:信息,可以用来查看程序执行的流程;
-
DEBUG:调试,用来调试程序的bug。
我们可以使用日志器输出这五种不同的日志,然后通过设置日志器的级别来控制输出的结果。如下例程所示:
import org.apache.log4j.*;
import org.junit.jupiter.api.Test;
public class LogDemo {
static Logger log = Logger.getLogger(LogDemo.class);
static {
Appender appender = new ConsoleAppender(new SimpleLayout());
BasicConfigurator.configure(appender);
}
@Test
public void testLevel() {
log.setLevel(Level.ERROR);//设置级别为ERROR
log.debug("Log4j Demo!");//不会打印
log.info("Log4j Demo!");//不会打印
log.warn("Log4j Demo!");//不会打印
log.error("Log4j Demo!");//会打印
log.fatal("Log4j Demo!");//会打印
}
}
打印结果如图所示:
上面代码中,只有log.error()和log.fatal() 两个方法的输出会完成,其他级别的输出都不会完成。因为设置日志器的级别为Level.ERROR后,只有高于ERROR级别的日志才能输出。
4.日志器名称
在创建日志器时,需要给日志器指定一个名称,例如上例中的:Logger log = Logger.getLogger(LogDemo.class);
使用了类的名字作为日志器的名称。日志器的名称不只是一个名称而已,日志器的名称说明了日志器之间的父子关系。子日志器会继承父日志器的Appender和Level。日志器的父子关系是通过日志器的名称来决定的,例如名称为com.demo
的日志器是com.demo.sub
的日志器的爸爸。com.demo.sub
会继承com.demo
的Appender
以及Level
。
import org.apache.log4j.*;
import org.junit.jupiter.api.Test;
public class LogDemo {
@Test
public void testLogger() {
//<1> 创建名为"com.demo"的日志器
Logger log = Logger.getLogger("com.demo");
Appender appender = new ConsoleAppender(new SimpleLayout());
BasicConfigurator.configure(appender);
log.setLevel(Level.ERROR);
//<2> 创建名为"com.demo.sun"的日志器,它继承了父日志器"com.demo"的Appender和Level
Logger logSub = Logger.getLogger("com.demo.sub");
//<3> 因为继承了父日志器"com.demo"的Appender和Level,父类的Level为Level.ERROR,所以下列的日志不会打印
logSub.info("不会打印...");
}
}
通常我们创建日志器都是使用当前类的名称来创建:Logger log = Logger.getLogger(LogDemo.class);这样我们可以通过配置父日志器来改变日志器的Appender和Level。
配置文件
1 log4j配置概述
log4j有两种配置文件:log4j.properties和log4j.xml
。因为log4j是比较简单的组件,所以建议使log4j.properties
。如果你把log4j.properties
放到项目的src下,如果Maven项目则放到resources
目录下即可,那么log4j会自动加载这个配置文件,这也是最为常用的方式。
2 根日志器
在配置文件中,需要配置名为log4j.rootLogger
的日志器,它就是根日志器。其他的日志器都是根日志器的子日志器,会继承根日志器的发送器,以及级别等。
#第一个Debug定义了根日志器的日志级别
log4j.rootLogger=DEBUG,Demo
log4j.appender.Demo=org.apache.log4j.ConsoleAppender
log4j.appender.Demo.layout=org.apache.log4j.SimpleLayout
log4j.rootLogger表示根日志器,DEBUG是指定根日志器的输出级别,只要大于等于DEBUG级别的日志就可以输出,而Demo是说明发送器(Appender)的名称;
log4j.appender.Demo
表示发送器,org.apache.log4j.ConsoleAppender
表示发送器为控制台发送器,即输出结果在控制台上显示;log4j.appender.Demo.layout
表示Demo
这个发送器的格式化器,org.apache.log4j.SimpleLayout
表示简化格式化器。
@Test
public void testRootLogger() {
Logger log = Logger.getLogger(LogDemo.class);
log.info("hello...");
}
3 其他日志器
除了上面的日志器,也可以配置其他的日志器,语法如下:
log4j.rootLogger=DEBUG,Demo
log4j.logger.com.demo=WARN
log4j.appender.Demo=org.apache.log4j.ConsoleAppender
log4j.appender.Demo.layout=org.apache.log4j.SimpleLayout
在这里不只配置了一个根日志器,还配置了一个名称为com.demo
的日志器。所有日志器如果名称是以com.demo
前缀的,那么都会继承上面的配置,如果不是,那么继承的就是root日志器了。
Appender
1 Appender概述
Appender是用来指定输出目标的类,你可以叫它发送器。上面我们使用的ConsoleAppender
就是用来向控制台输出的发送器。常用的发送器有:
-
ConsoleAppender:向控制台输出日志;
-
FileAppender:向文件输出日志
-
DailyRollingFileAppender:向文件输出日志,每天一个日志文件;
-
RollingFileAppender:向文件输出日志,当文件大小达到指定大小后,生成新文件;
2 ConsoleAppender
ConsoleAppender的目标是控制台!这也不多做解释
log4j.rootLogger=DEBUG,Demo
log4j.appender.Demo=org.apache.log4j.ConsoleAppender
log4j.appender.Demo.layout=org.apache.log4j.SimpleLayout
3 FileAppender
FileAppender的目标是磁盘文件,将日志记录到文件中。
log4j.rootLogger=DEBUG,Demo
#指定Demo发送器的类型为FileAppender
log4j.appender.Demo=org.apache.log4j.FileAppender
#指定Demo发送器的目标文件为log.txt
log4j.appender.Demo.File=log.txt
#指定追加方式为true,即不会覆盖原有日志信息。默认即为true,所以可以不给出这个配置
log4j.appender.Demo.Append=true
#指定发送器的格式化器为简单格式化器
log4j.appender.Demo.layout=org.apache.log4j.SimpleLayout
4 RollingFileAppender
RollingFileAppender
是FileAppender的子类,它的作用是当日志文件大小超出文件大小大限时,会把日志文件转换成备份文件,然后再生成一个新的日志文件。
例如日志文件名为log.txt,设置文件大小上限为10KB,当log.txt文件的大小超出了10KB后,把log.txt的名称转换成log.txt.1,然后再生成一个log.txt,新的日志会写入到新的log.txt文件中。当log.txt的大小再次达到10KB时,把log.txt.1
名称修改成log.txt.2
,把log.txt修改成log.txt.1,然后再生成一个新的log.txt文件。
还可以设置文件的个数,当设置备份文件的个数为3时,表示最多可以有3个文件。当文件达到3后,再次达到10KB时,那么会删除最后一个文件。例如当前已经存在log.txt、log.txt.1、log.txt.2
,这时如果log.txt又达到了10KB时,那么删除log.txt.2
,然后把log.txt.1
修改成log.txt.2
,再把log.txt
修改成log.txt.1
,然后再创建log.txt文件。
log4j.rootLogger=DEBUG,Demo
log4j.appender.Demo=org.apache.log4j.RollingFileAppender
log4j.appender.Demo.File=log.txt
#指定每个日志文件大小
log4j.appender.Demo.MaxFileSize=10KB
#指定最多产生的日志文件数
log4j.appender.Demo.MaxBackupIndex=3
log4j.appender.Demo.layout=org.apache.log4j.SimpleLayout
4 DailyRollingFileAppender
DailyRollingFileAppender
会根据设定的时间频率生成备份文件。
当时间频率为yyyy-MM:按月生成备份文件;
当时间频率为yyyy-ww:按周生成备份文件;
当时间频率为yyyy-MM-dd:按天生成备份文件;
当时间频率为yyyy-MM-dd-a:每天生成两次备份;
当时间频率为yyyy-MM-dd-HH:按小时生成备份文件;
当时间频率为yyyy-MM-dd-HH-mm:按分钟生成备份文件。
log4j.rootLogger=DEBUG,Demo
log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
#指定A1发送器的时间频率为每天生成一个备份文件。时间频率也是备份文件的后缀名,例如:log.txt.2019-09-01,如果没有给出’.’,那么就是log.txt2019-09-01
log4j.appender.A1.File=log.txt
log4j.appender.A1.DatePattern='.'yyyy-MM-dd
log4j.appender.A1.layout=org.apache.log4j.SimpleLayout
Layout
1 Layout种类
需要给发送器指定格式化器,这样发送器就可以按照格式化器指定的格式来输出日志信息了,常用的格式化器是PatternLayout.
2 PatternLayout
可以为PatternLayout指定一个模板,发送器会按模板来输出日志信息。下面介绍一下模式字符:
%m:信息本身;
%c:日志器的名称;
%d:日期,还可以指定日期的格式,例如:%d{yyyy-MM-dd HH:mm:ss};
%p:日志级别;
%n:换行;
%t:当前线程;
%l:输出日志的Java类相关信息。
如果在web项目中的配置,一般可以使用一些环境变量,例如下列中"${catalina.home}"指定的是tomcat的主目录:
log4j.rootLogger=INFO,C, F
log4j.appender.C=org.apache.log4j.ConsoleAppender
log4j.appender.C.layout=org.apache.log4j.PatternLayout
log4j.appender.C.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%p] %m [%t] %c [%l]%n
#指定tomcat的logs目录存放日志文件,如果希望存放到项目目录下,可以使用绝对路径。
log4j.appender.F.File=${catalina.home}/logs/demo.txt
log4j.appender.F=org.apache.log4j.DailyRollingFileAppender
log4j.appender.F.layout=org.apache.log4j.PatternLayout
log4j.appender.F.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%p] %m [%t] %c [%l]%n