博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
springboot中的日志框架
阅读量:3924 次
发布时间:2019-05-23

本文共 4209 字,大约阅读时间需要 14 分钟。

日志框架

在项目的开发中,日志是必不可少的一个记录事件的组件,所以也会相应的在项目中实现和构建我们所需要的日志框架。

而市面上常见的日志框架有很多,比如:JCL(Jakarta Commons Logging)、SLF4J、Jboss-logging、jUL(java.util.logging)、log4j、log4j2、logback等等,我们该如何选择呢?

通常情况下,日志是由一个抽象层+实现层的组合来搭建的

在这里插入图片描述
而SpringBoot机智的选择了SLF4J+Logback的组合,这个组合是当下比较合适的一组(log4j2其实很厉害,但是太厉害还不能很好地整合)。

SLF4J框架

SLF4J框架是一个常用的日志抽象层。

官网是最好的学习助手。
来到slf4j的官网的用户手册,我们可以在下边看到这张图:
在这里插入图片描述
首先SLF4J是一个日志门面,我们如果使用需要再另外找到一个日志实现框架,比如log4j、logback、log4j2、jcl、jul等等。

并且slf4j和log4j以及logback是同一个人写的,先有的log4j,但是作者觉得这个框架功能并不是很理想,并且在log4j的基础上进行改进的话改进要很大,所以作者干脆一不做二不休又编写了另一个框架,也就是大名鼎鼎的Logback。

假如我们使用slf4j+logback,因为logback已经知道了slf4j的存在,所以可以完美搭配。但如果slf4j想要搭配其他框架的话,就要导入一个中间的过渡jar包,因为其他框架在编写之前并不知道slf4j的存在。

各种框架的过渡jar包如下所示:

在这里插入图片描述
这些jar包,往上实现了slf4j,往下内部又调用了log4j,jcl或者jul等等的方法,所以称之为过渡包。

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

遗留问题的解决

在我们的项目中,可能同时使用到了许多框架,比如spring、mybatis、hibernate等等。但是这些框架底层使用到了许多不同的日志框架,比如spring的默认日志框架是commens-logging。

不同的框架使用不同的日志框架,这样我们的项目看起来就像是一个日志的杂交系统。

那如何解决这种问题呢?

来看看slf4j的官网告诉我们如何使用吧:

在这里插入图片描述
slf4j官网的指示很明显,就是再用的时候需要导入一个“偷天换日包”。

因为如果直接将这些框架所依赖的日志框架jar包排除出去,系统肯定会报错。我们就要使用一个偷天换日包,偷梁换柱包,比如:

在这里插入图片描述
拿spring举例子,因为spring必须使用commens-logging日志框架,而我们又想使用slf4j+logback的日志组合,那么我们必须要把commens-logging排除出去,但是怎么让系统不报错呢?

我们使用这些偷天换日包的话,就像jcl-over-slf4j.jar。这个jar的名字很明显就是从JCL想slf4j转化,它内部包的包名,包括类名都和JCL的完全相同,但是这些类中的方法全部是调用的slf4j的方法进行实现,这样我们就可以完美实现slf4j+logback组合,并且令系统不报错。

这样spring依旧使用JCL作为日志支持,但是他所使用的JCL已经不是原来的JCL了,原来的JCL已经被我们排除出去,使用的是我们导入的偷天换日包,这样就不会报错了。

统一日志记录的思路(SpringBoot实现统一日志记录为slf4j的做法):

  1. 先排除掉其他日志框架
  2. 然后用中间包来替换排除掉的日志框架
  3. 最后再添加目标日志框架

springboot的日志解决方案

springboot使用的是***slf4j+logback***的组合。

按照以前的想法:

springboot的底层是spring,那么他必然依赖JCL,所以我们要先将原来的JCL排除出去,加入我们的偷天换日包。这个偷天换日包,包名和类名都是各种框架需要的包名和类名,以保证框架不会报错,但是底层实现都是通过slf4j的方法来实现的。这样就能实现slf4j+logback的组合了。

但是在我使用springboot2.2.5版本的时候发现,框架组合并不是按照原来盗用原来日志框架的包名和类名来实现的,而是通过桥接方式实现,如下所示:

在这里插入图片描述
那么包名不是原来的包名的话,使用到jul的框架依旧会报错,点进这个类发现,虽然包名不是jul的包名,但是通过桥接模式依旧能让我们实现jul–>slf4j的改变。

在springboot2.0之后:

在SpringBoot2.x版本的时候,上述的实现方式发生了一些改变,中间引入了"桥接"的概念,没有直接通过模拟类名实现,比如类:SLF4JBridgeHandler,但是其底层的实现方法都是类似的,都是通过排除原有依赖实现。

比如springboot2.2.5,快速创建一个springboot的web项目,进入pom文件:

在这里插入图片描述
打开项目的依赖图:
在这里插入图片描述
我们可以看到,jul-to-slf4j.jar和log4j-to-slf4j.jar等等这些jar包,这些包都是偷天换日包,内部调用的都是slf4j的方法但是包名和类名都不变,这样就可以很好地和slf4j整合在一起了。

比如我们打开jul-to-slf4j.jar:

在这里插入图片描述
打开这个类,可以看到这个类的注释:
在这里插入图片描述
大概意思是:这个handler将会把JUL重定向(redirect)到slf4j,但是这个handler仅仅能将JUL桥接到slf4j。

我觉得这种方式和原来的方式大同小异,都是排除原来依赖的日志jar包,然后导入一个过渡包,实现slf4j+JCL或者slf4j+JUL的整合。

SpringBoot能自动适配所有的日志,而且底层使用slf4j+logback的方式记录日志,引入其他框架的时候,只需要把这个框架依赖的日志框架排除掉即可。

日志的使用

springboot日志配置

那我们在配置好日志之后,如何使用呢?

代码如下:

Logger logger = LoggerFactory.getLogger(getClass());@Testpublic void contextLoads() {
//日志的级别;//由低到高 trace

可以看到

在这里插入图片描述
输出只有info,warn和error级别。日志的默认级别是info(也就是root级别),只有info和高于info级别的日志才能输出。

我们可以在配置文件application.properties中进行配置,如:

在这里插入图片描述
trace是最低级别,这样所有级别的日志信息都能输出出来。

我们还可以配置哪些东西呢?

比如:

logging.level.com.atguigu=trace#logging.path=# 不指定路径在当前项目下生成springboot.log日志# 可以指定完整的路径;#logging.file=G:/springboot.log# 在当前磁盘的根路径下创建spring文件夹和里面的log文件夹;使用 spring.log 作为默认文件logging.path=/spring/log# 在控制台输出的日志的格式logging.pattern.console=%d{
yyyy‐MM‐dd} [%thread] %‐5level %logger{
50} ‐ %msg%n# 指定文件中日志输出的格式logging.pattern.file=%d{
yyyy‐MM‐dd} === [%thread] === %‐5level === %logger{
50} ==== %msg%n

在这里插入图片描述

像这样配置到application.properties这样,如果这样的话也太low了,我们可以写一个logback的专门的配置文件,那么这个配置文件放到哪里呢?

再次提到我觉得官网是最好的学习助手。

来到spring官网没查看springboot2.2.5的使用手册,在logging一栏:

在这里插入图片描述
所以我们可以把编写的logback.xml配置文件放到类路径的根目录下。这样springboot就可以自己帮我们加载进行配置了。

还有在命名为logback.xml之外,还有一个logback-spring.xml,如果这样命名的话就可以使用spriingboot为我们提供的logback的额外功能,官网是这么说的如如下图所示:在这里插入图片描述

点进去主要有两个扩展功能:
在这里插入图片描述
那为什么我们改个名字就可以使用springboot为我们提供的额外功能呢?
在这里插入图片描述
大概内容是这样的:因为标准的logback.xml文件会被日志框架过早的加载,所以你需要去使用logback-spring.xml或者定义一个logging.config。
这个拓展在logback的配置扫描下不能使用(logback-spring.xml会被spring扫描到),如果你非要这样使用,那么就会报这样一个错误。

额外特性1:profile配置

在这里插入图片描述
大概意思就是,我们可以定义一个标签,里边有个name属性,我们在name属性中指定这个配置在哪个profile中生效,在其他profile不会生效。如下所示:

%d{
yyyy‐MM‐dd HH:mm:ss.SSS} ‐‐‐‐> [%thread] ‐‐‐> %‐5level%logger{
50} ‐ %msg%n
%d{
yyyy‐MM‐dd HH:mm:ss.SSS} ==== [%thread] ==== %‐5level%logger{
50} ‐ %msg%n

额外功能2:环境属性

在这里插入图片描述
可以使用标签,这个标签可以允许我们从application.yml中获取值,而并不是直接设一个值scope属性为该值使用的范围,source是获取值得来源,并使用${}的方式获该值。
使用方法如下所示:

${
fluentHost}
...

转载地址:http://omqrn.baihongyu.com/

你可能感兴趣的文章
Linux实操--实用指令Day4
查看>>
Linux实操--实用指令Day3
查看>>
spring+springboot认识
查看>>
Leetcode 136. 只出现一次的数字
查看>>
Leetcode 11. 盛最多水的容器
查看>>
Leetcode 121. 买卖股票的最佳时机
查看>>
Leetcode 123. 买卖股票的最佳时机 III
查看>>
Leetcode 24. 两两交换链表中的节点
查看>>
Leetcode 100. 相同的树
查看>>
Leetcode 257. 二叉树的所有路径
查看>>
Leetcode 4. 寻找两个正序数组的中位数
查看>>
Leetcode 101. 对称二叉树
查看>>
Leetcode 108. 将有序数组转换为二叉搜索树
查看>>
Leetcode 303. 区域和检索 - 数组不可变
查看>>
Leetcode 110. 平衡二叉树
查看>>
Leetcode 111. 二叉树的最小深度
查看>>
Leetcode 226. 翻转二叉树
查看>>
Leetcode 617. 合并二叉树
查看>>
Leetcode 654. 最大二叉树
查看>>
Leetcode 304. 二维区域和检索 - 矩阵不可变
查看>>