日期:2014-05-16  浏览次数:20764 次

扩展logback DBAppender
一) logback已经提供了一个DBAppender(ch.qos.logback.classic.db.DBAppender),为何还需自己发明一个轮子?

1.1
ch.qos.logback.classic.db.DBAppender默认只能保存4个参数到数据库里,如下
(slf4j代码)
LOGGER.info("{}{}{}{}{}", 1,2,3,4,5);

参数5不能保存在DB中的单独一个字段,这样并不方便。扩展为可以保存32个参数。

1.2
logback默认的DBAppender不方便配置,不能自由指定表名

1.3
logback默认的DBAppender中保存的时间戳为long,阅读时不方便。

二) 代码片段 (仅新的DBAppender类,其他工具类等为节省篇幅不贴出)
package com.github.yingzhuo.logbackext.db;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import ch.qos.logback.classic.db.DBHelper;
import ch.qos.logback.classic.spi.CallerData;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.IThrowableProxy;
import ch.qos.logback.classic.spi.StackTraceElementProxy;
import ch.qos.logback.classic.spi.ThrowableProxyUtil;
import ch.qos.logback.core.CoreConstants;
import ch.qos.logback.core.db.DBAppenderBase;
import ch.qos.logback.core.db.dialect.SQLDialectCode;

import com.github.yingzhuo.logbackext.names.DefaultTableAndColumnNameResolver;
import com.github.yingzhuo.logbackext.names.TableAndColumnNameResolver;

/**
 * 参考ch.qos.logback.classic.db.DBAppender
 * 
 * @author yingzhuo
 * 
 */
@SuppressWarnings("rawtypes")
public class DBAppender extends DBAppenderBase<ILoggingEvent> {
	
	private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
	
	private boolean printStackTrace = true;
	protected String insertPropertiesSQL;
	protected String insertExceptionSQL;
	protected String insertSQL;
	protected static final Method GET_GENERATED_KEYS_METHOD;

	private TableAndColumnNameResolver nameResolver = new DefaultTableAndColumnNameResolver();

	static final int TIMESTMP_INDEX = 1;
	static final int FORMATTED_MESSAGE_INDEX = 2;
	static final int LOGGER_NAME_INDEX = 3;
	static final int LEVEL_STRING_INDEX = 4;
	static final int THREAD_NAME_INDEX = 5;
	static final int REFERENCE_FLAG_INDEX = 6;
	static final int ARG0_INDEX = 7;
	static final int ARG1_INDEX = 8;
	static final int ARG2_INDEX = 9;
	static final int ARG3_INDEX = 10;
	static final int ARG4_INDEX = 11;
	static final int ARG5_INDEX = 12;
	static final int ARG6_INDEX = 13;
	static final int ARG7_INDEX = 14;
	static final int ARG8_INDEX = 15;
	static final int ARG9_INDEX = 16;
	static final int ARG10_INDEX = 17;
	static final int ARG11_INDEX = 18;
	static final int ARG12_INDEX = 19;
	static final int ARG13_INDEX = 20;
	static final int ARG14_INDEX = 21;
	static final int ARG15_INDEX = 22;
	static final int ARG16_INDEX = 23;
	static final int ARG17_INDEX = 24;
	static final int ARG18_INDEX = 25;
	static final int ARG19_INDEX = 26;
	static final int ARG20_INDEX = 27;
	static final int ARG21_INDEX = 28;
	static final int ARG22_INDEX = 29;
	static final int ARG23_INDEX = 30;
	static final int ARG24_INDEX = 31;
	static final int ARG25_INDEX = 32;
	static final int ARG26_INDEX = 33;
	static final int ARG27_INDEX = 34;
	static final int ARG28_INDEX = 35;
	static final int ARG29_INDEX = 36;
	static final int ARG30_INDEX = 37;
	static final int ARG31_INDEX = 38;

	static final int CALLER_FILENAME_INDEX = 39;
	static final int CALLER_CLASS_INDEX = 40;
	static final int CALLER_METHOD_INDEX = 41;
	static final int CALLER_LINE_INDEX = 42;
	static final int EVENT_ID_INDEX = 43;

	static final StackTraceElement EMPTY_CALLER_DATA = CallerData.naInstance();

	static {
		Method getGeneratedKeysMethod;
		try {
			getGeneratedKeysMethod = PreparedStatement.class.getMethod("getGeneratedKeys", (Class[]) null);
		} catch (Exception ex) {
			getGeneratedKeysMethod = null;
		}
		GET_GE