SpringBoot+P6Spy实现优雅打印sql日志
作者:互联网
SpringBoot+P6Spy实现优雅打印sql日志
引言
此前做过的一个springBoot项目,sql日志打印十分优雅简洁,sql语句在控制台特殊标色比较显眼,而且打印出来的是包括参数在内的实际执行sql,还打印出了sql耗时和执行时间,对于问题定位分析特别有帮助。
正好最近在做一个门户网站开发的需求,所用的框架是SpringBoot+MybatisPlus,和上述的项目框架是一样的,就想着直接复用之前这个项目的sql日志打印方式(之前这个项目的日志相关开发我完全没接触),但是没想到因为对P6Spy框架的不了解踩了一些坑,通过一步步的摸索才最终达到了理想的效果。
踩坑历程
项目使用的日志框架是logback,这里我直接将之前项目的logback-spring.xml和spy.properties配置文件修改一些参数
复制过来使用,配置文件部分内容如下:
logback-spring.xml:
<!-- 日志输出级别 -->
<root level="info">
<appender-ref ref="businessLogFile"/>
<appender-ref ref="STDOUT"/>
<!--<appender-ref ref="sqlLogFile"/>-->
</root>
<logger name="org.springframework.jdbc.core.JdbcTemplate" additivity="false" level="DEBUG">
<appender-ref ref="sqlLogFile"/>
</logger>
spy.properties:
module.log=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前缀
useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,batch,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 真实JDBC driver , 多个以 逗号 分割 默认为空
#driverlist=org.h2.Driver
driverlist=oracle.jdbc.OracleDriver
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2
我感觉这样就可以了,但是项目启动之后控制台却没有任何的sql日志打印,第一反应是MybatisPlus配置的问题,在yml文件中MybatisPlus的配置如下:
mybatis-plus:
mapper-locations: classpath*:mapper/oracle/*/*.xml
type-aliases-package: com.ztesoft.datasync.*.entity
在网上查了MybatisPlus控制台为什么不打印日志之后,我修改了配置文件:
mybatis-plus:
mapper-locations: classpath*:mapper/oracle/*/*.xml
type-aliases-package: com.ztesoft.datasync.*.entity
configuration:
# 是否将sql打印到控制面板(该配置会将sql语句和查询的结果都打印到控制台)
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
重新启动项目,结果却没有任何变化。我就想着是不是logback配置文件的问题,是不是因为缺少sql日志的配置,但是logback的配置文件是直接复用之前项目的,应该没有问题。不过基于验证一下问题根源的想法,我还是在logback配置文件里增加了一条配置,用于扫描mapper接口,并且将日志级别定义为DEBUG级别:
<!--打印sql语句和参数-->
<logger name="com.ztesoft.datasync.datasyncdao.mapper" level="DEBUG" />
重新启动项目,控制台能打印sql日志了!但是好像跟P6Spy框架优雅简洁的自定义sql日志没有什么关系,这个是mybatis框架的日志:
关于P6Spy
最后,我终于想到了问题是不是出在我对P6Spy的使用方式有误,通过搜索P6Spy框架的使用,我发现了P6Spy正确打开方式,其实非常简单:P6Spy是一个可以用来在应用程序中拦截和修改数据操作语句的开源框架,通过劫持JDBC驱动,在调用实际JDBC驱动前拦截调用的目标语,达到SQL语句日志记录的目的。应用P6Spy只需要:
1.添加依赖
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>3.8.7</version>
</dependency>
2.替换你的JDBC Driver为com.p6spy.engine.spy.P6SpyDriver
3.修改JDBC Url为jdbc:p6spy:xxxx
4.配置spy.properties
1和4都没问题,问题出在了2和3,因为之前项目的数据源是mysql,现在这个项目是oracle,所以没注意到之前项目数据源的JDBC Driver和JDBC Url都是p6spy的:
而我的却是这样的:
怪不得在配置文件一样的前提下怎么也达不到之前项目的效果。这就是只知道复制粘贴,不懂还不去研究技术实质的代价!修改完配置文件之后重启项目,完美实现:
拓展
p6spy的自定义日志打印实现方式有两种,第一种在配置文件中指定logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger,这也是我的项目使用的方式,P6SpyLogger实现了MessageFormattingStrategy接口,自定义了log格式信息:
public class P6SpyLogger implements MessageFormattingStrategy {
public P6SpyLogger() {
}
public String formatMessage(int connectionId, String now, long elapsed, String category, String prepared, String sql, String url) {
return StringUtils.isNotEmpty(sql) ? " Consume Time:" + elapsed + " ms " + now + "\n Execute SQL:" + sql.replaceAll("[\\s]+", " ") + "\n" : null;
}
}
第二种是直接指定logMessageFormat的值,这样更加灵活,可以自己定义格式,比如:
logMessageFormat=%(currentTime) | SQL耗时: %(executionTime) ms | 连接信息: %(category)-%(connectionId) | 执行语句: %(sql)
可用的变量为:
# %(connectionId) connection id
# %(currentTime) 当前时间
# %(executionTime) 执行耗时
# %(category) 执行分组
# %(effectiveSql) 提交的SQL 换行
# %(effectiveSqlSingleLine) 提交的SQL 不换行显示
# %(sql) 执行的真实SQL语句,已替换占位
# %(sqlSingleLine) 执行的真实SQL语句,已替换占位 不换行显示
结语
开发一个新的项目,直接复用其他项目的功能是很正常的事情,使用自己之前没接触过的框架也很正常,但是如果接触到之后,不先简单了解和研究就直接一股脑的复制粘贴,那就很容易踩到各种各样的坑。而且因为自己根本就不熟悉,所以解决问题也会花费更多的时间,更难受的是问题解决以后才发现原来如此的简单和基础,但是却花费了自己大量的时间,感到非常后悔和不值。所以还是建议对于自己要用到的没接触过的技术和框架,还是先了解了解再上手使用。
标签:SpringBoot,P6Spy,配置文件,打印,sql,日志,p6spy 来源: https://blog.csdn.net/weixin_45087127/article/details/114365322