一、创建拦截器实现类
在mybatisplus模块 里面 创建 intecerptor 文件夹,在文件下下面创建 intecerptor接口 实现类
注: intecerptor 接口来自mybatis
实现类代码如下
package com.jingdianjichi.interceptor; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.ParameterMapping; import org.apache.ibatis.plugin.*; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.defaults.DefaultSqlSession.StrictMap; import java.lang.reflect.Field; import java.sql.Statement; import java.util.*; @Intercepts(value = { @Signature(args = {Statement.class, ResultHandler.class}, method = "query", type = StatementHandler.class), @Signature(args = {Statement.class}, method = "update", type = StatementHandler.class), @Signature(args = {Statement.class}, method = "batch", type = StatementHandler.class)}) public class SqlBeautyInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { Object target = invocation.getTarget(); long startTime = System.currentTimeMillis(); StatementHandler statementHandler = (StatementHandler) target; try { return invocation.proceed(); } finally { long endTime = System.currentTimeMillis(); long sqlCost = endTime - startTime; BoundSql boundSql = statementHandler.getBoundSql(); String sql = boundSql.getSql(); Object parameterObject = boundSql.getParameterObject(); List<ParameterMapping> parameterMappingList = boundSql.getParameterMappings(); sql = formatSql(sql, parameterObject, parameterMappingList); System.out.println("SQL: [ " + sql + " ]执行耗时[ " + sqlCost + "ms ]"); } } @Override public Object plugin(Object o) { return Plugin.wrap(o, this); } @Override public void setProperties(Properties properties) { } private String formatSql(String sql, Object parameterObject, List<ParameterMapping> parameterMappingList) { if (sql == "" || sql.length() == 0) { return ""; } sql = beautifySql(sql); if (parameterObject == null || parameterMappingList == null || parameterMappingList.size() == 0) { return sql; } String sqlWithoutReplacePlaceholder = sql; try { if (parameterMappingList != null) { Class<?> parameterObjectClass = parameterObject.getClass(); if (isStrictMap(parameterObjectClass)) { StrictMap<Collection<?>> strictMap = (StrictMap<Collection<?>>) parameterObject; if (isList(strictMap.get("list").getClass())) { sql = handleListParameter(sql, strictMap.get("list")); } } else if (isMap(parameterObjectClass)) { Map<?, ?> paramMap = (Map<?, ?>) parameterObject; sql = handleMapParameter(sql, paramMap, parameterMappingList); } else { sql = handleCommonParameter(sql, parameterMappingList, parameterObjectClass, parameterObject); } } } catch (Exception e) { return sqlWithoutReplacePlaceholder; } return sql; } private String handleCommonParameter(String sql, List<ParameterMapping> parameterMappingList, Class<?> parameterObjectClass, Object parameterObject) throws Exception { Class<?> originalParameterObjectClass = parameterObjectClass; List<Field> allFieldList = new ArrayList<>(); while (parameterObjectClass != null) { allFieldList.addAll(new ArrayList<>(Arrays.asList(parameterObjectClass.getDeclaredFields()))); parameterObjectClass = parameterObjectClass.getSuperclass(); } Field[] fields = new Field[allFieldList.size()]; fields = allFieldList.toArray(fields); parameterObjectClass = originalParameterObjectClass; for (ParameterMapping parameterMapping : parameterMappingList) { String propertyValue = null; if (isPrimitiveOrPrimitiveWrapper(parameterObjectClass)) { propertyValue = parameterObject.toString(); } else { String propertyName = parameterMapping.getProperty(); Field field = null; for (Field everyField : fields) { if (everyField.getName().equals(propertyName)) { field = everyField; } } field.setAccessible(true); propertyValue = String.valueOf(field.get(parameterObject)); if (parameterMapping.getJavaType().isAssignableFrom(String.class)) { propertyValue = "\"" + propertyValue + "\""; } } sql = sql.replaceFirst("\\?", propertyValue); } return sql; } private String handleMapParameter(String sql, Map<?, ?> paramMap, List<ParameterMapping> parameterMappingList) { for (ParameterMapping parameterMapping : parameterMappingList) { Object propertyName = parameterMapping.getProperty(); Object propertyValue = paramMap.get(propertyName); if (propertyValue != null) { if (propertyValue.getClass().isAssignableFrom(String.class)) { propertyValue = "\"" + propertyValue + "\""; } sql = sql.replaceFirst("\\?", propertyValue.toString()); } } return sql; } private String handleListParameter(String sql, Collection<?> col) { if (col != null && col.size() != 0) { for (Object obj : col) { String value = null; Class<?> objClass = obj.getClass(); if (isPrimitiveOrPrimitiveWrapper(objClass)) { value = obj.toString(); } else if (objClass.isAssignableFrom(String.class)) { value = "\"" + obj.toString() + "\""; } sql = sql.replaceFirst("\\?", value); } } return sql; } private String beautifySql(String sql) { sql = sql.replaceAll("[\\s\n ]+", " "); return sql; } private boolean isPrimitiveOrPrimitiveWrapper(Class<?> parameterObjectClass) { return parameterObjectClass.isPrimitive() || (parameterObjectClass.isAssignableFrom(Byte.class) || parameterObjectClass.isAssignableFrom(Short.class) || parameterObjectClass.isAssignableFrom(Integer.class) || parameterObjectClass.isAssignableFrom(Long.class) || parameterObjectClass.isAssignableFrom(Double.class) || parameterObjectClass.isAssignableFrom(Float.class) || parameterObjectClass.isAssignableFrom(Character.class) || parameterObjectClass.isAssignableFrom(Boolean.class)); } /** * 是否DefaultSqlSession的内部类StrictMap */ private boolean isStrictMap(Class<?> parameterObjectClass) { return parameterObjectClass.isAssignableFrom(StrictMap.class); } /** * 是否List的实现类 */ private boolean isList(Class<?> clazz) { Class<?>[] interfaceClasses = clazz.getInterfaces(); for (Class<?> interfaceClass : interfaceClasses) { if (interfaceClass.isAssignableFrom(List.class)) { return true; } } return false; } /** * 是否Map的实现类 */ private boolean isMap(Class<?> parameterObjectClass) { Class<?>[] interfaceClasses = parameterObjectClass.getInterfaces(); for (Class<?> interfaceClass : interfaceClasses) { if (interfaceClass.isAssignableFrom(Map.class)) { return true; } } return false; } }
二、创建配置类
在mybatisplus模块 里面 创建 config文件夹,在文件下下面创建 MybatisConfiguration类
注入 这个实现类
代码如下
package com.jingdianjichi.config; import com.jingdianjichi.interceptor.SqlBeautyInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MybatisConfiguration { @Bean public SqlBeautyInterceptor sqlBeautyInterceptor(){ return new SqlBeautyInterceptor(); } }
三、启动控制类
四、调用接口,查看结果