sql打印-基于log日志

直接上代码


package xxx;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.selector.ContextSelector;
import cn.hutool.db.sql.SqlFormatter;

public class CustomDefaultContextSelector implements ContextSelector, MethodInterceptor {
	
	private LoggerContext defaultLoggerContext;
	
	private LoggerContext proxyedDefaultLoggerContext;
	
	private static ConcurrentHashMap<String, org.slf4j.Logger> cachedLogger = new ConcurrentHashMap<>(
			1000);
	
	public CustomDefaultContextSelector(LoggerContext context) {
		this.defaultLoggerContext = context;
	}
	
	@Override
	public LoggerContext getLoggerContext() {
		return getDefaultLoggerContext();
	}
	
	@Override
	public LoggerContext getDefaultLoggerContext() {
		if (proxyedDefaultLoggerContext == null) {
			Enhancer enhancer = new Enhancer();
			enhancer.setSuperclass(defaultLoggerContext.getClass());
			enhancer.setCallback(this);
			proxyedDefaultLoggerContext = (LoggerContext) enhancer.create();
		}
		return proxyedDefaultLoggerContext;
	}
	
	@Override
	public LoggerContext detachLoggerContext(String loggerContextName) {
		return defaultLoggerContext;
	}
	
	@Override
	public List<String> getContextNames() {
		return Arrays.asList(defaultLoggerContext.getName());
	}
	
	@Override
	public LoggerContext getLoggerContext(String name) {
		if (defaultLoggerContext.getName().equals(name)) {
			return defaultLoggerContext;
		} else {
			return null;
		}
	}
	
	@Override
	public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		Object result;
		result = methodProxy.invokeSuper(o, args);
		if (Objects.equals(method.getReturnType().getName(), org.slf4j.Logger.class.getName())
				&& Objects.equals(method.getName(), "getLogger")) {
			org.slf4j.Logger logger = (org.slf4j.Logger) result;
			String loggerName = logger.getName();
			
			/**
			 * 只关心mybatis层的logger,mybatis层的logger的包名,我们这边是固定的包下面 如果不是这个包下的,直接返回
			 */
			if (!loggerName.startsWith("cn.com.xxx")) {
				return result;
			}
			
			/**
			 * 对mybatis mapper的log,需要进行代理;代理后的对象,我们暂存一下,免得每次都创建代理对象 从缓存获取代理logger
			 */
			if (cachedLogger.get(loggerName) != null) {
				return cachedLogger.get(loggerName);
			}
			
			CustomLoggerInterceptor customLoggerInterceptor = new CustomLoggerInterceptor();
			customLoggerInterceptor.setLogger((Logger) result);
			Object newProxyInstance = Proxy.newProxyInstance(result.getClass().getClassLoader(),
					result.getClass().getInterfaces(),
					customLoggerInterceptor);
			
			cachedLogger.put(loggerName, (org.slf4j.Logger) newProxyInstance);
			return newProxyInstance;
		}
		
		return result;
	}
	
	public static ConcurrentHashMap<String, org.slf4j.Logger> getCachedLogger() {
		return cachedLogger;
	}
	
	public static class CustomLoggerInterceptor implements InvocationHandler {
		
		/**
		 * 
		 */
		private static final String PARAMETERS = "==> Parameters: ";
		
		/**
		 * 
		 */
		private static final String PREPARING = "==>  Preparing: ";
		
		private static final Set<String> skipMethodSet = new HashSet<String>();
		
		Pattern pattern = Pattern.compile(
				"\\(String\\),{0,1}|\\(Timestamp\\),{0,1}|\\(Date\\),{0,1}|\\(Time\\),{0,1}|\\(LocalDate\\),{0,1}|\\(LocalTime\\),{0,1}|\\(LocalDateTime\\),{0,1}|\\(Byte\\),{0,1}|\\(Short\\),{0,1}|\\(Integer\\),{0,1}|\\(Long\\),{0,1}|\\(Float\\),{0,1}|\\(Double\\),{0,1}|\\(BigDecimal\\),{0,1}|\\(Boolean\\),{0,1}|\\(Null\\),{0,1}");
		
		public ThreadLocal<String> threadLocal = new ThreadLocal<>();
		
		static {
			skipMethodSet.add("isTraceEnabled");
			skipMethodSet.add("isDebugEnabled");
			skipMethodSet.add("isInfoEnabled");
			skipMethodSet.add("isWarnEnabled");
			skipMethodSet.add("isErrorEnabled");
			
		}
		
		private Logger logger;
		
		public void setLogger(Logger logger) {
			this.logger = logger;
		}
		
		@Override
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			// 包名
			if (logger.getName().startsWith("cn.com.xxx")) {
				if (skipMethodSet.contains(method.getName())) {
					return method.invoke(logger, args);
				}
				Object orginResult = method.invoke(logger, args);
				try {
					@SuppressWarnings("unused")
					String testString = (String) args[3];
				} catch (Exception e) {
					return method.invoke(logger, args);
				}
				String startString = (String) args[3];
				// 去前缀
				if (startString.startsWith(PREPARING)) {
					threadLocal.set(startString.replace(PREPARING, ""));
				}
				// ==> Parameters: 1(Integer), 10(Integer)
				if (startString.startsWith(PARAMETERS)) {
					extracted(startString);
				}
				return orginResult;
			}
			return method.invoke(logger, args);
		}
		
		private void extracted(String rawParams) {
			// 去前缀
			rawParams = rawParams.replace(PARAMETERS, "");
			String[] rawParamArray = rawParams.split(",");
			// 正则分割
			String[] paramArray = pattern.split(rawParams);
			String sql = threadLocal.get();
			try {
				if (StringUtils.isNotBlank(sql) && sql.contains("?")) {
					for (int i = 0; i < paramArray.length; i++) {
						String value = paramArray[i];
						value = StringUtils.stripStart(value, null);
						// 字符串加引号
						if (rawParamArray[i].contains("String")
								|| rawParamArray[i].contains("Timestamp")
									|| rawParamArray[i].contains("Date")
									|| rawParamArray[i].contains("Time")
									|| rawParamArray[i].contains("LocalDate")
									|| rawParamArray[i].contains("LocalDateTime")
									|| rawParamArray[i].contains("LocalTime")
									|| rawParamArray[i].contains("LocalDateTime")) {
							value = "'" + value + "'";
						}
						sql = sql.replaceFirst("\\?", value);
					}
					printSQL(SqlFormatter.format(sql));
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				threadLocal.remove();
			}
		}
		
		/**
		 * printSQL
		 * 
		 * @param sqlString void
		 */
		public final void printSQL(String sqlString) {
			if (sqlString.contains(PREPARING)) {
				sqlString = sqlString.substring(PREPARING.length());
			}
			System.out.println("\033[32;4m"
					+ "\r\n;;-- ------------------------------------------------------------------------------------------------------------------------------\r\n"
						+ "\r\n"
						+ sqlString
						+ ";"
						+ "\r\n"
						+ "\r\n;;-- ------------------------------------------------------------------------------------------------------------------------------\r\n"
						+ "\033[0m");
		}
	}
	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值