You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spring的logback-spring.xml中过滤特定SQL查询日志?

解决Logback过滤MyBatis特定启动SQL日志的问题

我来帮你搞定这个问题!你遇到的核心痛点是:MyBatis输出SQL日志时,你加的注释-- NOT_SQL_LOG和SQL主体会被拆分成独立的日志事件,所以你的自定义Logback拦截器只过滤了注释那一行,没覆盖整个SQL的查询、参数、结果日志。另外你用EvaluatorFilter启动失败,大概率是因为缺少必要的依赖库。下面给你几个可行的解决方案:

方案一:利用MDC标记+Logback过滤(业务代码侵入式)

这种方法需要在启动时执行的SQL调用逻辑里添加MDC标记,让Logback识别并过滤这些日志:

  1. 在业务代码中添加MDC标记
    在你启动时调用的retrieveMessage方法里,用MDC临时标记需要过滤的SQL:

    import org.slf4j.MDC;
    
    public Message retrieveMessage(String param) {
        try {
            // 标记需要跳过日志的SQL
            MDC.put("SKIP_SQL_LOG", "true");
            return sqlSessionTemplate.selectOne("retrieveMessage", param);
        } finally {
            // 执行完毕后移除标记,避免影响其他SQL
            MDC.remove("SKIP_SQL_LOG");
        }
    }
    
  2. 修改Logback配置
    更新你的STDOUT-SQL-RESULTSET appender,添加基于MDC的EvaluatorFilter(记得先补全依赖):

    <appender name="STDOUT-SQL-RESULTSET" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
            <evaluator>
                <!-- 判断MDC中是否存在标记 -->
                <expression>mdc.get("SKIP_SQL_LOG") != null && mdc.get("SKIP_SQL_LOG").equals("true")</expression>
            </evaluator>
            <OnMatch>DENY</OnMatch> <!-- 匹配到标记就拒绝输出 -->
            <OnMismatch>NEUTRAL</OnMismatch> <!-- 不匹配则继续后续过滤 -->
        </filter>
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%msg%n</pattern>
        </encoder>
    </appender>
    
  3. 补充依赖(解决EvaluatorFilter启动失败)
    Logback的EvaluatorFilter依赖Janino库,需要在pom.xml中添加:

    <dependency>
        <groupId>org.codehaus.janino</groupId>
        <artifactId>janino</artifactId>
        <version>3.1.11</version> <!-- 用最新稳定版即可 -->
    </dependency>
    

方案二:自定义MyBatis拦截器(无业务代码侵入)

这种方法通过MyBatis的拦截器机制,自动识别带特定注释的SQL并标记MDC,不需要修改业务代码:

  1. 编写MyBatis拦截器
    拦截MyBatis的SQL执行过程,识别带-- NOT_SQL_LOG注释的SQL并添加MDC标记:

    import org.apache.ibatis.executor.statement.StatementHandler;
    import org.apache.ibatis.plugin.*;
    import org.apache.ibatis.session.ResultHandler;
    import org.slf4j.MDC;
    
    import java.sql.Connection;
    import java.util.Properties;
    
    @Intercepts({
            @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
    })
    public class SkipSqlLogInterceptor implements Interceptor {
    
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
            StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
            String sql = statementHandler.getBoundSql().getSql().trim();
            // 判断SQL是否包含需要跳过日志的注释
            if (sql.startsWith("-- NOT_SQL_LOG")) {
                MDC.put("SKIP_SQL_LOG", "true");
            }
            try {
                return invocation.proceed();
            } finally {
                // 执行完毕后移除标记
                MDC.remove("SKIP_SQL_LOG");
            }
        }
    
        @Override
        public Object plugin(Object target) {
            return Plugin.wrap(target, this);
        }
    
        @Override
        public void setProperties(Properties properties) {
            // 可配置自定义参数,这里暂时不需要
        }
    }
    
  2. 注册MyBatis拦截器
    在Spring Boot中,通过@Bean注册拦截器:

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class MyBatisConfig {
        @Bean
        public SkipSqlLogInterceptor skipSqlLogInterceptor() {
            return new SkipSqlLogInterceptor();
        }
    }
    
  3. 复用方案一的Logback配置
    直接使用方案一中的Logback过滤器配置即可,不需要额外修改。

方案三:直接通过SQL内容过滤(简单但不够灵活)

如果你能确定启动时的SQL有唯一的特征(比如特定的表名或查询内容),可以直接在Logback中过滤包含该特征的日志:

<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
    <evaluator>
        <expression>message.contains("blahblah")</expression> <!-- 替换为你的SQL特征 -->
    </evaluator>
    <OnMatch>DENY</OnMatch>
    <OnMismatch>NEUTRAL</OnMismatch>
</filter>

这种方法的缺点是如果运行时也有相同特征的SQL,会被误过滤,所以仅适合启动SQL有唯一标识的场景。

为什么你之前的方法无效?

  • 自定义Logback拦截器只过滤了包含NOT_SQL_LOG的单条日志事件,但MyBatis会把注释、SQL准备、参数、结果拆分成多条日志,所以只有注释行被过滤,其他日志依然输出。
  • EvaluatorFilter启动失败是因为缺少Janino依赖,补全依赖后就能正常工作。

内容的提问来源于stack exchange,提问作者user11269434

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:53:22