【分享】JFinal集成Druid优雅地打印sql

环境JFinal 4.9,打印输出效果如下:

image.png

看了前辈的帖子,但是感觉都不是自己想要的,druid虽然自带打印sql功能,但是我很讨厌它打印的sql,附加了太多我不关注的信息,当然,生产模式会切换使用它,而开发模式使用自己简洁优雅的sql输出。

需求:开发时控制台打印清爽的sql,于是就自己写了个玩一玩:

MyDruidFilter.java: 
import com.alibaba.druid.filter.FilterAdapter;
import com.alibaba.druid.filter.FilterChain;
import com.alibaba.druid.proxy.jdbc.JdbcParameter;
import com.alibaba.druid.proxy.jdbc.StatementProxy;
import com.alibaba.druid.sql.SQLUtils;
import com.jfinal.log.Log;
import com.jfinal.log.Log4jLog;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/*
    author: Timor
    date: 2020/7/12 0012
*/
public class MyDruidFilter extends FilterAdapter {
    private static final Log log = Log4jLog.getLog(MyDruidFilter.class);
    private boolean formatSQL = false;

    public MyDruidFilter() {}

    public MyDruidFilter(boolean formatSQL) {
        this.formatSQL = formatSQL;
    }

    @Override
    public void statement_close(FilterChain chain, StatementProxy statement) throws SQLException {
        super.statement_close(chain, statement);
        String sql = statement.getBatchSql();

        // 不输出无意义的内容
        if(sql.isEmpty()) return;

        int parametersSize = statement.getParametersSize();
        if (parametersSize > 0) {
            List<Object> parameters = new ArrayList<>(parametersSize);

            for(int i = 0; i < parametersSize; ++i) {
                JdbcParameter jdbcParam = statement.getParameter(i);
                parameters.add(jdbcParam != null ? jdbcParam.getValue() : null);
            }
            // 这里可以使用数据库类型常量
            String dbType = statement.getConnectionProxy().getDirectDataSource().getDbType();
            if(formatSQL){
                sql = SQLUtils.format(sql, dbType, parameters, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);
            }
        }

        // 打印sal
        printSQL(sql);
    }

    public void printSQL(String sql){
        String sb = "\n"
                + "MyDruidFilter SQL report ---------- " + new Date().toString() + " ---------------\n"
                + sql.trim()
                + "\n--------------------------------------------------------------------------------\n";
        // 这会输出一些看着不爽的信息……
        // log.info(sb);
        System.out.println(sb);
    }
}

在config里面加载过滤器:

image.png

大功告成,启动后等sql执行就可在控制台看见优雅地sql了


评论区

JFinal

2020-07-22 15:47

在 statement_close 回调中输出 sql ,这个思路不错,赞

山东小木

2020-07-22 16:20

在Druid里内置已经实现了 Slf4jLogFilter druid里的 配置一下就出来了

BTMTimor

2020-07-22 16:26

@山东小木 了解,但是开发时它打印的sql不方便阅读

山东小木

2020-07-22 17:50

@BTMTimor 可以配置完整输出sql 不是问号的那种 输出的是最终完整sql

BTMTimor

2020-07-22 18:33

@山东小木 我是因为它打印格式化sql时的select xxx,y yy会在log信息后面,要滑动滚动条才能看到,我希望在开发时可以输出我关注的信息,不想看到这一串:[DEBUG]-[Thread: XNIO-1 task-8]-[com.alibaba.druid.filter.logging.Log4jFilter.statementLog()]: {conn-10001, pstmt-20040} executed.。当然,非开发模式启动时我配置了它会使用druid自带的,性能优异。

BTMTimor

2020-07-22 18:33

@山东小木 所以开发模式就没用druid自带的

JAdmins

2020-07-24 10:00

写得不错,不过日期字段可以稍微处理一下,会更好。