日志框架背景
- 1)程序媛小张,开发了一个大型系统;
- 2)最开始系统中使用 System.out.println("");将关键数据打印在控制台
- 3)后面发现这样不容易查看之前的日志信息,于是小张开发了一个小框架来记录系统的一些运行时信息,将所有运行信息统一保存到了文件中,最原始的日志框架就叫“zhanglogging.jar”
- 4)在不断的开发实践中,小张觉得之前的框架需要改进,决定再加几个功能:如异步模式、自动分类归档等, 改进版的框架名字叫“zhanglogging-good.jar”
- 5)因为日志框架升级,以前的项目如果要使用新的日志框架,那就不得不修改源码,假设哪一天又升级了日志框架叫“zhanglogging-prefect.jar”,这样反复修改项目源码仍然不太合适
- 6)后面发现数据库 JDBC 的 数据库驱动的模式,由Java 提供统一的JDBC 接口,不同的数据库供应商提供实现,切换数据库的时候,只需要直接更新数据库驱动即可,并不需要修改源码
- 7)于是小张也写了一个统一的日志接口层,叫 “日志门面”(日志的一个抽象层),名字叫 logging-abstract.jar;给项目中导入具体的日志实现就行了;
主流日志框架
- 市面上的日志框架;JUL、JCL(Apache 基金会的)、Jboss-logging、logback、log4j、log4j2、slf4j....
日志门面(日志抽象层) | 日志实现 |
JCL(Jakarta Commons Logging-属于Apache基金会) jboss-logging | JUL(java.util.logging-Java JDK自带的) |
SLF4j(Simple Logging Facade for Java) |
Log4j 、Log4j2、 Logback |
- 其中 SLF4j 与 Log4j 、 Logback 出自同一人之手,Logback 是 Log4j 的升级版;而 Log4j2 只是借用了 Log4j 的名号而已
- SpringBoot 底层是 Spring 框架,而 Spring 框架默认是用 JCL
- 所以为了开发日志系统扩展性更好的应用,就得从上表中左右两边各选择一个进行日志开发
- SpringBoot 选用的是 SLF4j 和 logback,所以Spring Boot 的日志框架重点是学习使用 SLF4j 和 logback
SLF4j 详解
SLF4J 原理
- 官网地址:https://www.slf4j.org/,官网有非常详细的使用文档以及 Jar 包下载和 Maven 依赖配置 等
- SLF4J Maven 依赖获取网址:https://mvnrepository.com/artifact/org.slf4j/slf4j-api
- 开发的时候,为了应用日志系统的将来的扩展,日志记录方法的调用,不应该再来直接调用日志的实现类,而是调用日志抽象层里面的方法;
- 意思是给系统里面导入 slf4j 的jar和 logback的jar之后,记录日志应该调用的是 slf4j 的API 而不是 logback。官方 "Hello Wolrd"例子代码如下:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.info("Hello World");
}
}
- 每一个日志的实现框架都有自己的配置文件,使用 slf4j 日志门面以后,配置文件还是要用日志实现框架自己本身的配置文件;
slf4j 与实现框架图总览
- 第一列“SLF4J unbound”:意思是如果应用中只导入“slf4j-api.jar日志门面”,没有导入slf4j实现时,则所有调用日志记录的方法都会无效,即不会有记录
- 第二列“SLF4J bound to logback-classic”:意思是如果导入了“slf4j-api.jar日志门面”及实现“logback-classic”的jar包,则调用SLF4J之后底层会以logback进行记录
- 第三列“SLF4J bound to log4j”:意思是导入了“slf4j-api.jar日志门面”及实现“log4j.jar”包之后,中间还要导入一个适配包“slf4j-log412.jar”,所以当应用中调用SLF4J记录日志的时候,会先经过适配包,最后调用实现包
- 原因就是log4j使用的时间很久了,之前并没有考虑到后来的星星之火slf4j,所以导致现在使用时需要借助适配包。而logback本身就是专门为slf4写的实现包,所以不需要任何适配。后面的JUL也是同理,不再累述
slf4j 与 log4j 入门
导入 jar
- 在应用中的pom.xml中导入依赖
- 所有的依赖配置基本上都可以从仓库中找到:“https://mvnrepository.com/”
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!--https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
- 如果不是Maven想要,则手动导入slf4j、log4j、slf4j-log4j12的jar包即可
添加配置文件
- 已经说过应用中日志记录调用的是 slf4j 的API,但是配置文件导入的还是实现框架的
#指定输出信息的级别--以及输出的位置
log4j.rootLogger=DEBUG,console,logFile
#表示Logger不会在父Logger的appender里输出,默认为true
log4j.additivity.org.apache=true
#控制台
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.ImmediateFlush=true
log4j.appender.console.Target=System.err
log4j.appender.console.layout.ConversionPattern=%5p [%t] (%c:%L) %d{yyyy-MM-dd HH:mm:ss,SSS} ---- %m%n
#日志文件
log4j.appender.logFile=org.apache.log4j.FileAppender
log4j.appender.logFile.Threshold=DEBUG
log4j.appender.logFile.ImmediateFlush=true
log4j.appender.logFile.Append=true
log4j.appender.logFile.File=E:/logs_wmx/log.log4j
log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
log4j.appender.logFile.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
日志记录
package www.wmx.com;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Hello world!
*/
public class App {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(App.class);
logger.info("Hello World");
logger.warn("严重警告.....");
}
}
- 控制台输出如下:
INFO [main] (www.wmx.com.App:12) 2018-07-14 13:40:28,643 ---- Hello World
WARN [main] (www.wmx.com.App:13) 2018-07-14 13:40:28,646 ---- 严重警告.....
Process finished with exit code 0
日志框架统一转为 slf4j
- 有时一个项目比较大时,里面导入了很多库或者框架,它们自身也在记录日志,使用了各种五花八门的日志框架,假如Spring 使用了 JCL、Hibernate 使用了 jboss-logging、MyBatis 又使用了其它的 xxxx等
- 那么能不能将它们统一转成slf4呢?统一日志记录,都统一使用slf4j进行输出呢?slf4j 官方提供了解决方案。
- 根据官方提供的上图所示,解决思想是:
- 将系统中其它日志框架删除掉;
- 用中间包来替换原有的日志框架;
- 导入slf4j的其他实现