当前位置: 首页 > 科技观察

发展-SpringBoot是如何实现日志记录的?

时间:2023-03-13 20:10:58 科技观察

休息日无聊,看了看SpringBoot中的日志实现,说说我的理解。门面模式说到日志框架,就不得不说到门面模式。门面模式的核心是外部与子系统的通信必须通过统一的外观对象进行,使子系统更易于使用。用一张图来表示门面模式的结构:门面模式很简单,模式就是把一些复杂的流程封装成一个接口,方便外部用户使用。该模式涉及三个角色:Fa?ade角色:外观模式的核心。它由熟悉子系统功能的客户角色调用。几个功能的组合(模块)是根据客户角色的需要在内部预先确定的。子系统(模块)作用:实现子系统的功能。它对客户端角色和门面是未知的。可以在系统内部相互交互,也可以有接口对外调用。客户角色:完成调用Facede要实现的功能。简单来说,市面上的日志框架。上表中的日志门面对应门面模式中的Facede对象。它们只是一个接口层,不提供日志实现。日志实现对应于各个子系统或模块,日志记录的具体逻辑实现写在右框内;那么我们的应用就相当于客户端。为什么要使用门面模式?想象一下我们开发系统的场景,我们需要用到很多包,而这些包都有自己的日志框架,那么就会出现这样一种情况:我们在自己的系统中使用了Logback日志系统,我们的系统使用了Hibernate.Hibernate使用的日志系统是jboss-logging,我们系统使用的是Spring,Spring使用的日志系统是commons-logging。这样我们的系统就得同时支持和维护Logback、jboss-logging、commons-logging三个日志框架,非常不方便。解决这个问题的方法是引入一个接口层,它决定使用哪个日志系统,调用者只需要打印日志即可,而不用关心如何打印日志,上表中的日志门面就是这个界面层。鉴于此,我们在选择日志的时候,一定要从上表中左边的日志门面和右边的日志实现中选择一个框架。SpringBoot底层默认使用SLF4j和Logback来实现日志输出。SLF4j使用官方文档给出了这样一个例子:importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;publicclassHelloWorld{publicstaticvoidmain(String[]args){//HelloWorld.class是你要打印的指定类的日志,//if如果想在其他类中打印,只需将HelloWorld.class替换为目标类名.class即可。Loggerlogger=LoggerFactory.getLogger(HelloWorld.class);logger.info("HelloWorld");}}为了了解SLF4j的工作原理,翻了下它的官方文档,看到了这么一张图:SLF4J的简要说明,里面有上图中SLF4J的六个用法,一共有五个作用。不用说,Application就是我们的系统。SLF4JAPI是日志接口层(门面);蓝色和底部灰色是具体的日志实现(子系统);而Adaptation是适配层。解释一下,上图中的第二种和第三种用法。第二个是SpringBoot的默认用法;为什么会出现第三个?因为Log4J出现的比较早,不知道后面还会有SLF4J。Log4J不能直接作为SLF4J的日志来实现,所以中间出现了一个适配层。第四个类比。提醒一下,每个日志实现框架都有自己的配置文件。使用SLF4J后,**配置文件还是做成了日志实现框架本身的配置文件。比如Logback使用logback.xml文件,Log4J使用Log4j.xml文件。如何将系统中的所有日志统一到SLF4J?继续浏览官网,看到了这样一张图:Legacy从上图可以看出,将系统中的所有日志统一到SLF4J的方法是:先排除其他日志框架。使用中间件替换原来的日志框架。我们导入SLF4J的其他实现。SpringBoot中的日志关系SpringBoot使用如下依赖来实现日志功能:2.1.3.RELEASEcompilespring-boot-starter-logging有这样一个关系图:从上图可以看出日志的底层依赖:SpringBoot2.x底层也是采用slf4j+logback或者Log4J的方式进行日志记录。SpringBoot引入了一个中间替换包,用SLF4J替换其他日志。如果我们要引入其他框架,可以去掉这个框架默认的日志依赖。比如Spring使用了commons-logging框架,我们可以这样去掉:commons-loggingcommons-loggingSpringBoot可以自动适配所有日志,底层使用slf4j+logback记录日志和引入其他框架时,只需要排除该框架依赖的日志框架即可。日志使用①默认配置(以Log4J框架为例),SpringBoot默认已经帮我们配置好日志://loggerLoggerlogger=LoggerFactory.getLogger(getClass());@TestpublicvoidcontextLoads(){//日志级别;//从低到高trace可以指定某个配置只在某个环境下有效示例(以Logback框架为例):%d{yyyy-MM-ddHH:mm:ss.SSS}---->[%thread]--->%-5level%logger{50}-%msg%n%d{yyyy-MM-ddHH:mm:ss.SSS}====[%thread]====%-5level%logger{50}-%msg%n如果你使用logback。使用logback-spring.xml代替logback-spring.xml作为日志配置文件,同时也使用了Profile功能。会出现如下错误:noapplicableactionfor[springProfile]Switchingthelogframework了解了SpringBoot底层日志依赖后,我们就可以根据SLF4J适配日志了。匹配图片并进行相关切换。例如,切换成SLF4J+Log4J,可以这样做:org.springframework.bootspring-boot-starter-weblogback-经典ch.qos.logbackorg.slf4jslf4j-log4j12切换成log4j2,就可以这样做:org.springframework.bootspring-boot-starter-web<排除>spring-boot-starter-loggingorg.springframework.bootorg.springframework。bootspring-boot-starter-log4j2***放logback-spring.xml的详细配置,可以参考自己项目中的配置:%d{yyyy-MM-ddHH:mm:ss.SSS}---->[%thread]--->%-5level%logger{50}-%msg%n%d{yyyy-MM-ddHH:mm:ss.SSS}====[%thread]====%-5level%logger{50}-%msg%n${LOG_HOME}/${appName}.log${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log365100MB%d{yyyy-MM-ddHH:mm:ss.SSS}[%thread]-[%-5level][%logger{50}:%line]-%msg%n