springboot中的日志框架

日志框架

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

而市面上常见的日志框架有很多,比如: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());
@Test
public void contextLoads() {
//日志的级别;
//由低到高 trace<debug<info<warn<error
//可以调整输出的日志级别;日志就只会在这个级别以以后的高级别生效
logger.trace("这是trace日志...");
logger.debug("这是debug日志...");
//SpringBoot默认给我们使用的是info级别的,没有指定级别的就用SpringBoot默认规定的级别;root级别
logger.info("这是info日志...");
logger.warn("这是warn日志...");
logger.error("这是error日志...");
}

可以看到
在这里插入图片描述
输出只有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不会生效。如下所示:

<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<!‐‐
日志输出格式:
%d表示日期时间,
%thread表示线程名,
%5level:级别从左显示5个字符宽度
%logger{50} 表示logger名字最长50个字符,否则按照句点分割。
%msg:日志消息,
%n是换行符
‐‐>
<layout class="ch.qos.logback.classic.PatternLayout">
<springProfile name="dev">
<pattern>%d{yyyy‐MM‐dd HH:mm:ss.SSS} ‐‐‐‐> [%thread] ‐‐‐> %5level
%logger{50}%msg%n</pattern>
</springProfile>
<springProfile name="!dev">
<pattern>%d{yyyy‐MM‐dd HH:mm:ss.SSS} ==== [%thread] ==== %5level
%logger{50}%msg%n</pattern>
</springProfile>
</layout>
</appender>

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

<springProperty scope="context" name="fluentHost" source="myapp.fluentd.host"
        defaultValue="localhost"/>
<appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender">
    <remoteHost>${fluentHost}</remoteHost>
    ...
</appender>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值