配置MyBatis SQL拦截器 Interceptor

本文介绍如何在MyBatis中实现自定义拦截器,包括配置数据源、SqlSessionFactory及事务管理器的过程,展示了如何通过拦截器监控SQL语句执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自定义拦截器实现接口Interceptor:

package com.feifan.interceptor;

import java.util.Properties;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.scripting.defaults.RawSqlSource;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

/**
 * Mybatis 拦截器 允许使用的插件来拦截的方法包括 Executor (update, query, flushStatements, commit, rollback, getTransaction, close,
 * isClosed) ParameterHandler (getParameterObject, setParameters)
 * ResultSetHandler(handleResultSets,handleOutputParameters) StatementHandler (prepare, parameterize, batch, update,
 * query)
 * 
 * @author Donald
 * @date 2019/01/21
 * @see
 */
@Configuration
@Component
@Intercepts({@Signature(type = Executor.class, method = "query",
    args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
public class MysqlInterceptor implements Interceptor {

    private static final Logger LOGGER = LoggerFactory.getLogger(MysqlInterceptor.class);

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // TODO Auto-generated method stub
        Object[] args = invocation.getArgs();
        MappedStatement ms = (MappedStatement)args[0];
        String mapperMethod = ms.getId();
        RawSqlSource sqlSource = (RawSqlSource)ms.getSqlSource();
        BoundSql sql = sqlSource.getBoundSql(null);
        LOGGER.info("mybatis intercept sql:{},Mapper方法是:{}", sql.getSql(), mapperMethod);
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        // TODO Auto-generated method stub
        LOGGER.info("MysqlInterCeptor plugin>>>>>>>{}", target);
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        // TODO Auto-generated method stub
        String dialect = properties.getProperty("dialect");
        LOGGER.info("mybatis intercept dialect:>>>>>>>{}", dialect);
    }

}
  • 在SqlSessionFactory 注册 SQL 拦截器
 @Bean("sqlSessionFactory")
    public SqlSessionFactory getSqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        // 读取mapper 配置文件
        Resource[] resources = new PathMatchingResourcePatternResolver().getResources("classpath:mappers/*Mapper.xml");
        factoryBean.setMapperLocations(resources);
        factoryBean.setTypeAliasesPackage("com.feifan.to");
        // 配置驼峰命名规则
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        configuration.setMapUnderscoreToCamelCase(true);
        factoryBean.setConfiguration(configuration);
        // 加入SQL 语句执行拦截器
        factoryBean.setPlugins(new Interceptor[] {new MysqlInterceptor()});
        return factoryBean.getObject();
    }

MyBatis 配置类

package com.feifan.configure;

import javax.sql.DataSource;

import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.server.ConfigurableWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.http.HttpStatus;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.alibaba.druid.pool.DruidDataSource;
import com.feifan.interceptor.MysqlInterceptor;

/**
 * Mybatis 配置类 不通过springboot 使用自己配置的数据源
 * 
 * @author Donald
 * @date 2019/01/19
 * @see
 */
@Configuration
// @ConfigurationProperties // 读区主配置文件application.properties
@PropertySource(value = {"MyBatis.properties"})
public class MyBatisConfig {

    // 配置数据源
    @Bean(value = "dataSource", destroyMethod = "close", initMethod = "init")
    public DataSource getDataSource(@Value("${spring.datasource.driver-class-name}") String driver,
        @Value("${spring.datasource.url}") String url, @Value("${spring.datasource.username}") String username,
        @Value("${spring.datasource.password}") String password) {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setInitialSize(2);
        dataSource.setMaxActive(100);
        dataSource.setMaxWait(30000);
        dataSource.setPoolPreparedStatements(false);
        dataSource.setDefaultAutoCommit(false);
        return dataSource;
    }

    // sqlsessionFactory
    @Bean("sqlSessionFactory")
    public SqlSessionFactory getSqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        // 读取mapper 配置文件
        Resource[] resources = new PathMatchingResourcePatternResolver().getResources("classpath:mappers/*Mapper.xml");
        factoryBean.setMapperLocations(resources);
        factoryBean.setTypeAliasesPackage("com.feifan.to");
        // 配置驼峰命名规则
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        configuration.setMapUnderscoreToCamelCase(true);
        factoryBean.setConfiguration(configuration);
        // 加入SQL 语句执行拦截器
        factoryBean.setPlugins(new Interceptor[] {new MysqlInterceptor()});
        return factoryBean.getObject();
    }

    // 配置事务管理器
    @Bean
    public DataSourceTransactionManager getDatasourceTrans(@Qualifier("dataSource") DataSource dataSource) {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }

    @Bean
    public SqlSessionTemplate geSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        SqlSessionTemplate sessionTemplate = new SqlSessionTemplate(sqlSessionFactory);
        return sessionTemplate;
    }

    /**
     * 以编程方式配置嵌入式servlet容器,可以通过注册实现该 WebServerFactoryCustomizer 接口的Spring bean
     * TomcatServletWebServerFactory,JettyServletWebServerFactory并且UndertowServletWebServerFactory 是专用变体,
     * ConfigurableServletWebServerFactory分别为Tomcat,Jetty和Undertow提供了额外的自定义setter方法。
     * 
     * @return
     */
    @Bean
    public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer() {
        return new WebServerFactoryCustomizer<ConfigurableWebServerFactory>() {
            @Override
            public void customize(ConfigurableWebServerFactory factory) {
                // 对嵌入式servlet容器的配置
                // factory.setPort(8081);
                /* 注意:new ErrorPage(stat, path);中path必须是页面名称,并且必须“/”开始。
                    底层调用了String.java中如下方法:
                    public boolean startsWith(String prefix) {
                        return startsWith(prefix, 0);
                    }*/
                ErrorPage errorPage400 = new ErrorPage(HttpStatus.BAD_REQUEST, "/service/error");
                ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/service/error-400");
                ErrorPage errorPage500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/service/error");
                factory.addErrorPages(errorPage400, errorPage404, errorPage500);
            }
        };

    }

}

部分参考路径:

https://github.com/DonaldAndMickey/Boke.git

<think>嗯,用户想了解如何在Spring Boot中配置MyBatisSQL拦截器。首先,我需要回忆一下MyBatis拦截器机制。MyBatis拦截器可以用于在SQL执行前后进行一些处理,比如日志记录、性能监控、分页处理等。用户可能是想实现类似的功能。 接下来,我应该考虑如何在Spring Boot项目中配置这个拦截器。首先,用户需要创建一个实现MyBatisInterceptor接口的类,并重写intercept方法。这里可能需要举一个例子,比如记录SQL执行时间,这样用户更容易理解。 然后,需要使用@Intercepts注解来指定拦截的方法,比如Executor类的update和query方法。同时,在配置类中,通过@Bean方法将拦截器注册到SqlSessionFactory中。这里需要注意,如果用户已经使用了MyBatis的starter,可能需要通过BeanPostProcessor来处理,或者在配置类中手动添加拦截器。 另外,要提醒用户注意拦截器的顺序,如果有多个拦截器的话,执行顺序可能会影响结果。还要提到可能的常见应用场景,比如分页、敏感数据加密、SQL日志等,这样用户能更好地了解拦截器的用途。 最后,检查是否有遗漏的步骤,比如Maven依赖是否正确,是否需要额外的配置。确保示例代码的正确性,特别是@Configuration类的配置部分,以及拦截器本身的实现。可能还需要提到使用@Signature注解来指定拦截的具体方法参数,避免用户在这里出错。</think>在Spring Boot中配置MyBatis SQL拦截器可以通过以下步骤实现(以记录SQL执行时间的拦截器为例): --- ### 一、创建拦截器类 ```java @Intercepts({ @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}), @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}) }) public class SqlCostInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { long start = System.currentTimeMillis(); try { return invocation.proceed(); // 执行原方法 } finally { long cost = System.currentTimeMillis() - start; String sqlId = ((MappedStatement) invocation.getArgs()[0]).getId(); System.out.println("SQL [" + sqlId + "] 执行耗时:" + cost + "ms"); } } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { // 可读取配置文件中的参数 } } ``` --- ### 二、注册拦截器配置类中将拦截器注册到MyBatis: ```java @Configuration public class MyBatisConfig { @Bean public SqlCostInterceptor sqlCostInterceptor() { return new SqlCostInterceptor(); } @Bean public ConfigurationCustomizer mybatisConfigurationCustomizer() { return configuration -> { configuration.addInterceptor(sqlCostInterceptor()); }; } } ``` --- ### 三、添加必要依赖 确保`pom.xml`包含: ```xml <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>3.0.3</version> </dependency> ``` --- ### 四、拦截器常见用途 1. **SQL性能监控**:记录执行时间 2. **分页处理**:自动改写分页SQL 3. **敏感数据加密**:加解密特定字段 4. **SQL日志记录**:输出完整可执行的SQL 5. **租户隔离**:自动添加tenant_id条件 --- ### 注意事项 - 多个拦截器按注册顺序执行 - 谨慎处理`invocation.proceed()`的返回值 - 避免在拦截器中执行耗时操作 - 通过`@Signature`精确指定要拦截的方法 可以通过`@Intercepts`注解组合多个拦截点,实现更复杂的SQL监控需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值