写点什么

精彩 3000 字!给讲得明明白白:配置 logback

用户头像
比伯
关注
发布于: 2021 年 04 月 28 日
精彩3000字!给讲得明明白白:配置 logback

logack 简介

logback 官网:https://logback.qos.ch/

目前还没有看过日志类框架的源码,仅限于如何使用。所以就不说那些“空话”了。最直观的认知是:

  • logback 和 log4j 是一个人写的

  • springboot 默认使用的日志框架是 logback。

  • 三个模块组成

logback-core

logback-classic

logback-access

  • 其他的关于性能,关于内存占用,关于测试,关于文档详见源码及官网说明

logback-core 是其它模块的基础设施,其它模块基于它构建,显然,logback-core 提供了一些关键的通用机制。logback-classic 他的地位和作用等同于 Log4J,它也被认为是 Log4J 的一个改进版,并且它实现了简单日志门面 SLF4J;而 logback-access 主要作为一个与 Servlet 容器交互的模块,比如说 tomcat 或者 jetty,提供一些与 HTTP 访问相关的功能。

配置文件详解

这部分主要来学习下 logback 配置文件的一些配置项。

configuration

先来看这张图,这个结构就是整个 logback.xml 配置文件的结构。

对应来看下配置文件:

对应来看下配置文件:
<configuration scan="true" scanPeriod="60 seconds" debug="false"> <property name="glmapper-name" value="glmapper-demo" /> <contextName>${glmapper-name}</contextName> <appender> //xxxx </appender> <logger> //xxxx </logger> <root> //xxxx </root> </configuration> 复制代码
复制代码


ps:想使用 spring 扩展 profile 支持,要以 logback-spring.xml 命名,其他如 property 需要改为 springProperty

  • scan:当此属性设置为 true 时,配置文件如果发生改变,将会被重新加载,默认值为 true。

  • scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当 scan 为 true 时,此属性生效。默认的时间间隔为 1 分钟。

  • debug:当此属性设置为 true 时,将打印出 logback 内部日志信息,实时查看 logback 运行状态。默认值为 false。

contextName

每个 logger 都关联到 logger 上下文,默认上下文名称为“default”。但可以使用 contextName 标签设置成其他名字,用于区分不同应用程序的记录

property

用来定义变量值的标签,property 标签有两个属性,name 和 value;其中 name 的值是变量的名称,value 的值是变量定义的值。通过 property 定义的值会被插入到 logger 上下文中。定义变量后,可以使“${name}”来使用变量。如上面的 xml 所示。

logger

用来设置某一个包或者具体的某一个类的日志打印级别以及指定 appender。

root

根 logger,也是一种 logger,且只有一个 level 属性

appender

负责写日志的组件,下面会细说

filter

filter 其实是 appender 里面的子元素。它作为过滤器存在,执行一个过滤器会有返回 DENY,NEUTRAL,ACCEPT 三个枚举值中的一个。

  • DENY:日志将立即被抛弃不再经过其他过滤器

  • NEUTRAL:有序列表里的下个过滤器过接着处理日志

  • ACCEPT:日志会被立即处理,不再经过剩余过滤器

案例分析

首先来配置一个非常简单的文件。这里申请下,我使用的是 logback-spring.xml。和 logback.xml 在 properties 上有略微差别。其他都一样。

工程:springboot+web

先来看下项目目录


properties 中就是指定了日志的打印级别和日志的输出位置:

#设置应用的日志级别logging.level.com.glmapper.spring.boot=INFO#路径logging.path=./logs复制代码
复制代码


通过控制台输出的 log

logback-spring.xml 的配置如下:

<configuration>    <!-- 默认的控制台日志输出,一般生产环境都是后台启动,这个没太大作用 -->    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">            <Pattern>%d{HH:mm:ss.SSS} %-5level %logger{80} - %msg%n</Pattern>        </encoder>    </appender>        <root level="info">        <appender-ref ref="STDOUT"/>    </root></configuration>复制代码
复制代码


打印日志的 controller

private static final Logger LOGGER =LoggerFactory.getLogger(HelloController.class);@Autowiredprivate TestLogService testLogService;
@GetMapping("/hello")public String hello(){ LOGGER.info("GLMAPPER-SERVICE:info"); LOGGER.error("GLMAPPER-SERVICE:error"); testLogService.printLogToSpecialPackage(); return "hello spring boot";}
复制代码


验证结果:

01:50:39.633 INFO  com.glmapper.spring.boot.controller.HelloController- GLMAPPER-SERVICE:info01:50:39.633 ERROR com.glmapper.spring.boot.controller.HelloController- GLMAPPER-SERVICE:error复制代码
复制代码

上面的就是通过控制台打印出来的,这个时候因为我们没有指定日志文件的输出,因为不会在工程目录下生产 logs 文件夹。

控制台不打印,直接输出到日志文件

先来看下配置文件:


<appender name="GLMAPPER-LOGGERONE"class="ch.qos.logback.core.rolling.RollingFileAppender">    <append>true</append>    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">        <level>${logging.level}</level>    </filter>    <file>        ${logging.path}/glmapper-spring-boot/glmapper-loggerone.log    </file>    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">        <FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-loggerone.log.%d{yyyy-MM-dd}</FileNamePattern>        <MaxHistory>30</MaxHistory>    </rollingPolicy>    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>        <charset>UTF-8</charset>    </encoder></appender>
<root level="info"> <appender-ref ref="GLMAPPER-LOGGERONE"/></root></configuration>复制代码
复制代码

这里我们 appender-ref 指定的 appender 是 GLMAPPER-LOGGERONE,因为之前没有名字为 GLMAPPER-LOGGERONE 的 appender,所以要增加一个 name 为 GLMAPPER-LOGGERONE 的 appender。

注意上面这个配置,我们是直接接将 root 的 appender-ref 直接指定到我们的 GLMAPPER-LOGGERONE 这个 appender 的。所以控制台中将只会打印出 bannar 之后就啥也不打印了,所有的启动信息都会被打印在日志文件 glmapper-loggerone.log 中。


但是实际上我们不希望我的业务日志中会包括这些启动信息。所以这个时候我们就需要通过 logger 标签来搞事情了。将上面的配置文件进行简单修改:

<logger name="com.glmapper.spring.boot.controller" level="${logging.level}"        additivity="false">    <appender-ref ref="GLMAPPER-LOGGERONE" /></logger>
<root level="${logging.level}"> <appender-ref ref="STDOUT"/></root>复制代码
复制代码

让 root 指向控制台输出;logger 负责打印包 com.glmapper.spring.boot.controller 下的日志。

验证结果

还是通过我们的测试 controller 来打印日志为例,但是这里不会在控制台出现日志信息了。期望的日志文件在./logs/glmapper-spring-boot/glmapper-loggerone.log。


logger 和 appender 的关系

上面两种是一个基本的配置方式,通过上面两个案例,我们先来了解下 logger/appender/root 之间的关系,然后再详细的说下 logger 和 appender 的配置细节。

在最前面介绍中提到,root 是根 logger,所以他两是一回事;只不过 root 中不能有 name 和 additivity 属性,只有一个 level。

appender 是一个日志打印的组件,这里组件里面定义了打印过滤的条件、打印输出方式、滚动策略、编码方式、打印格式等等。但是它仅仅是一个打印组件,如果我们不使用一个 logger 或者 root 的 appender-ref 指定某个具体的 appender 时,它就没有什么意义。

因此 appender 让我们的应用知道怎么打、打印到哪里、打印成什么样;而 logger 则是告诉应用哪些可以这么打。例如某个类下的日志可以使用这个 appender 打印或者某个包下的日志可以这么打印。

appender 配置详解

这里以上面案例中的名为 GLMAPPER-LOGGERONE 的 appender 说明:

<appender name="GLMAPPER-LOGGERONE"    class="ch.qos.logback.core.rolling.RollingFileAppender">    <append>true</append>    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">        <level>${logging.level}</level>    </filter>    <file>        ${logging.path}/glmapper-spring-boot/glmapper-loggerone.log    </file>    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">        <FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-loggerone.log.%d{yyyy-MM-dd}</FileNamePattern>        <MaxHistory>30</MaxHistory>    </rollingPolicy>    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>        <charset>UTF-8</charset>    </encoder></appender>复制代码
复制代码

appender 有两个属性 name 和 class;name 指定 appender 名称,class 指定 appender 的全限定名。上面声明的是名为 GLMAPPER-LOGGERONE,class 为 ch.qos.logback.core.rolling.RollingFileAppender 的一个 appender。

appender 的种类

  • ConsoleAppender:把日志添加到控制台

  • FileAppender:把日志添加到文件

  • RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。它是 FileAppender 的子类

append 子标签

<append>true</append>复制代码
复制代码

如果是 true,日志被追加到文件结尾,如果是 false,清空现存文件,默认是 true。

filter 子标签

在简介中提到了 filter;作用就是上面说的。可以为 appender 添加一个或多个过滤器,可以用任意条件对日志进行过滤。appender 有多个过滤器时,按照配置顺序执行。

ThresholdFilter

临界值过滤器,过滤掉低于指定临界值的日志。当日志级别等于或高于临界值时,过滤器返回 NEUTRAL;当日志级别低于临界值时,日志会被拒绝。

<filter class="ch.qos.logback.classic.filter.ThresholdFilter">    <level>INFO</level></filter>复制代码
复制代码

LevelFilter

级别过滤器,根据日志级别进行过滤。如果日志级别等于配置级别,过滤器会根据 onMath(用于配置符合过滤条件的操作) 和 onMismatch(用于配置不符合过滤条件的操作)接收或拒绝日志。

<filter class="ch.qos.logback.classic.filter.LevelFilter">     <level>INFO</level>     <onMatch>ACCEPT</onMatch>     <onMismatch>DENY</onMismatch>   </filter> 复制代码
复制代码

关于 NEUTRAL、ACCEPT、DENY 见上文简介中关于 filter 的介绍。

file 子标签

file 标签用于指定被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。

<file>    ${logging.path}/glmapper-spring-boot/glmapper-loggerone.log</file>复制代码
复制代码

这个表示当前 appender 将会将日志写入到 ${logging.path}/glmapper-spring-boot/glmapper-loggerone.log 这个目录下。

rollingPolicy 子标签

这个子标签用来描述滚动策略的。这个只有 appender 的 class 是 RollingFileAppender 时才需要配置。这个也会涉及文件的移动和重命名(a.log->a.log.2018.07.22)。

TimeBasedRollingPolicy

最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责触发滚动。这个下面又包括了两个属性:

  • FileNamePattern

  • maxHistory

<rollingPolicy     class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">    <!--日志文件输出的文件名:按天回滚 daily -->    <FileNamePattern>        ${logging.path}/glmapper-spring-boot/glmapper-loggerone.log.%d{yyyy-MM-dd}    </FileNamePattern>    <!--日志文件保留天数-->    <MaxHistory>30</MaxHistory></rollingPolicy>复制代码
复制代码

上面的这段配置表明每天生成一个日志文件,保存 30 天的日志文件

FixedWindowRollingPolicy

根据固定窗口算法重命名文件的滚动策略。

encoder 子标签

对记录事件进行格式化。他干了两件事:

  • 把日志信息转换成字节数组

  • 把字节数组写入到输出流

<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">    <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}    - %msg%n</pattern>    <charset>UTF-8</charset></encoder>复制代码
复制代码

目前 encoder 只有 PatternLayoutEncoder 一种类型。

定义一个只打印 error 级别日志的 appcener

 <!-- 错误日志 appender : 按照每天生成日志文件 --><appender name="ERROR-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">    <append>true</append>    <!-- 过滤器,只记录 error 级别的日志 -->    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">        <level>error</level>    </filter>    <!-- 日志名称 -->    <file>${logging.path}/glmapper-spring-boot/glmapper-error.log</file>    <!-- 每天生成一个日志文件,保存30天的日志文件 -->    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">        <!--日志文件输出的文件名:按天回滚 daily -->        <FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-error.log.%d{yyyy-MM-dd}</FileNamePattern>        <!--日志文件保留天数-->        <MaxHistory>30</MaxHistory>    </rollingPolicy>    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">        <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>        <!-- 编码 -->        <charset>UTF-8</charset>    </encoder></appender>复制代码
复制代码


定义一个输出到控制台的 appender

<!-- 默认的控制台日志输出,一般生产环境都是后台启动,这个没太大作用 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">        <Pattern>%d{HH:mm:ss.SSS} %-5level %logger{80} - %msg%n</Pattern>    </encoder></appender>复制代码
复制代码


logger 配置详解

<logger name="com.glmapper.spring.boot.controller"        level="${logging.level}" additivity="false">    <appender-ref ref="GLMAPPER-LOGGERONE" /></logger>复制代码
复制代码

上面的这个配置文件描述的是:com.glmapper.spring.boot.controller 这个包下的 ${logging.level}级别的日志将会使用 GLMAPPER-LOGGERONE 来打印。logger 有三个属性和一个子标签:

  • name:用来指定受此 logger 约束的某一个包或者具体的某一个类。

  • level:用来设置打印级别(TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF),还有一个值 INHERITED 或者同义词 NULL,代表强制执行上级的级别。如果没有设置此属性,那么当前 logger 将会继承上级的级别。

  • addtivity:用来描述是否向上级 logger 传递打印信息。默认是 true。

appender-ref 则是用来指定具体 appender 的。

不同日志隔离打印案例

在前面的例子中我们有三种 appender,一个是指定包约束的,一个是控制 error 级别的,一个是控制台的。然后这小节我们就来实现下不同日志打印到不同的 log 文件中。

根据包进行日志文件隔离

这个例子里我们将 com.glmapper.spring.boot.controller 中的日志输出到 glmapper-controller.log;将 com.glmapper.spring.boot.service 中的日志输出到 glmapper-service.log。

<!--打印日志到glmapper-service.log的appender--><appender name="GLMAPPER-SERVICE"          class="ch.qos.logback.core.rolling.RollingFileAppender">    <append>true</append>    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">        <level>${logging.level}</level>    </filter>    <file>        ${logging.path}/glmapper-spring-boot/glmapper-service.log    </file>    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">        <FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-service.log.%d{yyyy-MM-dd}</FileNamePattern>        <MaxHistory>30</MaxHistory>    </rollingPolicy>    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>        <charset>UTF-8</charset>    </encoder></appender>
<!--打印日志到glmapper-controller.log的appender--><appender name="GLMAPPER-CONTROLLER" class="ch.qos.logback.core.rolling.RollingFileAppender"> <append>true</append> <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>${logging.level}</level> </filter> <file> ${logging.path}/glmapper-spring-boot/glmapper-controller.log </file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-controller.log.%d{yyyy-MM-dd}</FileNamePattern> <MaxHistory>30</MaxHistory> </rollingPolicy> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> <charset>UTF-8</charset> </encoder></appender>
<!--此logger约束将.controller包下的日志输出到GLMAPPER-CONTROLLER,错误日志输出到GERROR-APPENDE;GERROR-APPENDE见上面--><logger name="com.glmapper.spring.boot.controller" level="${logging.level}" additivity="false"> <appender-ref ref="GLMAPPER-CONTROLLER" /> <appender-ref ref="GERROR-APPENDER" /></logger>
<!--此logger约束将.service包下的日志输出到GLMAPPER-SERVICE,错误日志输出到GERROR-APPENDE;GERROR-APPENDE见上面--><logger name="com.glmapper.spring.boot.service" level="${logging.level}" additivity="false"> <appender-ref ref="GLMAPPER-SERVICE" /> <appender-ref ref="GERROR-APPENDER" /></logger>复制代码
复制代码

来看运行结果

1、glmaper-controller

2、glmapper-service

3、glmapper-error


满足我们的预期,但是这里有个小问题。在 info 日志里出现了 error,当然这是正常的。假如我们不想在 info 里面出现 error 怎么办呢?很简单,我们以 APPENDER-SERVICE 为例,将 filter 过滤器进行修改:

将下面的:

<filter class="ch.qos.logback.classic.filter.ThresholdFilter">    <level>${logging.level}</level></filter>复制代码
复制代码

修改为:

<filter class="ch.qos.logback.classic.filter.LevelFilter">    <level>ERROR</level>    <!-- 如果命中就禁止这条日志 -->    <onMatch>DENY</onMatch>      <!-- 如果没有命中就使用这条规则 -->    <onMismatch>ACCEPT</onMismatch>  </filter>复制代码
复制代码

这里同时要注意的是,在 logger 中 level 需要设置为 info 级别。

根据类进行日志文件隔离

这个其实也是和上面那个差不过,只不过粒度更细一点,一般情况下比如说我们有个定时任务类需要单独来记录其日志信息,这样我们就可以考虑使用基于类维度来约束打印

<!--特殊功能单独appender 例如调度类的日志--><appender name="SCHEDULERTASKLOCK-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">    <append>true</append>    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">        <level>${logging.level}</level>    </filter>    <file>${logging.path}/glmapper-spring-boot/scheduler-task-lock.log</file>    <!-- 每天生成一个日志文件,保存30天的日志文件 -->    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">        <!--日志文件输出的文件名:按天回滚 daily -->        <FileNamePattern>${logging.path}/glmapper-spring-boot/scheduler-task-lock.log.%d{yyyy-MM-dd}</FileNamePattern>        <!--日志文件保留天数-->        <MaxHistory>30</MaxHistory>    </rollingPolicy>    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">        <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>        <!-- 编码 -->        <charset>UTF-8</charset>    </encoder></appender>
<!--这里指定到了具体的某一个类--><logger name="com.glmapper.spring.boot.task.TestLogTask" level="${logging.level}" additivity="true"> <appender-ref ref="SCHEDULERTASKLOCK-APPENDER" /> <appender-ref ref="ERROR-APPENDER" /> </logger>复制代码
复制代码

最终 TestLogTask 中的日志将会被打印到这个自己独立的 log 文件中。如下所示:


根据自定义 logger 的 name 进行日志文件隔离

ogger 的 name 除了类、包等约束之外,当然还可以这样来玩。。。

在进行案例之前,这里先把前面案例中 logger 声明的代码贴一下,以作对比,以 TestLogTask 类中的日志为例:

private static final Logger LOGGER = LoggerFactory.getLogger(TestLogTask.class);复制代码
复制代码

在 getLogger 中我们是将当前对象的 class 作为参数的,这个是为了打印时获取其全限定名的(见下面 3-)。

1-2018-07-21 11:15:42.003 [pool-1-thread-1] 2-INFO  3-com.glmapper.spring.boot.task.TestLogTask -4-com.glmapper.spring.boot.task:info复制代码
复制代码

业务类定义

我们同样是 service 包下定义一个类 TestLogNameServiceImpl

package com.glmapper.spring.boot.service;
@Service("testLogNameService")public class TestLogNameServiceImpl implements TestLogNameService {
private static final Logger LOGGER = LoggerFactory.getLogger("GLMAPPER-TEST-LOG");
@Override public void print() { LOGGER.info("GLMAPPER-TEST-LOG:this is special logger-----info"); LOGGER.error("GLMAPPER-TEST-LOG:this is special logger-------error"); }}复制代码
复制代码


appender 和 logger 配置

<appender name="ROOT-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">    <append>true</append>    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">        <level>${logging.level}</level>    </filter>    <file>${logging.path}/glmapper-spring-boot/glmapper-test.log</file>    <!-- 每天生成一个日志文件,保存30天的日志文件 -->    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">        <!--日志文件输出的文件名:按天回滚 daily -->        <FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-test.log.%d{yyyy-MM-dd}        </FileNamePattern>        <!--日志文件保留天数-->        <MaxHistory>30</MaxHistory>    </rollingPolicy>    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">        <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>        <!-- 编码 -->        <charset>UTF-8</charset>    </encoder></appender>
<!--这里的name和业务类中的getLogger中的字符串是一样的--><logger name="GLMAPPER-TEST-LOG" level="${logging.level}" additivity="true"> <appender-ref ref="ROOT-APPENDER" /> <appender-ref ref="ERROR-APPENDER" /> </logger>复制代码
复制代码

我们这个预期的是 TestLogNameServiceImpl 中的日志不打印到 glmapper-service.log 中,而是打印到 glmapper-test.log 中。

1、glmapper-test.log

2、glmapper-service.log


满足我们的预期。

如何使用 logback 打印 mybatis 的 sql 语句

这个还是比较坑的。为什么。看下这个:

<settings>    <setting name="logImpl" value="slf4j" /></settings>复制代码
复制代码

在 mybatis-configration.xml 中,我们通过这样一个配置项来关联到具体的日志组件。但是 logImpl 的实现中是没有 logback 的。那么怎么办呢?这里只能通过 slf4j 的方式桥接到 logback。

然后在我们的 logback-spring.xml 中进行如下配置:

 <!-- 将sql语句输出到具体的日志文件中 --><logger name="com.alipay.sofa.cloudplatform.common.dao" level="${logging.sql.level}" additivity="false">    <appender-ref ref="SQL-APPENDER"/></logger>复制代码
复制代码

这里有几个点需要注意的。首先是 ${logging.sql.level}这个必须是 debug,这个是由 mybatis 本身实现决定的。而这里的 name 设定的 com.alipay.sofa.cloudplatform.common.dao 值就是我们 dao 接口的包路径。

网上看了一个比较典型的案例,这种方式只能输出到控制台,并不能将文件输出到日志文件;它是根据内部的一个实现机制偷了个懒。mybatis 用 logback 日志不显示 sql 的解决办法。

总结

本篇博客主要是整理最近工作中的一些日志配置积累,将每个细节进行总结一下,以作备忘。如果有时间的话会考虑看一个日志框架的源码。其实我觉得还是很有必要的,日志组件毕竟是需要进行日志文件落盘的,这个会涉及到许多的性能问题、缓冲区问题、队列问题、当然还有一些锁的问题、同步打印或者异步打印等问题。有兴趣的小伙伴可以看看,然后分享给我们。

后面准备写一写蚂蚁金服 SOFABoot 和 SpringBoot 的一些文章,如果有兴趣可以先看一波。

原文链接:https://juejin.cn/post/6844903641535479821

最后,小编还给大家整理了一份面试宝典 有需要的添加小助理 vx:mxzFAFAFA 来领取



发布于: 2021 年 04 月 28 日阅读数: 87
用户头像

比伯

关注

还未添加个人签名 2020.11.09 加入

还未添加个人简介

评论

发布
暂无评论
精彩3000字!给讲得明明白白:配置 logback