p6spy使用logback作为日志系统

受够了ibatis自带sql语句的日志输出,一坨的问号,直接copy出来,还不能运行,要手工替换每个问号为对应的参数。依照google法则,嗯,发现一个可以自动将sql的问号替换为实际参数并进行日志输出的工具--p6spy。

没的说,download,依照使用手册,把p6spy.jar放到lib目录,p6spy.properties放到classes目录。对原jdbc驱动源进行相应的配置,改为driverClassName = com.p6spy.engine.spy.P6SpyDriver。

开始运行,吼吼,似乎还不错,自动生成spy.log文件,里面一坨的日志,重要的是sql终于是可执行的了。

但……还是不够,我想在控制台也看到,嗯,看p6spy.properties选项配置,有三种日志方式:

#appender=com.p6spy.engine.logging.appender.Log4jLogger
#appender=com.p6spy.engine.logging.appender.StdoutLogger
appender=com.p6spy.engine.logging.appender.FileLogger

默认用的是FileLogger方式,当仁不让,改为log4jLogger,再次运行……哎,这回不行了,因为我的系统用的日志系统是slf4j+logback,昏厥ing……

好吧,不就是一个类吗,打开p6spy源码,查看com.p6spy.engine.logging.appender.Log4jLogger的源码。

嗯,不错,看样子改动不会很大,Log4jLogger源码也才几十行,重要的是实现了P6Logger接口,这就简单了,自建一个类,实现P6Logger接口,就一切搞定了,废话不说,上源码:

package com.boaotech.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.p6spy.engine.logging.appender.P6Logger;
public class P6SpyLogger implements P6Logger {
	private static final Logger logger = LoggerFactory.getLogger("p6spy");
	
	private String lastEntry;
	@Override
	public String getLastEntry() {
		return lastEntry;
	}
	
	public void setLastEntry(String lastEntry) {
		this.lastEntry = lastEntry;
	}
	@Override
	public void logException(Exception e) {
		logger.debug(e.getMessage(), e);
	}
	@Override
	public void logSQL(int connectionId, String now, long elapsed, String category,
			String prepared, String sql) {
		if(!"resultset".equals(category))
			logger.debug(trim(sql));
	}
	@Override
	public void logText(String text) {
		logger.debug(text);
		lastEntry = text;
	}
	public static String trim(String sql) {
		StringBuilder sb = new StringBuilder(256);
		int i = 0, n = sql.length();
		boolean b = true;
		char c;
		while(i < n) {
			c = sql.charAt(i);
			switch (c) {
				case '"':
					b = false;
					sb.append(c);
					++i;
					while(i < n) {
						c = sql.charAt(i);
						if(c == '"') {
							if(i + 1 >= n || sql.charAt(i + 1) != '"') {
								sb.append(c);
								++i;
								break;
							}
							sb.append(c);
							c = sql.charAt(i);
						}
						sb.append(c);
						++i;
					}
					break;
				case '/'':
					b = false;
					sb.append(c);
					++i;
					while(i < n) {
						c = sql.charAt(i);
						if(c == '/'') {
							if(sql.charAt(i + 1) != '/'') {
								sb.append(c);
								break;
							}
							sb.append(c);
							++i;
							c = sql.charAt(i);
						}
						sb.append(c);
						++i;
					}
					break;
				case ' ':
					if(!b) {
						b = true;
						sb.append(c);
					}
					break;
				case '/n': case '/r': case '/t':
					if(!b) {
						b = true;
						sb.append(' ');
					}
					break;
				default:
					b = false;
					sb.append(c);
					break;
			}
			++i;
		}
		return sb.toString();
	}
}

除了实现P6Logger接口外,还对输出的sql做了去除空格的格式化工作,主要是我用的ibatis定义的SQL语句是基于XML的,为了美观,用了大量的缩进,太多的空格和换行,另外,默认p6spy是输出resultset的内容的,这对调试非常不方便,需要知道查询返回的结果,我直接把SQL复制出来执行不就完了,所以,logSQL函数对resultset做了过滤判断,如果是resultset,就不输出。

修改p6spy.properties配置文件,注释掉原来的FileLogger,添加如下一行:

appender=com.kivensoft.util.P6SpyLogger

编译、运行,o my god,太酷了,我不得不佩服我自己,这么天才的想法,都能想出来,这个类,简直就是为我定制的,你说,我能不佩服自己吗?

得,好东西,当然不能私藏,放出来大家共享一把。

你可能感兴趣的:(java)