springboot+mybatis项目拦截器打印sql日志

本来debug模式可以查看到所有sql日志,但是生产环境开启的是info级别的日期,为了后期维护方便查日志,就需要增加info下可以查看到sql的日志。

一、编写拦截器类

1、实现Interceptor接口,org.apache.ibatis.plugin.Interceptor
2、增加@Intercepts注解,org.apache.ibatis.plugin.Intercepts
@Intercepts({@Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}),
    @Signature(type = StatementHandler.class, method = "update", args = {Statement.class})})
对应的包有import org.apache.ibatis.executor.statement.StatementHandler;
import java.sql.Statement;
import org.apache.ibatis.session.ResultHandler;

3、增加spring的@Component和@Configuration注解

4、实现intercept类

代码贴出:
import java.sql.Statement;
import java.util.Properties;

import org.apache.ibatis.executor.statement.StatementHandler;
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.session.ResultHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

@Intercepts({@Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}),
    @Signature(type = StatementHandler.class, method = "update", args = {Statement.class})})
@Component
@Configuration
public class SqlLogInterceptor implements Interceptor {

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

    @Override
    public Object intercept(Invocation invocation){
        		StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY,
                SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
 
        /**
         * 先拦截到RoutingStatementHandler,里面有个StatementHandler类型的delegate变量,
         * 其实现类是BaseStatementHandler,然后就到BaseStatementHandler的成员变量mappedStatement
         */
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
 
        /**
         * id为执行的mapper方法的全路径名
         */
        String id = mappedStatement.getId();
 
        BoundSql boundSql = statementHandler.getBoundSql();
        Object parameterObject = boundSql.getParameterObject();
        String params = getParameterValue(parameterObject);
 
        String sql = boundSql.getSql();//sql语句
        
        /**
         * 输出日志
         */       
        logger.info(id + " ==> Parameters: " + params);
		logger.info(id + " ==> sql: " + sql);
		
        long start = System.currentTimeMillis();
        Object proceed = invocation.proceed();
        long end = System.currentTimeMillis();
        logger.info(id + " ==> time: " + (end - start) + "ms");//耗时
        
        return proceed;

     
    }

	/**
     * 获取参数
     * @param obj
     * @return
     */
    private String getParameterValue(Object obj) {
        StringBuffer params = new StringBuffer();
        if (obj instanceof String) {
            params.append("'").append(obj.toString()).append("'");
        } else if (obj instanceof Date) {
            DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);
            params.append("'").append(formatter.format(new Date())).append("'");
        } else {
            if (obj != null) {
                params.append(obj.toString());
            }
        }
        return params.toString();
    }
    @Override
    public Object plugin(Object arg0) {
        return Plugin.wrap(arg0, this);
    }
    @Override
    public void setProperties(Properties arg0) {
    }
}
二、将拦截插件放在sqlSessionFactory的bean中管理

因为项目中没有mybatis的xml文件,但是又配置多数据源的地方,所以这个bean管理就被在类中管理。

代码贴出:
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactoryBean(DataSource dataSource) throws Exception{
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        // sql日志拦截器
		Interceptor[] plugins =  new Interceptor[]{ new SqlLogInterceptor()};
        sqlSessionFactoryBean.setPlugins(plugins);
        return sqlSessionFactoryBean.getObject();
 }

你可能感兴趣的:(后端,日志)