当前位置: 首页 > 科技观察

正当我准备和SpringEvent优雅解耦的时候,连续的两个BUG把我搞糊涂了

时间:2023-03-21 12:19:11 科技观察

介绍P6Spy是一个轻量级的框架,可以无缝拦截和记录数据库的执行,不需要对现有应用进行代码改动。原理是将原始数据源打包,在SQL执行前后做一些功能增强。执行效果如图所示。集成方式P6Spy提供了3种集成方式:数据源方式:如果我们的项目中使用了自定义的Datasource,我们可以使用P6DataSource对原始数据源进行封装,只需要在P6DataSource的构造函数中导入自定义的DataSource即可,这也是使用P6Spy的最简单方法。连接URL方式:由于我们一般使用框架提供的数据源,P6Spy也提供了包裹链接的功能。只要在配置数据源时稍微修改配置属性,就可以使用P6Spy的功能。SpringBoot自动配置:随着Springboot的流行,P6Spy也提供了基于Springboot的自动配置。如何使用本节主要讲解第二种方法的使用。第一步,介绍P6Spy。p6spyp6spy3.9.1第二步,修改数据源的配置。spring:datasource://这里的url添加p6spyurl:jdbc:p6spy:mysql://127.0.0.1:3306/dbNameusername:usernamepassword:pwd123456//把普通的MySQL驱动换成P6SpyDriverdriver-class-name:com.p6spy.engine.spy.P6SpyDriver第三步:新建一个spy.properties文件,放在resources目录下。module.log=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory//注意这一行配置logMessageFormat=com.shishan.demo2023.bean.P6SpyMessageFormattingStrategyappender=com.p6spy.engine.spy。appender.Slf4JLoggerderegisterdrivers=trueuseprefix=trueexcludecategories=info,debug,result,resultsetdateformat=yyyy-MM-ddHH:mm:ssoutagedetection=trueoutagedetectioninterval=2filter=trueexclude=QRTZ_JOB_DETAILS,QRTZ_TRIGGERS,QRTZ_CRON_TRIGGERS,QRTZ_LOCKS,QRTZ_FIRED_TRIGGERS,QRTZ_PAUSED_TRIGGER_GRPS,QRTZ_SCHEDULER_STATE需要注意配置参数logMessageFormat,这里我们需要指定一个实现了MessageFormattingStrategy的类来自由打印我们的sql。第四步,新建一个类实现MessageFormattingStrategy,重写formatMessage方法。@Slf4jpublicclassP6SpyMessageFormattingStrategyimplementsMessageFormattingStrategy{@OverridepublicStringformatMessage(intconnectionId,Stringnow,longelapsed,Stringcategory,Stringprepared,Stringsql,Stringurl){//执行时间大于1000ms时,打印slowsqlif(elapsed>1000){log.warn("慢sql,耗时:{}ms,sql:{}",elapsed,sql.replaceAll("[\\s]+",""));}returnStrUtil.format("耗时:{}ms,Sql:{}",elapsed,category.equals("commit")||category.equals("rollback")?category:sql.replaceAll("[\\s]+",""));}}formatMessage方法提供了7个参数,可以自由组合,其中常用的参数有elapsed和sql。简单介绍一下这7个参数的具体含义:connectionId:当前连接的id。now:当前时间,以毫秒为单位。elapsed:sql执行耗时。需要注意的是,这里的耗时指的是从向服务器发送sql到收到服务器响应结果的总耗时,而不是sql本身在服务器上的执行时间。category:操作的类型,比如query、update、commit、rollback等。prepared:编译后的sql不打印具体参数。sql:具体执行sql,参数占位符会被真正的参数值代替。url:当前数据库连接。效果经过以上4步,P6Spy可以帮我们自动打印执行的sql。下面新建一个controller看看具体效果。@RestController@RequestMapping(value="/demo")publicclassDemoController{@ResourceprivateUserRepositoryuserRepository;@RequestMapping(value="/test")publicResponseEntitytest(){Useruser=newUser();user.setName("张三");user.setPwd("123");用户保存=this.userRepository.save(user);System.out.println(JSON.toJSONString(保存));Iterableall=this.userRepository.findAll();all.forEach(值->System.out.println(JSON.toJSONString(值)));返回ResponseEntity.ok().build();}}启动项目,访问http://localhost:8080/demo/test,看控制台打印效果:与MybatisPlus集成由于很多Spring项目也使用了MybatisPlus,所以MP也提供了对P6Spy的支持。使用方法也很简单,只需对步骤2稍作修改即可。spring:datasource:url:jdbc:mysql://127.0.0.1:3306/dbusername:usernamepassword:pwd123456driver-class-name:com.mysql.cj.jdbc.Driver//添加配置使用p6spy函数p6spy:true最后,P6Spy通过对数据源的封装实现了一系列的功能增强,方便我们打印sql执行状态。但相应的,如果在生产环境中开启了p6spy的打印功能,对性能还是会有一定的影响。建议您在测试环境中启用该功能,这对于跟踪和修复Bug非常有帮助。