Mybatis日志參數(shù)快速替換占位符工具的詳細(xì)步驟
Mybatis log printf工具網(wǎng)頁(yè)地址: http://www.feedme.ltd/log.html
Mybatis執(zhí)行的sql的打印格式為:
2020-08-04 09:16:44 -DEBUG - [io-8888-exec-5] .mapper.operation.OperationMapper.insert. debug 145 : ==> Preparing: INSERT INTO tulu.t_log_operation (id, module, module_description, type, method, operator, operate_time) VALUES (?, ?, ?, ?, ?, ?, unix_timestamp(now()))
2020-08-04 09:16:44 -DEBUG - [io-8888-exec-5] .mapper.operation.OperationMapper.insert. debug 145 : ==> Parameters: 2743672230717162752(Long), 1(Integer), 登錄(String), 3(Integer), com.simba.tuloosa.controller.auth.LoginController.nativeLogin(String), 6d63b98cbe5e42d18c126da149162404(String)
2020-08-04 09:16:44 -DEBUG - [io-8888-exec-5] .mapper.operation.OperationMapper.insert. debug 145 : <== Updates: 1
IDEA里有一個(gè)插件Mybatis log plugin可以幫我們快速的提取參數(shù)拼成完整的SQL語(yǔ)句執(zhí)行,以快速排錯(cuò),但是很可惜,他是收費(fèi)的ε=(´ο`*)))唉,整來(lái)整取也沒(méi)法破解,算了,不如自己寫一個(gè)掛到公網(wǎng)上,也能復(fù)制sql隨時(shí)拼接,純js即可。
下面我們來(lái)逐步分析一下需要的步驟:
- 首先需要提取出preparedStatement語(yǔ)句
- 提取出所有的參數(shù),String類型還需要手動(dòng)添加引號(hào)
- 將statement中的占位符?替換為對(duì)應(yīng)的參數(shù)
很簡(jiǎn)單吧,就這三步即可。接下來(lái)動(dòng)手操作。
1、提取statement:只需截取從Preparing到行尾的\n即可
// str為完整的三行或兩行SQL 提取預(yù)編譯語(yǔ)句
let prepare = str.substring(str.indexOf('Preparing') + 11, str.indexOf('\n'))
indexOf(str: string):提取第一個(gè)匹配到的字符串的位置,返回其索引值
2、提取參數(shù):只需截取從Parameters到其行尾的\n即可
這時(shí)我們需要提取到str的第二個(gè)\n換行符,怎么提取某個(gè)字符串中的第n個(gè)字符串呢?
indexOf()函數(shù)在js中是有重載的,默認(rèn)提取第一個(gè)匹配的。它可以接受第二個(gè)參數(shù),可以傳入一個(gè)起始位置,即從position(索引)開始取第一個(gè)匹配的。
// js api indexOf(searchString: string, position?: number): number;
分析:取第二個(gè)\n,我們可以將第一個(gè)\n的索引傳入再加1;取第三個(gè)\n,則將第二個(gè)\n的索引傳入加1,以此類推,所以這是一個(gè)遞歸函數(shù),實(shí)現(xiàn)如下
// 返回字符串str中的第n字符串reg在str中的索引值index
function index(str, reg, n) {
if (!str || !reg || n <= 0) return -1
// 先求出第一個(gè),再遞歸n-1
if (n === 1) {
return str.indexOf(reg)
}
// 注意n-1的索引后一定要加1,負(fù)責(zé)會(huì)一直是第一個(gè)reg的索引
return str.indexOf(reg, index(str, reg, n - 1) + 1)
}
接下來(lái)先測(cè)試一下index函數(shù),打印正確
const str = 'hello world ok' const reg = '0' console.log(index(str, reg, 3)) // 求第三個(gè)o的索引,打印結(jié)果是12,正確
完成函數(shù)提取,所以回到上面的步驟,繼續(xù)提取第二個(gè)\n的位置
// 獲取參數(shù)字符串,去掉所有空格
const params = str.substring(str.indexOf('Parameters') + 12, index(str, '\n', 2)).replace(/ /g, '')
獲取參數(shù)后以逗號(hào)切割,返回是一個(gè)字符串參數(shù)數(shù)組
const array = params.split(',')
// ['2743672230717162752(Long)','1(Integer)','登錄(String)','3(Integer)']
提取完畢,則進(jìn)行第三步的替換
3、替換參數(shù)
// 遍歷數(shù)組,每次調(diào)用一次replace(old, new)即可,對(duì)字符串參數(shù)需要加上引號(hào)
array.map(item => {
// 獲取每個(gè)參數(shù)值
let newValue = item.substring(0, item.indexOf('('))
// 獲取參數(shù)類型
const type = item.substring(item.indexOf('(') + 1, item.indexOf(')'))
if ('String' === type) {
newValue = "'" + newValue + "'"
}
prepare = prepare .replace('?', newValue)
})
// 遍歷完畢,所有的占位符也就被參數(shù)替換完成啦
console.log(prepare)
// INSERT INTO tulu.t_log_operation (id, module, module_description, type, method, operator, operate_time) VALUES (2743672230717162752, 1, '登錄', 3, 'com.simba.tuloosa.controller.auth.LoginController.nativeLogin', '6d63b98cbe5e42d18c126da149162404', unix_timestamp(now()))
這樣我們就實(shí)現(xiàn)了整個(gè)的js遍歷、尋找、替換邏輯,整個(gè)過(guò)程就是不停的去indexOf(),substring()和replace(),是不是很簡(jiǎn)單呢,手寫一個(gè)就不用了去找插件了。
我把這個(gè)網(wǎng)頁(yè)放在了我的公網(wǎng)服務(wù)器上,訪問(wèn)地址是http://www.feedme.ltd/log.html
方便直接打開使用。
另外懶得寫樣式和DOM,所以在線引用了vue.js和elemenui,可能會(huì)出現(xiàn)有時(shí)候加載js文件速度比較慢的情況。
最后貼出整個(gè)HTML代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Mybatis Log Helper</title>
<meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="shortcut icon" href="" />
<script src="https://unpkg.com/vue@2.6.11/dist/vue.js"></script>
<!-- 引入樣式 -->
<link rel="stylesheet" rel="external nofollow" >
<!-- 引入組件庫(kù) -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<style>
#app {
margin-top: 70px;
display: flex;
justify-content: space-evenly;
align-items: center;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微軟雅黑", Arial, sans-serif;
}
</style>
</head>
<body>
<div id="app">
<el-input type="textarea" v-model="pre" placeholder="請(qǐng)復(fù)制輸入Mybatis打印的日志,須完整Prepareing語(yǔ)句和Parameter語(yǔ)句"
:rows="28" style="width: 600px"></el-input>
<el-button type="success" @click="convert" style="height: 60px; width: 80px;">轉(zhuǎn)換</el-button>
<el-input type="textarea" v-model="res" placeholder="輸出結(jié)果"
:rows="28" style="width: 600px"></el-input>
</div>
<script type="text/javascript">
const app = new Vue({
el: '#app',
data() {
return {
// 原始str
pre: '',
// 輸出結(jié)果
res: ''
}
},
methods: {
convert() {
const str = this.pre
if (str.indexOf('Preparing') == -1 || str.indexOf('Parameters') == -1) {
this.$message({
message: '請(qǐng)將Preparing和Parameters語(yǔ)句復(fù)制進(jìn)來(lái)',
type: 'error',
center: true
})
}
// str為完整的三行或兩行SQL 提取預(yù)編譯語(yǔ)句
let prepare = str.substring(str.indexOf('Preparing') + 11, str.indexOf('\n'))
// 獲取參數(shù),去空格
const params = str.substring(str.indexOf('Parameters') + 12, index(str, '\n', 2)).replace(/ /g, '')
// 參數(shù)數(shù)組
const array = params.split(',')
// 循環(huán)替換占位符,字符串方式替換每次替換第一個(gè)
array.map(item => {
// 獲取每個(gè)參數(shù)值
let newValue = item.substring(0, item.indexOf('('))
// 獲取參數(shù)類型
const type = item.substring(item.indexOf('(') + 1, item.indexOf(')'))
if ('String' === type) {
newValue = "'" + newValue + "'"
}
prepare = prepare .replace('?', newValue)
})
this.res = prepare
}
}
})
// 返回字符串str中的第n字符串reg在str中的索引值index
function index(str, reg, n) {
if (!str || !reg || n <= 0) return -1
// 先求出第一個(gè),再遞歸n-1
if (n === 1) {
return str.indexOf(reg)
}
// 注意n-1的索引后一定要加1,負(fù)責(zé)會(huì)一直是第一個(gè)reg的索引
return str.indexOf(reg, index(str, reg, n - 1) + 1)
}
// 測(cè)試index函數(shù)
const str = 'hello world ok'
const reg = 'o'
console.log(index(str, reg, 3))
</script>
</body>
</html>
總結(jié)
到此這篇關(guān)于Mybatis日志參數(shù)快速替換占位符工具的文章就介紹到這了,更多相關(guān)Mybatis日志參數(shù)替換占位符內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
從java源碼分析線程池(池化技術(shù))的實(shí)現(xiàn)原理
這篇文章主要介紹了從java源碼分析線程池(池化技術(shù))的實(shí)現(xiàn)原理,池化技術(shù)是一種編程技巧,當(dāng)程序出現(xiàn)高并發(fā)時(shí),能夠明顯的優(yōu)化程序,降低系統(tǒng)頻繁創(chuàng)建銷毀連接等額外開銷,下文更多的相關(guān)介紹需要的小伙伴可以參考一下2022-04-04
優(yōu)化spring?boot應(yīng)用后6s內(nèi)啟動(dòng)內(nèi)存減半
這篇文章主要為大家介紹了優(yōu)化spring?boot后應(yīng)用6s內(nèi)啟動(dòng)內(nèi)存減半的優(yōu)化示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-02-02
java去除集合中重復(fù)元素示例分享 java去除重復(fù)
這篇文章主要介紹了java去除集合中重復(fù)元素示例,大家參考使用吧2014-01-01
Session過(guò)期后自動(dòng)跳轉(zhuǎn)到登錄頁(yè)面的實(shí)例代碼
這篇文章主要介紹了Session過(guò)期后自動(dòng)跳轉(zhuǎn)到登錄頁(yè)面實(shí)例代碼,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06
如何將SpringBoot項(xiàng)目打成?war?包并部署到Tomcat
這篇文章主要介紹了如何將SpringBoot項(xiàng)目?打成?war?包?并?部署到?Tomcat,當(dāng)前環(huán)境是windows,tomcat版本是8.5采用的springboot版本是2.2.3,本文結(jié)合實(shí)例代碼給大家詳細(xì)講解需要的朋友可以參考下2022-11-11
springBoot中的CORS跨域注解@CrossOrigin詳解
這篇文章主要介紹了springBoot中的CORS跨域注解@CrossOrigin詳解,通常,服務(wù)于?JS?的主機(jī)(例如?example.com)與服務(wù)于數(shù)據(jù)的主機(jī)(例如?api.example.com)是不同的,在這種情況下,CORS?可以實(shí)現(xiàn)跨域通信,需要的朋友可以參考下2023-12-12
深入淺析Mybatis與Hibernate的區(qū)別與用途
這篇文章主要介紹了Mybatis與Hibernate的區(qū)別與用途的相關(guān)資料,需要的朋友可以參考下2017-10-10

