美文网首页
Spring boot Mybatis Plus 日志打印插件

Spring boot Mybatis Plus 日志打印插件

作者: 惜时流光沿途留殇 | 来源:发表于2021-04-14 22:56 被阅读0次

    插件类

    import java.lang.reflect.Field;
    import java.sql.Statement;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.List;
    import java.util.Properties;
    
    import org.apache.commons.lang.StringUtils;
    import org.apache.ibatis.executor.statement.StatementHandler;
    import org.apache.ibatis.mapping.BoundSql;
    import org.apache.ibatis.mapping.ParameterMapping;
    import org.apache.ibatis.mapping.ParameterMode;
    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.reflection.MetaObject;
    import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
    import org.apache.ibatis.session.Configuration;
    import org.apache.ibatis.session.ResultHandler;
    import org.apache.ibatis.type.TypeHandlerRegistry;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.core.Ordered;
    import org.springframework.util.ReflectionUtils;
    
    
    @Intercepts({
            @Signature(type = StatementHandler.class, method = "query", args = { Statement.class, ResultHandler.class }),
            @Signature(type = StatementHandler.class, method = "update", args = { Statement.class }),
            @Signature(type = StatementHandler.class, method = "batch", args = { Statement.class }) })
    public class MybatisSqlPrintIntercepter implements Interceptor, Ordered {
        private static final Logger logger = LoggerFactory.getLogger(MybatisSqlPrintIntercepter.class);
        private Configuration configuration = null;
    
        private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT_THREAD_LOCAL = new ThreadLocal<SimpleDateFormat>() {
            @Override
            protected SimpleDateFormat initialValue() {
                return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
            }
        };
    
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
            Object target = invocation.getTarget();
            long startTime = System.currentTimeMillis();
            try {
                return invocation.proceed();
            } finally {
                try {
                    long endTime = System.currentTimeMillis();
                    long sqlCost = endTime - startTime;
                    StatementHandler statementHandler = (StatementHandler) target;
                    BoundSql boundSql = statementHandler.getBoundSql();
                    if (configuration == null) {
                        final DefaultParameterHandler parameterHandler = (DefaultParameterHandler) statementHandler
                                .getParameterHandler();
                        Field configurationField = ReflectionUtils.findField(parameterHandler.getClass(), "configuration");
                        ReflectionUtils.makeAccessible(configurationField);
                        this.configuration = (Configuration) configurationField.get(parameterHandler);
                    }
                    // 替换参数格式化Sql语句,去除换行符
                    String sql = formatSql(boundSql, configuration).concat(";");
                    String  warning = "";
                    if(sqlCost > 100) {
                        warning  = "[耗时过长]";
                    }
                    logger.info("SQL==> {}    执行耗时:{} ms {}", sql, sqlCost,warning);
    
                } catch (Exception e) {
                    logger.error("==> 打印sql 日志异常 {}",e);
                }
            }
        }
    
        @Override
        public Object plugin(Object target) {
            return Plugin.wrap(target, this);
        }
    
        @Override
        public void setProperties(Properties properties) {
    
        }
    
        /**
         * 获取完整的sql实体的信息
         *
         * @param boundSql
         * @return
         */
        private String formatSql(BoundSql boundSql, Configuration configuration) {
            String sql = boundSql.getSql();
            List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
            Object parameterObject = boundSql.getParameterObject();
            // 输入sql字符串空判断
            if (StringUtils.isBlank(sql)) {
                return "";
            }
            if (configuration == null) {
                return "";
            }
            TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
            sql = beautifySql(sql);
            // 参考mybatis 源码 DefaultParameterHandler
            if (parameterMappings != null) {
                for (ParameterMapping parameterMapping : parameterMappings) {
                    if (parameterMapping.getMode() != ParameterMode.OUT) {
                        Object value;
                        String propertyName = parameterMapping.getProperty();
                        if (boundSql.hasAdditionalParameter(propertyName)) {
                            value = boundSql.getAdditionalParameter(propertyName);
                        } else if (parameterObject == null) {
                            value = null;
                        } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
                            value = parameterObject;
                        } else {
                            MetaObject metaObject = configuration.newMetaObject(parameterObject);
                            value = metaObject.getValue(propertyName);
                        }
                        String paramValueStr = "";
                        if (value instanceof String) {
                            paramValueStr = "'" + value + "'";
                        } else if (value instanceof Date) {
                            paramValueStr = "'" + DATE_FORMAT_THREAD_LOCAL.get().format(value) + "'";
                            DATE_FORMAT_THREAD_LOCAL.remove();
                        } else {
                            paramValueStr = value + "";
                        }
                        sql = sql.replaceFirst("\\?", paramValueStr);
    
    
                    }
                }
            }
            return sql;
        }
    
        private String beautifySql(String sql) {
            sql = sql.replaceAll("[\\s\n ]+", " ");
            return sql;
        }
    
        @Override
        public int getOrder() {
            return Ordered.HIGHEST_PRECEDENCE;
        }
    
    }
    
    

    注入

    import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
    import com.baomidou.mybatisplus.core.MybatisConfiguration;
    import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    /**
     * @Description
     * @Author
     * @Date
     */
    @Configuration
    public class MybatisPlusConfig {
        /**
         *   mybatis-plus分页插件
         */
        @Bean
        public PaginationInterceptor paginationInterceptor() {
            PaginationInterceptor page = new PaginationInterceptor();
            page.setDialectType("mysql");
            return page;
        }
    
        @Bean
        public MybatisSqlPrintIntercepter mybatisSqlPrintIntercepter() {
            return new MybatisSqlPrintIntercepter();
        }
    
    
    }
    

    相关文章

      网友评论

          本文标题:Spring boot Mybatis Plus 日志打印插件

          本文链接:https://www.haomeiwen.com/subject/bjrrlltx.html