SpringBoot Mybatis 初始化加载mybatis拦截器

发布时间:2021-04-17作者:laosun阅读(940)

    首先我们定义一个拦截所有SQL的拦截器,代码如下(代码网上随便找了一个,主要是代码行数多):

    /**
     *                     .::::.
     *                   .::::::::.
     *                  :::::::::::    佛主保佑、永无Bug
     *              ..:::::::::::'
     *            '::::::::::::'
     *              .::::::::::
     *         '::::::::::::::..
     *              ..::::::::::::.
     *            ``::::::::::::::::
     *             ::::``:::::::::'        .:::.
     *            ::::'   ':::::'       .::::::::.
     *          .::::'      ::::     .:::::::'::::.
     *         .:::'       :::::  .:::::::::' ':::::.
     *        .::'        :::::.:::::::::'      ':::::.
     *       .::'         ::::::::::::::'         ``::::.
     *   ...:::           ::::::::::::'              ``::.
     *  ```` ':.          ':::::::::'                  ::::..
     *                     '.:::::'                    ':'````..
     */
    
    import com.alibaba.fastjson.JSON;
    import org.apache.ibatis.cache.CacheKey;
    import org.apache.ibatis.executor.Executor;
    import org.apache.ibatis.mapping.BoundSql;
    import org.apache.ibatis.mapping.MappedStatement;
    import org.apache.ibatis.mapping.ParameterMapping;
    import org.apache.ibatis.plugin.*;
    import org.apache.ibatis.session.ResultHandler;
    import org.apache.ibatis.session.RowBounds;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    import java.util.Collection;
    import java.util.List;
    import java.util.Properties;
    
    /**
     * @Date 2021-04-17 21:49
     */
    @Intercepts(value = {
            @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,
                            CacheKey.class, BoundSql.class}),
            @Signature(type = Executor.class,
                    method = "query",
                    args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
    @Component
    public class SqlInterceptor implements Interceptor {
    
        private static final Logger logger = LoggerFactory.getLogger(SqlInterceptor.class);
    
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
            Object target = invocation.getTarget();
            Object result = null;
            if (target instanceof Executor) {
                long start = System.currentTimeMillis();
                Method method = invocation.getMethod();
                /**执行方法*/
                result = invocation.proceed();
                long end = System.currentTimeMillis();
                final Object[] args = invocation.getArgs();
    
                //获取原始的ms
                MappedStatement ms = (MappedStatement) args[0];
                String commandName = ms.getSqlCommandType().name();
                String name = method.getName();
                if (commandName.startsWith("INSERT")) {
                    name += "=新增";
                } else if (commandName.startsWith("UPDATE")) {
                    name += "=修改";
                } else if (commandName.startsWith("DELETE")) {
                    name += "=删除";
                } else if (commandName.startsWith("SELECT")) {
                    name += "=查询";
                }
                String message = "[SqlInterceptor] execute [" + name + "] cost [" + (end - start) + "] ms";
                StringBuffer stringBuffer = new StringBuffer();
                stringBuffer.append(message);
                stringBuffer.append("\n");
    
                Object parameterObject = args[1];
                BoundSql boundSql = ms.getBoundSql(parameterObject);
                String sql = boundSql.getSql();
                List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
                String parameterObjects = JSON.toJSONString(boundSql.getParameterObject());
    
    
                String id = ms.getId();
                stringBuffer.append("id=" + id);
                stringBuffer.append("\r\n");
    
                stringBuffer.append("sql=" + sql);
                stringBuffer.append("\n");
    
                stringBuffer.append("parameterMappings=" + parameterMappings);
                stringBuffer.append("\n");
    
                stringBuffer.append("parameterObjects=" + parameterObjects);
                stringBuffer.append("\n");
                // stringBuffer.append("result="+result);
                if (result != null) {
                    if (result instanceof List) {
                        stringBuffer.append("result=" + ((List) result).size());
                    } else if (result instanceof Collection) {
                        stringBuffer.append("result=" + ((Collection) result).size());
                    } else {
                        stringBuffer.append("result=" + 1);
                    }
                } else {
                    stringBuffer.append("result=NULL");
                }
                stringBuffer.append("\n");
                logger.warn(stringBuffer.toString());
                //数组可能为空
                // ParameterMapping mapping = boundSql.getParameterMappings().get(0);
                // Configuration configuration = ms.getConfiguration();
                //  DynamicContext context = new DynamicContext(configuration, parameterObject);
                //   String originSql = context.getSql();
                //  System.out.println("@@@@originSql:"+originSql);
            }
            return result;
        }
    
        @Override
        public Object plugin(Object target) {
            return Plugin.wrap(target, this);
        }
    
        @Override
        public void setProperties(Properties properties) {
    
        }
    }

    然后将该类放到SpringBoot启动时包的扫描范围下即可,类增加注释:@Component。



    在springboot中要给mybatis加上这个拦截器,有三种方法,前两种方法在启动项目时不会自动调用自定义拦截器的setProperties方法。


    第一种

    直接给自定义拦截器添加一个 @Component注解,当调用sql时结果如下,可以看到拦截器生效了,但是启动时候并没有自动调用setProperties方法。可以在初始化自定义拦截器的时候通过 @Value 注解直接初始化需要的参数。


    第二种

    在配置类里添加拦截器,这种方法结果同上,也不会自动调用setProperties方法。可以在初始化自定义拦截器的时候通过 @Value 注解直接初始化需要的参数。

    @Configuration
    public class MybatisConfig {
        @Bean
        ConfigurationCustomizer mybatisConfigurationCustomizer() {
            return new ConfigurationCustomizer() {
                @Override
                public void customize(org.apache.ibatis.session.Configuration configuration) {
                    configuration.addInterceptor(new SqlInterceptor());
                }
            };
        }
    }

    第三种

    这种方法就是跟以前的配置方法类似,在yml配置文件中指定mybatis的xml配置文件,注意config-location属性和configuration属性不能同时指定。

    mybatis:
      config-location: classpath:mybatis.xml
      type-aliases-package: com.xxx.model
      mapper-locations: classpath:mapper/*.xml

    mybatis.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <typeAliases>
            <package name="com.xxx.model"/>
        </typeAliases>
        <plugins>
            <plugin interceptor="com.xxx.interceptor.SqlInterceptor"> 
                <property name="dialect" value="mysql"/>
            </plugin>
        </plugins>
    </configuration>


0 +1

版权声明

 Java  源码  springboot  mybatis

 请文明留言

1 条评论