使用mybatis插件拦截SQL
1、定义注解,只拦截有注解的Mapper方法
package com.sgm.qms.system.aop; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 导入记录日志 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ExportLogger { }
2、定义拦截器
package com.sgm.qms.system.aop; import com.sgm.qms.common.controller.BaseController; import com.sgm.qms.common.utils.ContextUtil; import com.sgm.qms.system.entity.Employee; 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.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; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import java.text.DateFormat; import java.util.*; import java.util.regex.Matcher; @Intercepts({ @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 ExportLoggerInterceptor extends BaseController implements Interceptor { private static final Logger logger = LoggerFactory.getLogger(ExportLoggerInterceptor.class); @Override public Object intercept(Invocation invocation) throws Throwable { try { MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0]; //1.获取方法全路径 String methodNameSpace = mappedStatement.getId(); int i = methodNameSpace.lastIndexOf("."); String className = methodNameSpace.substring(0, i); String methodName = methodNameSpace.substring(++i); Class<?> mapperClass = Class.forName(className); Method[] declaredMethods = mapperClass.getDeclaredMethods(); for (Method method : declaredMethods) { if(methodName.equals(method.getName())) { ExportLogger exportLogger = method.getAnnotation(ExportLogger.class); if(exportLogger != null) { Object parameter = null; if (invocation.getArgs().length > 1) { parameter = invocation.getArgs()[1]; } BoundSql boundSql = mappedStatement.getBoundSql(parameter); Configuration configuration = mappedStatement.getConfiguration(); String sql = getSql(configuration, boundSql);// todo 此处将信息存入数据即可 } } } } catch (Exception e) { logger.error(e.getMessage(), e); } return invocation.proceed(); } @Override public Object plugin(Object target) { return target instanceof Executor ? Plugin.wrap(target, this) : target; } @Override public void setProperties(Properties properties) {} private static String getSql(Configuration configuration, BoundSql boundSql) { String sql = showSql(configuration, boundSql); return sql; } private static 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(new Date()) + "'"; } else { if (obj != null) { value = obj.toString(); } else { value = ""; } } return value; } private static String showSql(Configuration configuration, BoundSql boundSql) { Object parameterObject = boundSql.getParameterObject(); List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); String sql = boundSql.getSql().replaceAll("[\\s]+", " "); if (!parameterMappings.isEmpty() && parameterObject != null) { TypeHandlerRegistry typeHandlerRegistry = configuration .getTypeHandlerRegistry(); if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(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("\\?", Matcher.quoteReplacement(getParameterValue(obj))); } else if (boundSql.hasAdditionalParameter(propertyName)) { Object obj = boundSql .getAdditionalParameter(propertyName); sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParameterValue(obj))); } else { sql = sql.replaceFirst("\\?", "缺失"); }//打印出缺失,提醒该参数缺失并防止错位 } } } return sql; } }
3、向容器添加插件
a springboot项目直接在拦截器类上加 @Component 注解 或 使用 @Bean 注入容器
b 非springboot项目在mybatis的配置文件加入 plugin 就行
只要你不觉得尴尬,那尴尬的就是别人