MyBatis-Plus SQL日志

B站影视 日本电影 2025-09-13 12:32 1

摘要:import com.baomidou.mybatisplus.core.toolkit.SystemClock;import lombok.extern.slf4j.Slf4j;import org.apache.ibatis.executor.statem

EnhancedSqlLogInterceptor -> 拦截日志 SqlLogHandler -> 拓展功能:实现接口自定义处理日志

import com.baomidou.mybatisplus.core.toolkit.SystemClock;import lombok.extern.slf4j.Slf4j;import org.apache.ibatis.executor.statement.StatementHandler;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.reflection.SystemMetaObject;import org.apache.ibatis.session.Configuration;import org.apache.ibatis.type.TypeHandlerRegistry;import org.springframework.beans.factor #技术分享y.annotation.Autowired;import org.springframework.stereotype.Component;import java.lang.reflect.Array; import java.SQL.Statement; import java.text.SimpleDateFormat; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors;@Slf4j @Component @Intercepts({ @Signature(type = StatementHandler.class, method = "query", args = {Statement.class, org.apache.ibatis.session.ResultHandler.class}), @Signature(type = StatementHandler.class, method = "update", args = {Statement.class}), @Signature(type = StatementHandler.class, method = "batch", args = {Statement.class}) }) public class EnhancedSqlLogInterceptor implements Interceptor {private static final long SLOW_SQL_THRESHOLD = 1000;private static final Set HIDE_PARAMS = new HashSet(Arrays.asList( "password", "pwd", "secret", "token", "creditCard", "cvv" ));private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("(? sqlLogHandlers;@Override public Object intercept(Invocation invocation) throws Throwable {long startTime = SystemClock.now;try { return invocation.proceed; } finally { long endTime = SystemClock.now; long costTime = endTime - startTime;if (log.isDebugEnabled || costTime > SLOW_SQL_THRESHOLD || (sqlLogHandlers != null && !sqlLogHandlers.isEmpty)) { String methodName = invocation.getMethod.getName;StatementHandler statementHandler = (StatementHandler) invocation.getTarget;BoundSql boundSql = statementHandler.getBoundSql;String sqlWithPlaceholders = boundSql.getSql.trim;String completeSql = getCompleteSql(statementHandler, boundSql, sqlWithPlaceholders); String logMsg = buildLogMessage(methodName, completeSql, costTime);if(costTime > SLOW_SQL_THRESHOLD){ log.warn(logMsg); }else { if(log.isDebugEnabled){ log.debug(logMsg); } } if(sqlLogHandlers != null && !sqlLogHandlers.isEmpty){ for (SqlLogHandler sqlLogHandler : sqlLogHandlers) { sqlLogHandler.handle(methodName, completeSql, costTime); } } } } }private String getCompleteSql(StatementHandler statementHandler, BoundSql boundSql, String sqlWithPlaceholders) { try { List parameterMappings = boundSql.getParameterMappings; if (parameterMappings == null || parameterMappings.isEmpty) { return sqlWithPlaceholders; }MetaObject metaObject = SystemMetaObject.forObject(statementHandler); MappedStatement mappedStatement = (MappedStatement) MetaObject.getValue("delegate.mappedStatement"); Configuration configuration = mappedStatement.getConfiguration;Object parameterObject = boundSql.getParameterObject; List paramValues = getParameterValues(boundSql, configuration, parameterObject);Matcher matcher = PLACEHOLDER_PATTERN.matcher(sqlWithPlaceholders); StringBuffer sb = new StringBuffer; int paramIndex = 0; while (matcher.find && paramIndex getParameterValues(BoundSql boundSql, Configuration configuration, Object parameterObject) { List paramValues = new ArrayList; List parameterMappings = boundSql.getParameterMappings;if (parameterMappings != null) { TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry; MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(parameterObject);for (ParameterMapping parameterMapping : parameterMappings) { String propertyName = parameterMapping.getProperty;if (isSensitiveParam(propertyName)) { paramValues.add("******"); continue; }if (metaObject != null && typeHandlerRegistry.hasTypeHandler(parameterObject.getClass)) { paramValues.add(parameterObject); } else if (boundSql.hasAdditionalParameter(propertyName)) { Object value = boundSql.getAdditionalParameter(propertyName); paramValues.add(value); } else if (parameterObject == null) { paramValues.add(null); } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass)) { paramValues.add(parameterObject); } else if (metaObject != null) { Object value = metaObject.getValue(propertyName); paramValues.add(value); } else { paramValues.add(null); } } } return paramValues; }private String formatParameter(Object param) { if (param == null) { return "NULL"; }if (param instanceof String) { return "'" + param + "'"; }if (param instanceof Date) { return "'" + DATE_FORMAT.format((Date) param) + "'"; }if (param instanceof Number) { return param.toString; }if (param instanceof Boolean) { return Boolean.TRUE.equals(param) ? "1" : "0"; }if (param instanceof byte) { return "[BINARY]"; }if (param instanceof Collection) { return formatCollection((Collection) param); }if (param.getClass.isArray) { return formatArray(param); }return "'" + param.toString + "'"; }private String formatCollection(Collection collection) { StringBuilder sb = new StringBuilder; for (Object item : collection) { if (sb.length > 0) sb.append(","); sb.append(formatParameter(item)); } return sb.toString; }private String formatArray(Object array) { StringBuilder sb = new StringBuilder; int length = Array.getLength(array); for (int i = 0; i 0) sb.append(","); sb.append(formatParameter(Array.get(array, i))); } return sb.toString; }private boolean isSensitiveParam(String paramName) { if (paramName == null) return false;String lowerParamName = paramName.toLowerCase; return HIDE_PARAMS.stream .anyMatch(hideParam -> lowerParamName.contains(hideParam.toLowerCase)); }private String buildLogMessage(String method, String sql, long costTime) { return String.format("\n" + "┌───────────────────────────────────────────────────────────────────────────────\n" + "│ SQL 方法: %s\n" + "│ 执行时间: %d ms\n" + "│ 完整 SQL: \n" + "%s" + "└───────────────────────────────────────────────────────────────────────────────", method, costTime, formatSqlForDisplay(sql)).replace("│ \n",""); }private String formatSqlForDisplay(String sql) { List formattedLines = new ArrayList; StringBuilder currentLine = new StringBuilder;String tokens = sql.split("\s+");for (String token : tokens) { if (currentLine.length + token.length + 1 > MAX_LINE_LENGTH) { formattedLines.add(currentLine.toString); currentLine = new StringBuilder; }if (currentLine.length > 0) { currentLine.append(" "); } currentLine.append(token);if (isKeyword(token)) { formattedLines.add(currentLine.toString); currentLine = new StringBuilder; } }if (currentLine.length > 0) { formattedLines.add(currentLine.toString); }return formattedLines.stream .map(line -> "│ " + line) .collect(Collectors.joining("\n")) + "\n"; }private boolean isKeyword(String token) { if (token == null || token.isEmpty) { return false; }String upperToken = token.toUpperCase; return upperToken.equals("SELECT") || upperToken.equals("FROM") || upperToken.equals("WHERE") || upperToken.equals("JOIN") || upperToken.equals("INNER") || upperToken.equals("LEFT") || upperToken.equals("RIGHT") || upperToken.equals("GROUP") || upperToken.equals("ORDER") || upperToken.equals("HAVING") || upperToken.equals("LIMIT") || upperToken.equals("OFFSET") || upperToken.equals("UNION") || upperToken.equals("VALUES"); }@Override public Object plugin(Object target) { return Plugin.wrap(target, this); }@Override public void setProperties(Properties properties) { } }public interface SqlLogHandler {void handle(String methodName, String completeSql, long costTime); }import org.slf4j.Logger;import org.springframework.stereotype.Component;@Component public class DBLogHandler implements SqlLogHandler {private static final Logger logger = org.slf4j.LoggerFactory.getLogger(DBLogHandler.class);@Override public void handle(String methodName, String completeSql, long costTime) { logger.info("当前操作用户 :{}", SecurityUtils.getCurrentUserId); logger.info("DBLogHandler{}: {} costTime: {}", methodName, completeSql, costTime); AsyncExecutor.execute( -> logger.info("异步执行器 DBLogHandler{}: {} costTime: {}", methodName, completeSql, costTime)); } }

来源:墨码行者

相关推荐