SpringBoot之日志框架整合
一、简介
日志用于记录服务器运行时的一些信息
市面上的日志框架;
JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j…
日志门面 (日志的抽象层) | 日志实现 |
---|---|
|
Log4j JUL(java.util.logging) Log4j2 Logback |
SpringBoot:底层是Spring框架,Spring框架默认的日志框架是用JCL;
SpringBoot选用 SLF4j和logback;
二、SLF4j使用
在开发的时候,日志记录方法的调用,不应该来直接调用日志的实现类,而是调用日志抽象层里面的方法;
简单来说我们应该调用SLF4j里面的方法,然后通过导入logback的jar包,来实现调用logback的方法
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 API(日志的抽象层)中的某个方法,SLF4J API中的某个方法通过调用具体的日志实现类来实现日志功能,比如SLF4J与logback绑定时,可以直接调用logback中某个具体的方法。
但是如log4j和jul,这两个实现类由于与SLF4J API不怎么配合(他们不是以SLF4J API的标准编写的),因此需要中间的一个适配层,SLF4J API通过调用适配层中的方法,适配层再通过调用具体实现类的方法实现日志功能(设计模式—适配器模式,可以去了解一下)。
这里需要注意,配置文件还是按照日志实现类的格式来写,比如SLF4j和logback的搭配,日志的配置文件需要按照logback日志的配置文件要求来写(SLF4j只提供一个统一的接口,而实际上使用的日志框架是logback)。
三、遗留问题—多框架日志不统一
一般情况下,一个项目中会使用多个框架,比如Spring+Mybatis,每个框架的作者都会选择一个日志框架作为默认的日志框架,比如Spring框架中使用 JCL,而Mybatis框架中使用了log4j(这不是默认的日志框架,Mybatis没有默认日志框架),这时候出现了日志不统一的情况,这时候会出现很多问题,比如控制台打印格式不统一、开发复杂度增加…为了解决这个方法,SLF4J日志框架提供了一种方法------使用SLF4J提供的jar包替换原本日志框架的jar包(这些包的主要作用就是原本new自己的日志对象的,这些包将其换成new SLF4J对象,然后调用方法时,改成调用SLF4J的方法),让整个系统中所有日志都统一到SLF4J
注意
在我们引入一个新的框架时(SpringBoot依赖中没有进行配置的依赖),需要将其默认的日志框架移出,如:
<!-- 这是SpringBoot其中的一个依赖,这里将默认的日志框架排除掉了 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.7.0</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
<optional>true</optional>
</dependency>
四、日志使用
1. 默认配置
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class SpringBootApplicationTest {
Logger logger = LoggerFactory.getLogger(getClass());
@Test
void test(){
// 日志的级别;
// 由低到高 trace<debug<info<warn<error
// 可以调整输出的日志级别;日志就只会在这个级别以以后的高级别生效
logger.trace("这是trace日志...");
logger.debug("这是debug日志...");
// SpringBoot默认给我们使用的是info级别的,没有指定级别的就用SpringBoot默认规定的级别;root级别
logger.info("这是info日志...");
logger.warn("这是warn日志...");
logger.error("这是error日志...");
}
}
SpringBoot默认帮我们配置好了日志
日志输出格式:%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
其中
%d表示日期时间
%thread表示线程名
%-5level:级别从左显示5个字符宽度
%logger{50} 表示logger名字最长50个字符,否则按照句点分割。
%msg:日志消息
%n是换行符
# 同时我们可以修改配置文件(application.yaml/application.properties)达到修改日志的默认配置
logging:
level:
com.whether: trace
pattern:
console: '%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n'
可以修改哪些配置请参考https://docs.spring.io/spring-boot/docs/2.1.17.RELEASE/reference/html/common-application-properties.html
# 下面这些写法是properties写法的案例
# logging.level.com.whether=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
2. 其他配置
给类路径下放上每个日志框架自己的配置文件即可;SpringBoot就不使用他默认配置的了
Logging System | Customization |
---|---|
Logback |
logback-spring.xml , logback-spring.groovy , logback.xml or logback.groovy
|
Log4j2 |
log4j2-spring.xml or log4j2.xml
|
JDK (Java Util Logging) | logging.properties |
logback.xml:直接就被日志框架识别了;
logback-spring.xml:日志框架就不直接加载日志的配置项,由SpringBoot解析日志配置,可以使用SpringBoot的高级Profile功能
<springProfile name="staging">
<!-- configuration to be enabled when the "staging" profile is active -->
可以指定某段配置只在某个环境下生效
</springProfile>
如:
<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">
<!-- 当激活dev环境时,环境在spring.profiles.active中指定 -->
<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>
如果使用logback.xml作为日志配置文件,还要使用profile功能,会有以下错误
no applicable action for [springProfile]
五、切换日志框架
可以按照slf4j的日志适配图,进行相关的切换;
切换为slf4j+log4j的方式
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!-- 移出一个日志实现包以及log4j的替换包 -->
<exclusion>
<artifactId>logback-classic</artifactId>
<groupId>ch.qos.logback</groupId>
</exclusion>
<exclusion>
<artifactId>log4j-over-slf4j</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- 添加log4j日志实现包 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
切换为log4j2
<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>