发布时间:2021-04-17作者:laosun阅读(839)
首先我们定义一个拦截所有SQL的拦截器,代码如下(代码网上随便找了一个,主要是代码行数多):
/** * .::::. * .::::::::. * ::::::::::: 佛主保佑、永无Bug * ..:::::::::::' * '::::::::::::' * .:::::::::: * '::::::::::::::.. * ..::::::::::::. * ``:::::::::::::::: * ::::``:::::::::' .:::. * ::::' ':::::' .::::::::. * .::::' :::: .:::::::'::::. * .:::' ::::: .:::::::::' ':::::. * .::' :::::.:::::::::' ':::::. * .::' ::::::::::::::' ``::::. * ...::: ::::::::::::' ``::. * ```` ':. ':::::::::' ::::.. * '.:::::' ':'````.. */ import com.alibaba.fastjson.JSON; import org.apache.ibatis.cache.CacheKey; 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.*; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import java.lang.reflect.Method; import java.util.Collection; import java.util.List; import java.util.Properties; /** * @Date 2021-04-17 21:49 */ @Intercepts(value = { @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, CacheKey.class, BoundSql.class}), @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})}) @Component public class SqlInterceptor implements Interceptor { private static final Logger logger = LoggerFactory.getLogger(SqlInterceptor.class); @Override public Object intercept(Invocation invocation) throws Throwable { Object target = invocation.getTarget(); Object result = null; if (target instanceof Executor) { long start = System.currentTimeMillis(); Method method = invocation.getMethod(); /**执行方法*/ result = invocation.proceed(); long end = System.currentTimeMillis(); final Object[] args = invocation.getArgs(); //获取原始的ms MappedStatement ms = (MappedStatement) args[0]; String commandName = ms.getSqlCommandType().name(); String name = method.getName(); if (commandName.startsWith("INSERT")) { name += "=新增"; } else if (commandName.startsWith("UPDATE")) { name += "=修改"; } else if (commandName.startsWith("DELETE")) { name += "=删除"; } else if (commandName.startsWith("SELECT")) { name += "=查询"; } String message = "[SqlInterceptor] execute [" + name + "] cost [" + (end - start) + "] ms"; StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append(message); stringBuffer.append("\n"); Object parameterObject = args[1]; BoundSql boundSql = ms.getBoundSql(parameterObject); String sql = boundSql.getSql(); List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); String parameterObjects = JSON.toJSONString(boundSql.getParameterObject()); String id = ms.getId(); stringBuffer.append("id=" + id); stringBuffer.append("\r\n"); stringBuffer.append("sql=" + sql); stringBuffer.append("\n"); stringBuffer.append("parameterMappings=" + parameterMappings); stringBuffer.append("\n"); stringBuffer.append("parameterObjects=" + parameterObjects); stringBuffer.append("\n"); // stringBuffer.append("result="+result); if (result != null) { if (result instanceof List) { stringBuffer.append("result=" + ((List) result).size()); } else if (result instanceof Collection) { stringBuffer.append("result=" + ((Collection) result).size()); } else { stringBuffer.append("result=" + 1); } } else { stringBuffer.append("result=NULL"); } stringBuffer.append("\n"); logger.warn(stringBuffer.toString()); //数组可能为空 // ParameterMapping mapping = boundSql.getParameterMappings().get(0); // Configuration configuration = ms.getConfiguration(); // DynamicContext context = new DynamicContext(configuration, parameterObject); // String originSql = context.getSql(); // System.out.println("@@@@originSql:"+originSql); } return result; } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { } }
然后将该类放到SpringBoot启动时包的扫描范围下即可,类增加注释:@Component。
在springboot中要给mybatis加上这个拦截器,有三种方法,前两种方法在启动项目时不会自动调用自定义拦截器的setProperties方法。
第一种
直接给自定义拦截器添加一个 @Component注解,当调用sql时结果如下,可以看到拦截器生效了,但是启动时候并没有自动调用setProperties方法。可以在初始化自定义拦截器的时候通过 @Value 注解直接初始化需要的参数。
第二种
在配置类里添加拦截器,这种方法结果同上,也不会自动调用setProperties方法。可以在初始化自定义拦截器的时候通过 @Value 注解直接初始化需要的参数。
@Configuration public class MybatisConfig { @Bean ConfigurationCustomizer mybatisConfigurationCustomizer() { return new ConfigurationCustomizer() { @Override public void customize(org.apache.ibatis.session.Configuration configuration) { configuration.addInterceptor(new SqlInterceptor()); } }; } }
第三种
这种方法就是跟以前的配置方法类似,在yml配置文件中指定mybatis的xml配置文件,注意config-location属性和configuration属性不能同时指定。
mybatis: config-location: classpath:mybatis.xml type-aliases-package: com.xxx.model mapper-locations: classpath:mapper/*.xml
mybatis.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <typeAliases> <package name="com.xxx.model"/> </typeAliases> <plugins> <plugin interceptor="com.xxx.interceptor.SqlInterceptor"> <property name="dialect" value="mysql"/> </plugin> </plugins> </configuration>
版权属于: 技术客
原文地址: https://www.sunjs.com/article/detail/f7616ba14f8041df9ff93636c1451763.html
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
关键字: Java 源码 springboot mybatis