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

版权声明:如需转载,请注明出处。 https://blog.csdn.net/caiqing116/article/details/85146751

摘要: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包

<!-- mybatis 包 -->
<dependency>
	<groupId>org.mybatis</groupId>
	<artifactId>mybatis</artifactId>
	<version>3.2.8</version>
</dependency>

<!--mybatis spring 插件 -->
<dependency>
	<groupId>org.mybatis</groupId>
	<artifactId>mybatis-spring</artifactId>
	<version>1.2.2</version>
</dependency>

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

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

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

#端口号3308的数据源
jdbc.3308.url = jdbc\:mysql\://localhost\:3308/db_ssmdemo?useUnicode\=true&amp;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配置拦截器

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">
	
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="mapperLocations">
			 <list>
                <value>classpath:sql/*.xml</value>
            </list>
		</property>
		
		<property name="plugins">
			<list>
				<bean class="com.ssm.datasource.MybatisInterceptor"></bean>
			</list>
		</property>
	</bean>
	
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.ssm.mapper" />
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
	</bean>
	<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype">
  		<constructor-arg index="0" ref="sqlSessionFactory" />
	</bean>
	
</beans>

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();  
       
        //获取sql语句
        String sql = getSql(configuration, boundSql);  
        log.info("Mybatis 拦截器获取SQL:{}",sql);
        return sql;
	}

	@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<ParameterMapping> 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 = '墨倾池' 

猜你喜欢

转载自blog.csdn.net/caiqing116/article/details/85146751