05-01-SpringBoot之日志框架整合

SpringBoot之日志框架整合

一、简介

日志用于记录服务器运行时的一些信息

市面上的日志框架;

JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j....

日志门面 (日志的抽象层) 日志实现
JCL(Jakarta Commons Logging)不更新了 SLF4j(Simple Logging Facade for Java) jboss-logging不好用 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通过调用适配层中的方法,适配层再通过调用具体实现类的方法实现日志功能(设计模式---适配器模式,可以去了解一下)。

05-01-SpringBoot之日志框架整合

这里需要注意,配置文件还是按照日志实现类的格式来写,比如SLF4j和logback的搭配,日志的配置文件需要按照logback日志的配置文件要求来写(SLF4j只提供一个统一的接口,而实际上使用的日志框架是logback)。

三、遗留问题---多框架日志不统一

一般情况下,一个项目中会使用多个框架,比如Spring+Mybatis,每个框架的作者都会选择一个日志框架作为默认的日志框架,比如Spring框架中使用 JCL,而Mybatis框架中使用了log4j(这不是默认的日志框架,Mybatis没有默认日志框架),这时候出现了日志不统一的情况,这时候会出现很多问题,比如控制台打印格式不统一、开发复杂度增加......为了解决这个方法,SLF4J日志框架提供了一种方法------使用SLF4J提供的jar包替换原本日志框架的jar包(这些包的主要作用就是原本new自己的日志对象的,这些包将其换成new SLF4J对象,然后调用方法时,改成调用SLF4J的方法),让整个系统中所有日志都统一到SLF4J

05-01-SpringBoot之日志框架整合

05-01-SpringBoot之日志框架整合

注意

在我们引入一个新的框架时(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的方式

05-01-SpringBoot之日志框架整合

<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

05-01-SpringBoot之日志框架整合

<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>
上一篇:05-01-SpringBoot之日志框架整合


下一篇:springboot elk