暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Sql执行时间记录拦截器

IT学习道场 2023-02-01
352

直接上代码,自己看,粘贴可用

    package com.example.demo.mybatis;


    import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
    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.*;
    import org.apache.ibatis.reflection.MetaObject;
    import org.apache.ibatis.session.ResultHandler;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    import java.sql.Statement;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Properties;


    /**
    * 描述:Sql执行时间记录拦截器 </br>
    * 作者:王林冲 </br>
    * 时间:2022-12-12 14:11
    */
    @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})})
    @Component
    public class SqlExecuteTimeCountInterceptor implements Interceptor {


    private static Logger logger = LoggerFactory.getLogger(SqlExecuteTimeCountInterceptor.class);


    /**
    * 打印的参数字符串的最大长度
    */
    private final static int MAX_PARAM_LENGTH = 50;


    /**
    * 记录的最大SQL长度
    */
    private final static int MAX_SQL_LENGTH = 200;




    @Override
    public Object intercept(Invocation invocation) throws Throwable {
    Object target = invocation.getTarget();
    long startTime = System.currentTimeMillis();
    StatementHandler statementHandler = (StatementHandler) target;
    try {
    return invocation.proceed();
    } finally {
    long endTime = System.currentTimeMillis();


    long timeCount = endTime - startTime;
    //获取BoundSql
    BoundSql boundSql = statementHandler.getBoundSql();
    //获取原始sql
    String sql = boundSql.getSql();
    Object parameterObject = boundSql.getParameterObject();
    List<ParameterMapping> parameterMappingList = boundSql.getParameterMappings();


    // 格式化Sql语句,去除换行符,替换参数
    sql = formatSQL(sql, parameterObject, parameterMappingList);


    logger.info("=======> 执行 SQL:{} 执行耗时 {} ms", sql, timeCount);


    PluginUtils.MPStatementHandler mpStatementHandler = PluginUtils.mpStatementHandler(statementHandler);
    List<String> paramList = handleParameterToStr(mpStatementHandler);
    String paramStr = String.join(", ", paramList);
                logger.info("=======> 条件参数:{}" ,paramStr );
    }
    }








    private List<Object> handleParameter(PluginUtils.MPStatementHandler mpSh) {
    List<Object> values = new ArrayList();
    Object parameterObject = mpSh.boundSql().getParameterObject();
    List<ParameterMapping> parameterMappings = mpSh.boundSql().getParameterMappings();
    if (parameterMappings != null) {
    Iterator var5 = parameterMappings.iterator();


    while(var5.hasNext()) {
    ParameterMapping parameterMapping = (ParameterMapping)var5.next();
    if (parameterMapping.getMode() != ParameterMode.OUT) {
    String propertyName = parameterMapping.getProperty();
    Object value;
    if (mpSh.boundSql().hasAdditionalParameter(propertyName)) {
    value = mpSh.boundSql().getAdditionalParameter(propertyName);
    } else if (parameterObject == null) {
    value = null;
    } else if (mpSh.configuration().getTypeHandlerRegistry().hasTypeHandler(parameterObject.getClass())) {
    value = parameterObject;
    } else {
    MetaObject metaObject = mpSh.configuration().newMetaObject(parameterObject);
    value = metaObject.getValue(propertyName);
    }


    values.add(value);
    }
    }
    }
    return values;
    }


    private List<String> handleParameterToStr(PluginUtils.MPStatementHandler mpSh) {
    List<Object> objects = handleParameter(mpSh);
    List<String> values = new ArrayList<>(objects.size());
    objects.forEach(e -> {
    values.add(objToStr(e));
    });
    return values;
    }


    private String objToStr (Object o){
    StringBuffer sb =new StringBuffer(o.toString());
    sb.append("(");
    sb.append(o.getClass().getSimpleName()) ;
    sb.append(")");
    String str = sb.toString();
    return str;
    }




    /**
    * 格式化/美化 SQL语句
    *
    * @param sql sql 语句
    * @param parameterObject 参数的Map
    * @param parameterMappingList 参数的List
    * @return 格式化之后的SQL
    */
    private String formatSQL(String sql, Object parameterObject, List<ParameterMapping> parameterMappingList) {
    // 输入sql字符串空判断
    if (sql == null || sql.length() == 0) {
    return "";
    }
    // 美化sql
    sql = beautifySql(sql);
    // 不传参数的场景,直接把sql美化一下返回出去
    if (parameterObject == null || parameterMappingList == null || parameterMappingList.size() == 0) {
    return sql;
    }
    return LimitSQLLength(sql);
    }






    /**
    * 返回限制长度之后的SQL语句
    *
    *
    * @param sql 原始SQL语句
    */
    private String LimitSQLLength(String sql) {
    if (sql == null || sql.length() == 0) {
    return "";
    }
    if (sql.length() > MAX_SQL_LENGTH) {
    return sql.substring(0, MAX_SQL_LENGTH);
    } else {
    return sql;
    }
    }




    @Override
    public Object plugin(Object target) {
    return Plugin.wrap(target, this);
    }


    @Override
    public void setProperties(Properties properties) {


    }






    /**
    * 替换SQL 中? 所对应的值, 只保留前50个字符
    *
    * @param sql sql语句
    * @param valueOf ?对应的值
    */
    private String replaceValue(String sql, String valueOf) {
    //超过50个字符只取前50个
    if (valueOf != null && valueOf.length() > MAX_PARAM_LENGTH) {
    valueOf = valueOf.substring(0, MAX_PARAM_LENGTH);
    }
    sql = sql.replaceFirst("\\?", valueOf);
    return sql;
    }


    /**
    * 美化sql
    *
    * @param sql sql语句
    */
    private String beautifySql(String sql) {
    sql = sql.replaceAll("[\\s\n ]+", " ");
    return sql;
    }
    }


    复制


    文章转载自IT学习道场,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

    评论