3 - springboot的日志

目录

3 - springboot的日志

1 - 日志框架的故事

小张在开发一个大型系统,使用System.out.println("")将关键数据打印在控制台看看。

开发完了,老板说:System.out.println("")太多了。

小张一行一行注释掉了。

老板说:你把这些输出都给我写到一个文件当中,方便我以后看吧。

小张:MMD。

小张准备自己写一个框架,记录系统运行时候的信息,这个就是日志框架。zhanglogging.jar。

时代进步了,小张想出来了一些高大上的功能,以前日志记录的时候不管怎么输出都是阻塞的,他想用使用异步模式。他还想要使用日志归档的功能,每天的日志都自动归档。

小张实现了这些高大上的功能,zhanglogging-good.jar,这个是个新框架。跟以前的框架不兼容。

小张将以前的框架卸载了,换上了新的框架,重新修改之前项目当中的日志的API。

小张思考了,那TM以后我再更新日志框架,每次我都要改项目代码,是不是有点麻烦?

他想到了JDBC跟数据库驱动的关系。他想了,我们现在写数据库开发,都是面向接口编程,我们只需要把数据库的实现,也就是数据库的驱动放到了项目当中就可以了。小张想,日志框架也可以这样设计。所以小张为所有的日志框架写了一个统一的接口层,叫做日志门面,也就是日志的抽象层。

大家不管用什么日志框架,都用我的日志抽象层,以后我们进行编码的时候,只面向日志抽象层,不管是用什么日志框架,只需要项目中导入具体的日志实现,就可以了。

我们之前的日志框架,都是实现了日志抽闲层。

2 - 市面上的日志框架

3 - springboot的日志

左边是我们的日志门面,日志门面就是我们说的日志的抽象层,右边是日志的实现。我们应该在左边选择一个门面,右边选择一个实现;JCL就是apache jakarta小组开发的,我们一直在用的commons logging的jar包。

我们选择哪个呢?

先从左边选择,先排除jboss-logging,不是给我们普通程序员用的。再排除JCL,这个玩意最后一次更新是2014年,太TM老了。所以,我们理所应当,选择SLF4J作为日志门面。

再从右边选择,log4j和logback都是同一个人写的。log4j有性能问题,他觉得对log4j升级改动太大,他又新写了一个框架,叫做logback,他写了SLF4J作为日志门面。log4j没有logback高级,不用。JUL是为了跟log4j竞争的,很老,不用。log4j2是用了log4j的名字,是apache公司重新做的日志框架,设计非常好,太好了,高级有点过头了。所以,我们最终选择logback。

日志门面:我们选择SLF4J

日志框架:我们选择logback

springboot底层使用的是spring框架,spring框架默认使用的日志门面是JCL。springboot选用的是SLF4J和logback。

3 - 如何使用SLF4J

以后开发的时候进行日志记录。我们的日志记录方法调用,不应该调用日志实现类,而应该调用抽象层里面的方法。

3 - springboot的日志

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的jar,和logback的实现jar。

3 - springboot的日志

  • 参考上面图中,第一列,第一列表示的,只用slf4j没啥子用。
  • 参考上面图中,第二列,应用程序面向slf4j编程,调用slf4j的方法进行日志记录,在程序当中也导入了日志的实现logback的jar包,虽然我们调用的是slf4j的接口,但是最终logback会给我们实现将我们的日志记录到文件或者记录到控制台的。
  • 参考上面图中,第三列,如果slf4j要和log4j绑定在一起用。log4j出现的比较早,一开始根本就没有想到有slf4j这回事。因为后面的框架不断扩展之后,才有了slf4j这种统一抽象层。我们的应用程序还是调用slf4j的统一抽象层,然后中间我们需要有一个适配层,然后才能够调用log4j实现日志记录。所以,如果要用log4j要导入一个适配层的jar。
  • 参考上面图中,第四列,如果要使用java util jar,也是需要一个适配层的。
  • 参考上面图中,第五列,slf4j也有一些默认的实现,我们只需要导入slf4j和slf4j-simiple.jar。这里面有简单的日志实现。
  • 参考上面图中,第六列,我们导入slf4j.jar然后再导入slf4j-nop.jar,这个是说没有什么实现的jar,输出到一个空的位置。

slf4j要使用的话,就是要向上面图中的样子那样用。深蓝颜色的,就是slf4j的实现,绿色的就是适配层的意思。


每一个日志的实现框架,都有自己的配置文件,使用了slf4j以后,配置文件还是做成日志实现框架自己本身的配置文件;


4 - 遗留问题

开发a系统的时候,是使用slf4j和logback,可能a系统当中用到了spring、hibernate、mybatis等等一大堆框架,每一个框架底层可能也用到了日志框架,各不相同的,比如spring框架的底层,使用的就是commons-logging,而hibernate是使用jboss-logging来做的日志记录,现在就出现了一个问题。我们的系统当中使用slf4j和logback来做日志记录,而其他框架各自为政都是用自己的框架。这个感觉好乱哦。

我们现在想要做一件事情,就是统一日志记录。即使是别的框架,也要和系统项目一起,统一使用slf4j和logback一样进行输出。

3 - springboot的日志

3 - springboot的日志

针对上面的图,我们要进行一个说明:

  • 左上方,应用程序面向slf4j编程,真正的实现,使用的是logback。
  • 横着看,是说,有的框架使用的是commons-logging,有的框架使用的是log4j,有的框架使用的是java util logging。
  • 怎么办呢?把其他框架的日志,用上面的jar包来进行替换,比如说是spring当中使用的commons logging来进行日志记录的。我们导入jcl-over-slf4j.jar来对commons logging.jar来进行替换。如果我们正在使用spring框架,排除了commons logging,spring都运行不起来,因为在spring框架的底层凡是记录日志,都要用到commons logging的这些类。怎么办呢,我们使用一个新的jar包,就是jcl-over-slf4j.jar。这个jar包就是一个偷天换日的玩意。就是commons logging当中有什么类,jcl-over-slf4j.jar当中就有什么类,所以,spring框架把commons logging排除掉了,引入了jcl-over-slf4j.jar,spring框架当中需要用的commons logging的类,在jcl-over-slf4j.jar当中也有的。然后呢,我们的spring框架就不会报错了。这个包jcl-over-slf4j.jar真正调用的是slf4j,slf4j又调用的是logback。所以,我们通过这种包装层,把commons logging、log4j、java util logging都替换掉。
  • 如果我们是想要用slf4j+log4j的这种配置。我们看右上方的图,竖着的部分,日志抽象层使用的是slf4j,添加一个适配层,然后我们的日志实现,使用的是log4j。还是按照之前的用法。我们把别的框架使用的commons logging替换掉,使用jcl-over-slf4j替换。
  • 如果我们是想要用slf4j+java util logging的话,也是一样的道理。

上面的这张图的核心内容就是:我们如何让系统当中所有的日志都统一到slf4j。

- 第一步,将系统中其他日志框架都排除出去。
- 用中间包来替换原有的日志框架。偷天换日。
- 我们使用slf4j自己其他的实现。

5 - springboot与日志的关系

3 - springboot的日志

分析pom文件的依赖关系,有两种办法:

3 - springboot的日志

第一种办法,可以如图一样的分析。

第二种办法,可以如下图一样分析:

3 - springboot的日志

3 - springboot的日志

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>2.4.2</version>
      <scope>compile</scope>
    </dependency>

springboot使用来做日志功能的:

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-logging</artifactId>
      <version>2.4.2</version>
      <scope>compile</scope>
    </dependency>

3 - springboot的日志

1、springboot底层也是使用slf4j+logback的方式进行日志记录。

2、springboot还导入了jcl-over-slf4j和jul-to-slf4j,springboot也把其他的日志,都替换成为了slf4j

3、中间的替换包

3 - springboot的日志

3 - springboot的日志

4、如果我们要引入其他框架,我们一定要把这个框架的默认日志依赖移除掉。

spring框架使用的是commongs logging

3 - springboot的日志

从上面的图中,我们可以看到,排除掉了spring的commons-logging。

springboot能自动适配所有的日志,而且底层使用slf4j+logback的方式记录日志,引入其他框架的时候,只需要把这个框架依赖的日志框架排除掉,我们不用再做任何多余的配置,springboot就能够和它适配。

3 - springboot的日志


6 - springboot日志配置

springboot默认已经帮我们配置好了日志

3 - springboot的日志

3 - springboot的日志

调整日志级别:

3 - springboot的日志

3 - springboot的日志

3 - springboot的日志

3 - springboot的日志

3 - springboot的日志

3 - springboot的日志

3 - springboot的日志

不指定路径的情况下,在当前项目下生成,可以在配置的时候,就指定路径。


logging.path和logging.file是两个冲突设置。

3 - springboot的日志

3 - springboot的日志

3 - springboot的日志

3 - springboot的日志


默认日志输出格式是:

3 - springboot的日志

3 - springboot的日志

可以自己规定日志输出的格式:

3 - springboot的日志

3 - springboot的日志

3 - springboot的日志

3 - springboot的日志

3 - springboot的日志


7 - springboot默认日志配置

3 - springboot的日志

3 - springboot的日志

3 - springboot的日志

3 - springboot的日志

3 - springboot的日志

可以从上面的图中看到,root level是info的,这就是为什么springboot的日志级别是info的原因。

3 - springboot的日志

3 - springboot的日志


如果我们要用到logback的一些高级功能的话,我们就需要自己来写日志的配置文件。

  • 异步日志
  • 自动归档

怎么才能够用到自己的配置文件呢?

可以参考springboot的官方文档。

官方文档专门有一个章节来说logging。

3 - springboot的日志

3 - springboot的日志

只需要在类路径下面放上每个日志框架,我们自己的日志配置文件,就可以了。

springboot就不会使用它的默认配置了。

3 - springboot的日志

如果说,你放置的日志的配置文件的名字叫做logback.xml,这个就直接被日志框架识别了。

项目启动的时候,日志框架直接就用了这个配置文件,绕过了springboot了。

ctrl+shilf+f6,idea进行重命名的快捷键

如果我们把配置文件的名字修改为:logback-spring.xml,这样的话,日志框架就不认识了,日志框架过来一看不认识,它就不加载了。然后就由springboot加载了。

就可以用到springboot的springProfile标签,可以指定某段配置,只在某个环境下生效。

3 - springboot的日志

测试一下这个功能:

3 - springboot的日志

通过命令行参数激活开发环境:

3 - springboot的日志

3 - springboot的日志

3 - springboot的日志

8 - springboot切换框架

本来log4j就是因为太不好了,作者写了一个logback。但是现在假设,我们要从slf4j+logback切换到slf4j+log4j。

如果非要这么干,怎么办呢?

第一步:分析依赖树:

3 - springboot的日志

3 - springboot的日志

所以也要把上面的pom也排除掉。

第二步:导入slf4j对log4j的适配层

3 - springboot的日志

3 - springboot的日志

导入一个log4j的配置文件:

3 - springboot的日志

3 - springboot的日志

这个配置文件,是被log4j框架识别的。

启动项目,日志打印已经改变了。

3 - springboot的日志

3 - springboot的日志

3 - springboot的日志

搞定。


3 - springboot的日志

默认使用的是spring-boot-starter-logging,这个starter,我们可以排除掉。

3 - springboot的日志

3 - springboot的日志

3 - springboot的日志

通过上面的操作,就可以做到切换为log4j2了。

上一篇:maven建立逆向工程中出现的错误


下一篇:bzoj1801: [Ahoi2009]chess 中国象棋(DP)