这个包主要是处理数据库的,logback日志输出的目的地有三个控制台、文件、数据库。这个包提供了ch.qos.logback.core.db.dialect.SQLDialect、ch.qos.logback.core.db.ConnectionSource、ch.qos.logback.core.db.DBAppenderBase<E>三个接口把日志输入到数据库表中的。和日志相关的表有三个logging_event、logging_event_property、logging_event_exception。三个表的脚本文件在logback-classic.jar的ch.qos.logback.classic.db.script包下可自行获取。下面具体分析每一个接口的具体作用

1、ch.qos.logback.core.db.dialect.SQLDialect接口:该接口是一个数据库方言接口,一想到数据库的方言我们应该明白是为适配各种数据库差异性的。就像每种数据库的分页以及获取自增主键的sql都是不同。logback的方言主要实现各种数据库logging_event表自增主键EVENT_ID字段的值。logback目前支持的数据库类型:postgresql、mysql、oracle、microsoft、hsql、h2、sql anywhere、sqlite。具体接口图如下

 

 

 2、ch.qos.logback.core.db.ConnectionSource接口:该接口主要提供四种能力,第一个getConnection()获取connection连接、第二个getSQLDialectCode()通过DatabaseMetaDatagetDatabaseProductName()方法计算出SQLDialectCode枚举值,第三个supportsGetGeneratedKeys()判断驱动是否有现成的api获取自增主键值,如果不没有就通过sql去获取,也就是上面的方言实现类的getSelectInertId()方法获取,第四个supportsBatchUpdates()判断驱动是否支持批量操作如果不支持就追条追条插入。第二、三、四在基类ch.qos.logback.core.db.ConnectionSourceBase都已经实现。第一个在基类ConnectionSourceBase的子类中实现,这里强调下一般获取connection有三种方式第一种通过最原始的方式jdbc驱动可以获取connction,第二种通过dataSource对象的getConnection()方法获取,目的是为了能够对接第三方连接池框架。第三种就是jndi的方式。具体看图

 

 

 3、ch.qos.logback.core.db.DBAppenderBase<E>接口:该接口的目的是要把日志对象插入数据库的表中,一个模板方法append(),三个抽象方法:getInsertSQL()方法获取插入logging_event表的sql,subAppend()方法执行插入logging_event表的sql,secondarySubAppend()方法执行插入表logging_event_property和logging_event_exception两个表的sql。 append()是抽象类ch.qos.logback.core.db.DBAppenderBase的核心方法,但是在执行append()之前需要调用start()初始化SQLDialect对象以及cnxSupportsGetGeneratedKeys和cnxSupportsBatchUpdates属性。

该方法分为几步:

第一步:通过ch.qos.logback.core.db.ConnectionSource接口获取connection对象。

第二步:执行插入logging_event表的sql并获取自增主键值。

第三步:执行插入logging_event_property和logging_event_exception表的sql。

模板方法append()见图

 

 

 类图如下

 

 

 

 4、最后给一个例子

创建LoggingEvent对象

package com.logback.db;


public class LoggingEvent {
    private Long eventId;

    private int timestmp;

    private String formattedMessage;

    private String loggerName;

    private String levelString;

    private String threadName;

    private int referenceFlag;

    private String arg0;

    private String arg1;

    private String arg2;

    private String arg3;

    private String callerFilename;

    private String callerClass;

    private String callerMethod;

    private String callerLine;

    public Long getEventId() {
        return eventId;
    }

    public void setEventId(Long eventId) {
        this.eventId = eventId;
    }

    public int getTimestmp() {
        return timestmp;
    }

    public void setTimestmp(int timestmp) {
        this.timestmp = timestmp;
    }

    public String getFormattedMessage() {
        return formattedMessage;
    }

    public void setFormattedMessage(String formattedMessage) {
        this.formattedMessage = formattedMessage;
    }

    public String getLoggerName() {
        return loggerName;
    }

    public void setLoggerName(String loggerName) {
        this.loggerName = loggerName;
    }

    public String getLevelString() {
        return levelString;
    }

    public void setLevelString(String levelString) {
        this.levelString = levelString;
    }

    public String getThreadName() {
        return threadName;
    }

    public void setThreadName(String threadName) {
        this.threadName = threadName;
    }

    public int getReferenceFlag() {
        return referenceFlag;
    }

    public void setReferenceFlag(int referenceFlag) {
        this.referenceFlag = referenceFlag;
    }

    public String getArg0() {
        return arg0;
    }

    public void setArg0(String arg0) {
        this.arg0 = arg0;
    }

    public String getArg1() {
        return arg1;
    }

    public void setArg1(String arg1) {
        this.arg1 = arg1;
    }

    public String getArg2() {
        return arg2;
    }

    public void setArg2(String arg2) {
        this.arg2 = arg2;
    }

    public String getArg3() {
        return arg3;
    }

    public void setArg3(String arg3) {
        this.arg3 = arg3;
    }

    public String getCallerFilename() {
        return callerFilename;
    }

    public void setCallerFilename(String callerFilename) {
        this.callerFilename = callerFilename;
    }

    public String getCallerClass() {
        return callerClass;
    }

    public void setCallerClass(String callerClass) {
        this.callerClass = callerClass;
    }

    public String getCallerMethod() {
        return callerMethod;
    }

    public void setCallerMethod(String callerMethod) {
        this.callerMethod = callerMethod;
    }

    public String getCallerLine() {
        return callerLine;
    }

    public void setCallerLine(String callerLine) {
        this.callerLine = callerLine;
    }
}

实现DBAppenderBase类

package com.logback.db;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;

import ch.qos.logback.core.db.DBAppenderBase;

public class InsertDbAppend extends DBAppenderBase<LoggingEvent> {
    protected static final Method GET_GENERATED_KEYS_METHOD;
    static {
        Method getGeneratedKeysMethod;
        try {
            // the
            getGeneratedKeysMethod = PreparedStatement.class.getMethod("getGeneratedKeys", (Class[]) null);
        } catch (Exception ex) {
            getGeneratedKeysMethod = null;
        }
        GET_GENERATED_KEYS_METHOD = getGeneratedKeysMethod;
    }
    @Override
    protected Method getGeneratedKeysMethod() {
        // TODO Auto-generated method stub
        return GET_GENERATED_KEYS_METHOD;
    }

    @Override
    protected String getInsertSQL() {
        return "insert into logging_event(TIMESTMP,\r\n" + 
                "  FORMATTED_MESSAGE,\r\n" + 
                "  LOGGER_NAME,\r\n" + 
                "  LEVEL_STRING,\r\n" + 
                "  CALLER_FILENAME,\r\n" + 
                "  CALLER_CLASS,\r\n" + 
                "  CALLER_METHOD,\r\n" + 
                "  CALLER_LINE) values(?,?,?,?,?,?,?,?)";
    }

    @Override
    protected void subAppend(LoggingEvent eventObject, Connection connection, PreparedStatement statement)
            throws Throwable {
        try {
            statement.setInt(1,eventObject.getTimestmp());
            statement.setString(2,eventObject.getLoggerName());
            statement.setString(3,eventObject.getLevelString());
            statement.setString(4,eventObject.getCallerFilename());
            statement.setString(5,eventObject.getCallerClass());
            statement.setString(6,eventObject.getCallerMethod());
            statement.setString(7,eventObject.getCallerLine());
            statement.setInt(8,eventObject.getReferenceFlag());
            statement.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            statement.close();
        }
        
    }

    @Override
    protected void secondarySubAppend(LoggingEvent eventObject, Connection connection, long eventId) throws Throwable {
        //
        
    }

}

main方法

package com.logback.db;


import ch.qos.logback.core.db.DriverManagerConnectionSource;

public class DbMain {

    public static void main(String[] args) {
        //1、创建connectionDatasource对象
        DriverManagerConnectionSource driverManagerConnectionSource=new DriverManagerConnectionSource();
        driverManagerConnectionSource.setPassword("dcp");
        driverManagerConnectionSource.setUser("dcp");
        driverManagerConnectionSource.setUrl("jdbc:oracle:thin:@127.0.0.1:1521:orcl");
        driverManagerConnectionSource.setDriverClass("oracle.jdbc.OracleDriver");
        driverManagerConnectionSource.start();
        
        //2、创建DBAppenderBase实现类InsertDbAppend
        InsertDbAppend insertDbAppend=new InsertDbAppend();
        insertDbAppend.setConnectionSource(driverManagerConnectionSource);
        insertDbAppend.start();
        LoggingEvent loggingEvent=new LoggingEvent();
        loggingEvent.setCallerClass("callerClass");
        loggingEvent.setCallerFilename("callerFilename");
        loggingEvent.setCallerLine("callerLine");
        loggingEvent.setCallerMethod("callerMethod");
        loggingEvent.setFormattedMessage("formattedMessage");
        loggingEvent.setLevelString("levelString");
        loggingEvent.setLoggerName("loggerName");
        loggingEvent.setReferenceFlag(3);
        loggingEvent.setTimestmp(4);
        
        //3、调用核心方法
        insertDbAppend.append(loggingEvent);
        
    }

}