在编写大型项目时,日志输出是极其重要的一部分。而在Java项目中,常用的日志则是log4j和slf4j的组合。
Log For Java,Apache的一个开源项目,可以灵活地记录日志信息,我们可以通过log4j的配置文件灵活配置日志的记录格式、记录级别、输出格式,而不需要修改已有的日志记录代码。
官方网站:http://logging.apache.org/log4j/1.2/
简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,它只服务于各种各样的日志系统。按照官方的说法,slf4j是一个用于日志系统的简单Facade,允许最终用户在部署其应用时使用其所希望的日志系统。
在使用slf4j的时候,不需要在代码中或配置文件中指定你打算使用那个具体的日志系统,slf4j提供了统一的记录日志的接口,只要按照其提供的方法记录即可,最终日志的格式、记录级别、输出方式等通过具体日志系统的配置来实现,因此可以在应用中灵活切换日志系统。
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.26</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.26</version>
</dependency>
在Maven项目的src/main/resources目录中新建文件log4j.properties,一个可用的配置文件示例内容如下:
### 设置###
log4j.rootLogger = debug,stdout,D,E
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
log4j的日志级别如下表所示,其种从上至下等级越来越高,及配置了某一级别后,表格中处于它下边的位置级别的日志都会打印。
日志级别 | 说明 |
---|---|
ALL | 打印所有级别的日志 |
TRACE | 指定细粒度比DEBUG更低的信息事件 |
DEBUG | 指定细粒度信息事件是最有用的应用程序调试 |
INFO | 指定能够突出在粗粒度级别的应用程序运行情况的信息的消息 |
WARN | 指定具有潜在危害的情况 |
ERROR | 错误事件可能仍然允许应用程序继续运行 |
FATAL | 指定非常严重的错误事件,这可能导致应用程序中止 |
OFF | 这是最高等级,为了关闭日志记录 |
- ALL和OFF主要是为了方便配置打印日志和不打印日志,在实际代码使用中没有这两个级别对应的方法。
- 以上为log4j中的日志级别,但是在slf4j提供的接口中只有trace、debug、info、warn和error对应的方法,没有fatal。这是设计者觉得fatal表示大型错误,那么就意味着有可能会出现程序崩溃等现象,而这种问题在程序编写时是不太可能会想到的,即使想到了那也尽量应该在运行前避免。因此slf4j中没有fatal接口。
package com.ifish.study.java.log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Demo1 {
private static Logger log = LoggerFactory.getLogger(Demo1.class);
public static void main(String[] args) {
log.trace("This is a trace msg");
log.debug("This is a debug msg");
log.info("This is a info msg");
log.warn("This is a warn msg");
log.error("This is a error msg");
}
}
Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量,一旦修改属性,就容易出现忘记修改对应方法的失误。
Lombok能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。出现的神奇就是在源码中没有getter和setter方法,但是在编译生成的字节码文件中有getter和setter方法。这样就省去了手动重建这些代码的麻烦,使代码看起来更简洁些。
同样,Lombok也为slf4j提供了一个专门的注解@Slf4j,它们会为所注解的类提供一个名为log的变量。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<scope>provided</scope>
</dependency>
如下为使用了@Slf4j注解的代码
@Slf4j
public class LogExample {
}
如上代码在实际编译时会生成如下代码:
public class LogExample {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
}
在使用了lombok时,通常IDE会报错提示类中并没有这个变量,在IDEA中可以通过安装名为lombok的plugin来解决这个问题。