长大后想做什么?做回小孩!

0%

SpringBoot和日志框架

学习Java时间也不短了,最近忽然发现(顿悟)我好想没怎么学习使用过“日志”这个东西啊。。。之前学校的教学中简单的使用了log4j,但是配置文件也是老师给的,自己也没有细究其内容,就浑浑噩噩的过去了。现在想想确实不该,这不是一个好的现象。既然发现缺漏,那就花点时间将其慢慢弥补。

正文

SpringBoot基于Spring,Spring使用Apache的JCL(Jkarta Commons Logging)作为Spring框架内部的日志框架其仅仅是一个日志接口在实际应用中需要为该接口来指定相应的日志实现。SpringBoot默认的日志实现JUL(Java Util Logging)是JDK自带的日志包

此外SpringBoot外部当然也支持SLF4j(Simple Logging Facade for java)日志接口、Log4j日志实现、Logback日志实现这类很流行的日志框架。而且spring-boot-starter-logging采用了SLF4j+logback的形式,SpringBoot也能自动适配很多其他流行日志框架并简化配置。

统一将上面这些日志实现统称为日志框架

Java应用中,日志一般分为以下5个级别:

  • ERROR错误信息
  • WARN警告信息
  • INFO一般信息
  • DEBUG调试信息
  • TRACE跟踪信息

SLF4j

SLF4j是一个存取日志的标准接口,一张图展示SLF4j对多种日志框架极好的兼容性:

MrrFAO.png

使用的时候,日志记录方法的调用,不应该直接调用日志的实现类,而是调用日志抽象层里的方法。

每一个日志的实现框架都有自己的配置文件。使用SLF4j以后,配置文件依然是日志实现框架自己本身的配置文件。

一个思考

现在有一个a项目使用SLF4j+logback日志框架,但是a项目依赖了Spring、Hibernate、Mybatis等等框架,这些依赖的框架内部使用的不是SLF4j+logback日志框架:

a系统(SLF4j+logback):Spring(commons-logging)、Hibernate(jboss-logging)。。。

能否统一日志记录,使a系统及其依赖项目框架都使用SLF4j进行输出?

SLF4j官方文档中已经给出了解决方案,这个方案就是:Replace

MrcwQJ.md.png

这个解决方案大概以下三步:

  1. 将系统中其他的日志框架先排除出去,但是被排除日志框架的项目很可能会在运行时报错!
  2. 为了避免第一步的问题,SLF4j提供了一系列的中间包用来替换原有的日志框架。
  3. 最后导入我们需要的SLF4j实现即可。

总结

SpringBoot应用都依赖于spring-boot-starter,spring-boot-starter又依赖spring-boot-autoconfigure(自动配置)、snakeyaml(yaml文件解析)、spring-boot-starter-logging,其中spring-boot-starter-logging依赖关系如下:

MrgWNV.png

  1. SpringBoot底层使用SLF4j+logback进行日志记录。
  2. SpringBoot也把其他的日志都替换成了SLF4j。一系列的替换包项目,内部的包名和被替换的包保持一致,但是内部都是调用的SLF4j的方法实现的。
  3. 如果我们要引入其他的框架,一定要把这个框架的默认日志依赖exclusion掉,移除之后SpringBoot就可以自动适配。事实上SpringBoot本身也是这么干的。

配置和使用

在运行SpringBoot应用时,我们没有进行日志配置,但是依然有日志输出,说明SpringBoot有默认设置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//通过记录工厂获取记录器
Logger logger = LoggerFactory.getLogger(getClass());
@Test
void contextLoads() {
//日志级别由低到高:trace<debug<info<warn<error
//可以调整输出的日志级别,日志就只会设置级别及其更高的级别生效
logger.trace("trace...");
logger.debug("debug...");
logger.info("info...");
logger.warn("warn...");
logger.error("error...");
}
//运行结果:2019-11-17 20:43:34.396 INFO 175256 --- [ main] c.e.testslf4j.TestSlf4jApplicationTests : info...
//2019-11-17 20:43:34.397 WARN 175256 --- [ main] c.e.testslf4j.TestSlf4jApplicationTests : warn...
//2019-11-17 20:43:34.397 ERROR 175256 --- [ main] c.e.testslf4j.TestSlf4jApplicationTests : error...

从输出结果可以看出,SpringBoot默认配置的日志级别是:info,如果希望所有级别的日志,需要在配置文件中加入:

1
2
#logging.level.被设置的包路径=级别
logging.level.com.example.testslf4j=trace

如果希望不仅仅是在控制台输出日志,而是希望可以以文件的形式保存日志信息,可以进行如下配置:

1
2
3
#logging.file=springboot.log 不指定路径,springboot.log文件就会保存在项目下
#logging.file=E:/springboot.log 指定路径后,会在指定路径下保存日志文件
#logging.path=/spring/log 在当前次品的根目录下创建/spring/log,使用spring.log作为默认文件

但是上述配置方式在springboot2.0之后有所变化:

1
2
#logging.file改为logging.file.name=E:/springboot.log 
#logging.path改为logging.file.path=/spring/log

上述方法两条配置如果一起使用,只有logging.file.name起效。(老版本配置一样)还可以配置日志的格式:

1
2
3
4
5
6
7
8
9
10
11
12
#日志输出格式:
#%d表示日期时间,
#%thread表示线程名
#%-5level:级别从左显示5个字符宽度
#%logger{50}表示1ogger名字最长50个字符,否则按照句点分割。
#%msg:日志消息,
#%n是换行符

#控制台输出日志的格式
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中进行的,只能进行部分配置。如果想要进行更加详细完备的日志配置,需要添加xml日志配置文件。在springboot包中的logging包中有对logback进行默认配置的xml文件,如果想要定义自己的日志配置文件,直接在类路径下创建每个日志框架自己的配置文件即可,SpringBoot就不使用默认配置了。自定义日志配置文件的文件名必须使用官方文档中说的这些:

MsKptO.md.png

并且SpringBoot官方建议使用带有spring的文件名,如果使用logback.xml,配置文件就会被日志框架直接识别(相当于绕过了SpringBoot)。

反之,如果使用logback-spring.xml,日志框架就不直接加载日志的配置项,而是由SpringBoot来解析日志配置,而且可以使用SpringBoot的springProfile功能:

1
2
3
4
5
6
7
<!--可以指定某段配置,只在某个环境下生效(该功能只能SpringBoot解析时才能生效,如果直接日志框架识别则会报错)-->
<springProfile name="dev"><!--dev 开发环境下生效-->
<pattern>%d{yyyy-MM-dd}****[%thread]****%-5level****%logger{50}****%msg%n</pattern>
</springProfile>
<springProfile name="!dev"><!--!dev 非开发环境下生效-->
<pattern>%d{yyyy-MM-dd}----[%thread]----%-5level----%logger{50}----%msg%n</pattern>
</springProfile>

日志框架的切换

以SLF4j替换为LOG4j为例,先看官方文档:

Ms1eMQ.png

看明白了这个,切换这件事就变得简单了,简单粗暴直接排除原先的spring-boot-starter-logging依赖,引入spring-boot-starter-log4j2依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-logging</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

SpringBoot会自动适配log4j,并且也有其对应的默认配置。如果需要log4j的自定义配置文件,按照前文logback自定义配置文件的方式创建对应的xml文件即可。


关于每个日志框架的配置文件中还有哪些可配置项,后续学习中再去日志框架对应的官方文档或者大佬的博文中了解。