SpringBoot系列(三)----某程序猿竟然因为“日志”问题一夜秃头

某程序猿竟然因为“日志”问题一夜秃头。这是道德的沦丧还是因为什么。。。。

在一个夜深人静的凌晨两点。一个兢兢业业的程序猿–小张,正在面对着电脑敲着键盘。他正在开发一个公司发不下来的大型系统。由于这个系统有点大,小张每次为了调试或者测试方面,他都喜欢使用System.out.println("");将一些关键数据打印在控制台上,以方便查看。

经过一段时间,小张以掉数不胜数的头发为代价,终于把系统开发完了。然而,有一天,老板跑过来跟小张说:“小张啊。你这个系统里面的System.out.println("");是不是有点多了,你把他给我去掉吧。”没办法,小张为了保住饭碗,只能在老板的淫威之下把这个System.out.println("");去掉。

小张刚把System.out.println("");去掉,老板又跑过来说:“我觉得这个输出的还不错,我们能够通过控制台来了解项目的运行状况。” 小张当时心里把老板的家人都问候了一遍。。。。

小张抽了根烟冷静了一下。想到,我干脆直接写在一个文件不就好了吗,方便以后控制。小张想,难道又要去该System.out.println("");了吗?不不不,太麻烦了,小张就想,我干脆直接写个框架来记录系统的信息不就好了吗。说干就干。

然后又是一段秃头的日子。小张终于把这个框架给写好了。给它命名为:zhanglogging.jar。这个框架表现的还不错,小张对这个框架很满意。但是天有不测风云,随着时代的进步,小张觉得这个框架的功能有点简陋了,已经跟不上时代的脚步了。小张突然想到一些高大上的功能,什么异步模式、自动归档,将每天的日志放到一个文件里边,以天来分类。等等等…

接下来还是一段掉发的日子,还别说,小张凭借过硬的技术,终于把第二代日志框架给开发出来了,给它命名为:zhanglogging-good.jar。但是小张的头发也越来越少。没过几天的美好生活,小张面临的问题又来了。小张写的那个新框架,里面的API或者一些设计可能跟之前写的老框架有点不一样了。那怎么办呢?只能将以前那个老框架卸下,换上新的框架,重新修改之前相关的API,又完善了一些功能;最终,一个完美的框架问世了,小张将之命名为:zhanglogging-prefect.jar;

但是问题又来了,每次换框架的时候都要改代码,太麻烦了。小张突然想到了一种模式。想到了JDBC跟数据库驱动的关系。现在我们写数据库都是面向接口编程,我们只需要把数据库的实现放进去就行了。小张说,那我的这个框架我为什么不这么设计呢?说干就干。

小张为所有的日志框架写了一个统一的接口层,就叫做日志门面(日志的抽象层),给它命名为:zhanglogging-abstract.jar,以后进行编码的时候,只面向zhanglogging-abstract.jar进行编程就行了,想要用哪个日志框架只需要给项目中导入具体的日志实现就行了。之前的日志框架都是实现的抽象层。小张为了公司真的是操碎了心,头发也越来越少,为小张来个一键三连吧。

接下来我们来进入今天的主题:

SpringBoot日志框架选择

开发中存在非常多的日志框架,JUL(java.util.logging),JCL(Apche Commons Logging),Log4j, Log4j2,Logback,SLF4j,jboss-logging等。

日志门面 (日志的抽象层) 日志实现
JCL(Jakarta Commons Logging) SLF4j(Simple Logging Facade for Java) jboss-logging Log4j JUL(java.util.logging) Log4j2 Logback
  • 使用SpringBoot的日志框架,也就是说我们需要一个抽象层和一个实现层,SpringBoot选用SLF4j作为抽象层,logback作为实现层。这里要说一下的是,SpringBoot底层是Spring框架,Spring框架默认的是JCL作为抽象层。

SLF4j使用

如何在系统中使用SLF4j

(我们创建新项目中已经帮我们导入了slf4j和logback)如何在系统中使用SLF4j?以后开发的时候,日志记录方法的调用,不应该来直接调用日志的实现类,而是调用日志抽象层里面的方法

  • SLF4 官方给出了简单示例:
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 结合各种日志框架的官方示例,从图中可以清晰的看出 SLF4J API 永远作为日志的门面,直接应用与应用程序中。slf4j官网用户手册
    在这里插入图片描述
    每一个日志的实现框架都有自己的配置文件。使用slf4j以后,配置文件还是做成日志实现框架自己本身的配置文件;

遗留问题

我们想要写一个SpringBoot项目,日志框架组合我们打算使用Slf4j+logback,但是项目中集成了Spring,Hibernate,MyBatis等等组件依赖,这个时候会有一个问题,就是我们集成的组件框架中存在自己的日志框架,比如Spring自带commons-logging、Hibernate(jboss-logging)等等,那么这个时候,我们的项目里面就像一个日志框架的大杂烩一样,非常的乱,那么我们就需要给我们项目中日志框架做统一,也就是说,不管我依赖的组件自带了什么日志框架,我只要配置我的Slf4j+logback就可以了。

来看看官方文档
在这里插入图片描述
我们需要分别引入我们组件日志的覆盖层,因为我们想要去除组件中的日志,不可能跑去删除组件的日志框架包,这样会导致组件崩溃,底层源码都被该了还不崩溃,所以我们在删除其他组件的日志框架jar包的时候,需要导入一层覆盖层jar包,这个jar中依旧有原来组件的日志框架的API,组件运行就不会报错,就相当于多做了一层适配,我们调用Slf4j+logback,然后通过这层适配层调用各组件的日志框架。

如何让系统中所有的日志都统一到slf4j;

1、将系统中其他日志框架先排除出去;

2、用中间包来替换原有的日志框架;

3、我们导入slf4j其他的实现

SpringBoot日志关系

  • 新项目中的pom.xm文件中的内容自动引入的内容
  • pom.xml中引入了starter启动器,其实每个启动器都会引入大量的依赖,那么我们怎么查看呢,如下图
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

  • 双击进入到spring-boot-starter-logging中,可以看到如下
	<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-logging</artifactId>
      <version>2.4.3</version>
      <scope>compile</scope>
    </dependency>

总结:

  • SpringBoot底层也是使用slf4j+logback的方式进行日志记录
  • SpringBoot也把其他的日志都替换成了slf4j;
  • 中间替换包
    在这里插入图片描述
  • 如果我们要引入其他框架。一定要把这个框架的默认日志依赖移除掉。Spring框架用的是commons-logging;
  • SpringBoot能自动适配所有的日志,而且底层使用slf4j+logback的方式记录日志,引入其他框架的时候,只需要把这个框架的依赖的日志框架移除掉。

日志使用

当我们直接运行新建项目的测试类,我们发现SpringBoot是帮我们配置了日志的

  • 修改测试类:
@SpringBootTest
class SpringbootLoggingApplicationTests {
    
    

    //记录器
    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日志");
    }
}

在新版的idea中实例化Logger时
Logger logger=LoggerFactory.getLogger(getClass());
会自动导入
import org.junit.platform.commons.logging.Logger;
import org.junit.platform.commons.logging.LoggerFactory;
需要手动替换为
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

日志的级别:

  • 由低到高 trace<debug<info<warn<error可以调整输出的日志级别;
  • 日志就只会在这个级别以后的高级别生效
  • SpringBoot默认给我们使用的是info级别的,没有指定级别的就用SpringBoot默认规定的级别;也就是说info是我们的root级别

可以看到只输出了info及以上的级别。
在这里插入图片描述

  • 在主配置文件中修改,如下
logging.level.com.cz=trace

意思就是我们cz包下所有的类都调成trace级别

在这里插入图片描述

  • 继续修改配置文件的内容,然后我会逐一讲解。
logging.level.com.cz=trace

#当前项目下生成springboot.log日志
logging.file.name=springboot.log

# 在当前磁盘的根路径下创建spring文件夹和里面的log文件夹;使用 spring.log 作为默认文件
#logging.file.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
  • logging.file.name
    指定日志生成到某个文件

在这里插入图片描述

  • logging.pattern.console

    • 后面的%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n是我们自己指定的格式。
      在这里插入图片描述
  • 日志输出格式:

    • %d:表示日期时间,
    • %thread:表示线程名,
    • %-5level:级别从左显示5个字符宽度
    • %logger{50}:表示logger名字最长50个字符,否则按照句点分割。
    • %msg:日志消息,
    • %n:是换行符

指定配置

如果我们还需要使用异步日志等功能的话,那么我们可能需要专门进行编写日志的配置文件。详细的看官方日志配置文件说明

  • 给类路径下放上每个日志框架自己的配置文件即可;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放在resources目录下,里面写着我们日志配置的相关内容,直接创建就可以了,不需要配置什么,SpringBoot就会自动识别

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">
            <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]

切换日志框架

但是不建议切换,人家经过多年的测试才有了现在的日志框架,下面东西看看就好了。

在这里插入图片描述

然后在依赖中就会被排除掉,这个时候我们只要在pom.xml中引入我们想要换的那个日志实现层就可以了

猜你喜欢

转载自blog.csdn.net/weixin_43844418/article/details/113986343