簡介
P6Spy是一個輕量級框架,只需簡單配置,就可以無縫地攔截和記錄資料庫執行sql以及耗時,而無需對現有應用程式進行代碼更改。其原理是包裝原有的數據源,在sql執行前後做一些功能增強。
集成方式
P6Spy提供了3種集成方式:
- Datasource way:如果我們的項目中使用了自定義的DataSource,可以使用P6DataSource對原有的數據源進行包裝,只需將自定義的DataSource傳入P6DataSource的構造函數中即可,這也是使用P6Spy最簡單的一種方式。
- Connection URL way:由於我們一般都是用框架提供的數據源,所以P6Spy也提供了對連結進行包裝的功能。只要在配置數據源時,稍微修改配置的屬性,即可使用P6Spy的功能。
- Spring Boot autoconfiguration:隨著Spring boot的流行,P6Spy還提供了基於Springboot的自動配置。
如何使用
本節主要針對第2種方式的使用進行講解。
步驟一,引入P6Spy。
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>3.9.1</version>
</dependency>
步驟二,修改數據源的配置。
spring:
datasource:
//此處的URL增加了p6spy
url: jdbc:p6spy:MySQL://127.0.0.1:3306/dbName
username: username
password: pwd123456
//將普通的mysql驅動替換為P6SpyDriver
driver-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.P6SpyMessageFormattingStrategy
appender=com.p6spy.engine.spy.appender.Slf4JLogger
deregisterdrivers=true
useprefix=true
excludecategories=info,debug,result,resultset
dateformat=yyyy-MM-dd HH:mm:ss
outagedetection=true
outagedetectioninterval=2
filter=true
exclude=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方法。
@Slf4j
public class P6SpyMessageFormattingStrategy implements MessageFormattingStrategy {
@Override
public String formatMessage(int connectionId, String now, long elapsed,
String category, String prepared, String sql, String url) {
//執行時間大於1000ms時,列印慢sql
if (elapsed > 1000) {
log.warn("slow sql,耗時:{}ms,sql:{}", elapsed, sql.replaceAll("[\\s]+", " "));
}
return StrUtil.format("耗時:{}ms,Sql:{}",
elapsed,
category.equals("commit") || category.equals("rollback") ? category :
sql.replaceAll("[\\s]+", " "));
}
}
formatMessage方法提供了7個參數,這7個參數大家可以自由組合,其中常用的參數有elapsed和sql。
簡單介紹一下這7個參數的具體含義:
1,connectionId:當前connection的id。
2,now:當前時間,毫秒值。
3,elapsed:sql執行的耗時。需要注意的是這裡的耗時指的是從發送sql到伺服器截止到收到伺服器響應結果的總耗時,而不是sql本身在伺服器的執行時間。
4,category:操作的類型,比如查詢,更新,commit,rollback等。
5,prepared:編譯後的sql,不列印具體的參數。
6,sql:具體的執行sql,參數占位符會被真正的參數值替換。
7,url:當前的資料庫連接。
效果
經過以上4個步驟,P6Spy就可以幫助我們自動列印執行的sql了。我們新建一個controller看看具體的效果。
@RestController
@RequestMapping(value = "/demo")
public class DemoController {
@Resource
private UserRepository userRepository;
@RequestMapping(value = "/test")
public ResponseEntity<Object> test() {
User user = new User();
user.setName("張三");
user.setPwd("123");
User save = this.userRepository.save(user);
System.out.println(JSON.toJSONString(save));
Iterable<User> all = this.userRepository.findAll();
all.forEach(value -> System.out.println(JSON.toJSONString(value)));
return ResponseEntity.ok().build();
}
}
啟動項目,訪問http://localhost:8080/demo/test,看一下控制台的列印效果:
與Mybatis Plus的集成
由於很多的Spring項目也使用了Mybatis Plus,所以MP也提供了對P6Spy的支持。使用方式也很簡單,只需對步驟二稍微做一點修改即可。
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/db
username: username
password: pwd123456
driver-class-name: com.mysql.cj.jdbc.Driver
//增加一個配置即可使用p6spy的功能
p6spy:true
最後
P6Spy通過對數據源的包裝,進而實現了一系列的功能增強,讓我們可以方便的列印sql執行情況。但是相應的,如果在生產環境開啟p6spy的列印功能,對性能還是由一定的影響的。
建議大家在測試環境開啟此功能,對跟蹤、修復bug都很有幫助。
學習技術,分享技術,期待與大家共同進步,也感謝您的點讚與關注。