SSM整合系列之 通过Mybatis拦截器获取SQL语句 实现SQL监控

摘要:Mybatis为我们提供了一个Interceptor接口,通过实现该接口就可以定义我们自己的拦截器,MyBatis拦截器接口提供的3个方法中,plugin方法用于某些处理器(Handler)的构建过程。interceptor方法用于处理代理类的执行。setProperties方法用于拦截器属性的设置。本文将使用拦截器获取运行SQL

1.项目搭建
可以参考本系列文章,博客地址:https://blog.csdn.net/caiqing116/article/details/84573166
或者直接下载项目,git地址:https://github.com/gitcaiqing/SSM_DEMO.git
2.Maven引入Mybatis相关Jar包



	org.mybatis
	mybatis
	3.2.8




	org.mybatis
	mybatis-spring
	1.2.2

3.项目配置
(1)config/jdbc.config配置

#连接驱动
jdbc.driverClassName=com.mysql.jdbc.Driver

#端口号3306的数据源
jdbc.url = jdbc\:mysql\://localhost\:3306/db_ssmdemo?useUnicode\=true&characterEncoding\=UTF-8&allowMultiQueries\=true
jdbc.username = root
jdbc.password = 123456

#端口号3308的数据源
jdbc.3308.url = jdbc\:mysql\://localhost\:3308/db_ssmdemo?useUnicode\=true&characterEncoding\=UTF-8&allowMultiQueries\=true
jdbc.3308.username = root
jdbc.3308.password = 123456

#定义初始连接数 
jdbc.initialSize=2 
#定义最大连接数 
jdbc.maxActive=20
#定义最大空闲 
jdbc.maxIdle=20
#定义最小空闲 
jdbc.minIdle=1
#定义最长等待时间 
jdbc.maxWait=60000
#验证数据库连接的有效性
jdbc.validationQuery=select 1

(2)spring/mybatis.xml配置拦截器



	
	
		
		
			 
                classpath:sql/*.xml
            
		
		
		
			
				
			
		
	
	
	
		
		
	
	
  		
	
	

4.实现MybatisInterceptor 获取SQL并打印

package com.ssm.datasource;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
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.mapping.ParameterMapping;
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.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@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 MybatisInterceptor implements Interceptor {
	
	private static final Logger log = LoggerFactory.getLogger(MybatisInterceptor.class);

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];  
        Object parameter = null;  
        if (invocation.getArgs().length > 1) {  
            parameter = invocation.getArgs()[1];  
        }  

        BoundSql boundSql = mappedStatement.getBoundSql(parameter);  
    	Configuration configuration = mappedStatement.getConfiguration();  
    	Object returnVal = invocation.proceed();
   
    	//获取sql语句
   	 	String sql = getSql(configuration, boundSql);  
    	log.info("Mybatis 拦截器获取SQL:{}",sql);
    	return returnVal;
	}

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

	@Override
	public void setProperties(Properties arg0) {
	}
	
	/**
	 * 获取SQL
	 * @param configuration
	 * @param boundSql
	 * @return
	 */
	private String getSql(Configuration configuration, BoundSql boundSql) {
		Object parameterObject = boundSql.getParameterObject();  
	    List parameterMappings = boundSql.getParameterMappings();  
	    String sql = boundSql.getSql().replaceAll("[\\s]+", " ");  
	    if (parameterObject == null || parameterMappings.size() == 0) {
	    	return sql;
	    }  
        TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();  
        if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {  
        	sql = sql.replaceFirst("\\?", getParameterValue(parameterObject));  
        } else {  
        	MetaObject metaObject = configuration.newMetaObject(parameterObject);  
            for (ParameterMapping parameterMapping : parameterMappings) {  
            	String propertyName = parameterMapping.getProperty();  
                if (metaObject.hasGetter(propertyName)) {  
                	Object obj = metaObject.getValue(propertyName);  
                    sql = sql.replaceFirst("\\?", getParameterValue(obj));  
                } else if (boundSql.hasAdditionalParameter(propertyName)) {  
                	Object obj = boundSql.getAdditionalParameter(propertyName);  
                	sql = sql.replaceFirst("\\?", getParameterValue(obj));  
                }  
            }  
        }  
	    return sql;
	}

	private String getParameterValue(Object obj) {  
		String value = null;  
		if (obj instanceof String) {  
			value = "'" + obj.toString() + "'";  
	    } else if (obj instanceof Date) {  
	        DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);  
	        value = "'" + formatter.format(obj) + "'";  
	    } else {  
	        if (obj != null) {  
	            value = obj.toString();  
	        } else {  
	            value = "";  
	        }  
	    }  
	    return value;  
	}  
}

5.运行项目查看打印日志监控SQL

[2018-12-25 21:30:42][INFO] Mybatis 拦截器获取SQL:select id, userId, utype, username, password, headimg, realname, sex, age, mobile, email, credate, upddate from tb_basic_user where username = '墨倾池' 

你可能感兴趣的:(SSM)