Mybatis log printf工具網頁地址: http://www.feedme.ltd/log.html
Mybatis執行的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里有一個插件Mybatis log plugin可以幫我們快速的提取參數拼成完整的SQL語句執行,以快速排錯,但是很可惜,他是收費的ε=(´ο`*)))唉,整來整取也沒法破解,算了,不如自己寫一個掛到公網上,也能復制sql隨時拼接,純js即可。
下面我們來逐步分析一下需要的步驟:
- 首先需要提取出preparedStatement語句
- 提取出所有的參數,String類型還需要手動添加引號
- 將statement中的占位符?替換為對應的參數
很簡單吧,就這三步即可。接下來動手操作。
1、提取statement:只需截取從Preparing到行尾的\n即可
1
2
|
// str為完整的三行或兩行SQL 提取預編譯語句 let prepare = str.substring(str.indexOf( 'Preparing' ) + 11 , str.indexOf( '\n' )) |
indexOf(str: string):提取第一個匹配到的字符串的位置,返回其索引值
2、提取參數:只需截取從Parameters到其行尾的\n即可
這時我們需要提取到str的第二個\n換行符,怎么提取某個字符串中的第n個字符串呢?
indexOf()函數在js中是有重載的,默認提取第一個匹配的。它可以接受第二個參數,可以傳入一個起始位置,即從position(索引)開始取第一個匹配的。
1
2
|
// js api indexOf(searchString: string, position?: number): number; |
分析:取第二個\n,我們可以將第一個\n的索引傳入再加1;取第三個\n,則將第二個\n的索引傳入加1,以此類推,所以這是一個遞歸函數,實現如下
1
2
3
4
5
6
7
8
9
10
|
// 返回字符串str中的第n字符串reg在str中的索引值index function index(str, reg, n) { if (!str || !reg || n <= 0 ) return - 1 // 先求出第一個,再遞歸n-1 if (n === 1 ) { return str.indexOf(reg) } // 注意n-1的索引后一定要加1,負責會一直是第一個reg的索引 return str.indexOf(reg, index(str, reg, n - 1 ) + 1 ) } |
接下來先測試一下index函數,打印正確
1
2
3
|
const str = 'hello world ok' const reg = '0' console.log(index(str, reg, 3 )) // 求第三個o的索引,打印結果是12,正確 |
完成函數提取,所以回到上面的步驟,繼續提取第二個\n的位置
1
2
|
// 獲取參數字符串,去掉所有空格 const params = str.substring(str.indexOf( 'Parameters' ) + 12 , index(str, '\n' , 2 )).replace(/ /g, '' ) |
獲取參數后以逗號切割,返回是一個字符串參數數組
1
2
|
const array = params.split( ',' ) // ['2743672230717162752(Long)','1(Integer)','登錄(String)','3(Integer)'] |
提取完畢,則進行第三步的替換
3、替換參數
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// 遍歷數組,每次調用一次replace(old, new)即可,對字符串參數需要加上引號 array.map(item => { // 獲取每個參數值 let newValue = item.substring( 0 , item.indexOf( '(' )) // 獲取參數類型 const type = item.substring(item.indexOf( '(' ) + 1 , item.indexOf( ')' )) if ( 'String' === type) { newValue = "'" + newValue + "'" } prepare = prepare .replace( '?' , newValue) }) // 遍歷完畢,所有的占位符也就被參數替換完成啦 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())) |
這樣我們就實現了整個的js遍歷、尋找、替換邏輯,整個過程就是不停的去indexOf(),substring()和replace(),是不是很簡單呢,手寫一個就不用了去找插件了。
我把這個網頁放在了我的公網服務器上,訪問地址是http://www.feedme.ltd/log.html
方便直接打開使用。
另外懶得寫樣式和DOM,所以在線引用了vue.js和elemenui,可能會出現有時候加載js文件速度比較慢的情況。
最后貼出整個HTML代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
<!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= "" /> <!-- 引入樣式 --> <link rel= "stylesheet" href= "https://unpkg.com/element-ui/lib/theme-chalk/index.css" rel= "external nofollow" > <!-- 引入組件庫 --> <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= "請復制輸入Mybatis打印的日志,須完整Prepareing語句和Parameter語句" :rows= "28" style= "width: 600px" ></el-input> <el-button type= "success" @click = "convert" style= "height: 60px; width: 80px;" >轉換</el-button> <el-input type= "textarea" v-model= "res" placeholder= "輸出結果" :rows= "28" style= "width: 600px" ></el-input> </div> <script type= "text/javascript" > const app = new Vue({ el: '#app' , data() { return { // 原始str pre: '' , // 輸出結果 res: '' } }, methods: { convert() { const str = this .pre if (str.indexOf( 'Preparing' ) == - 1 || str.indexOf( 'Parameters' ) == - 1 ) { this .$message({ message: '請將Preparing和Parameters語句復制進來' , type: 'error' , center: true }) } // str為完整的三行或兩行SQL 提取預編譯語句 let prepare = str.substring(str.indexOf( 'Preparing' ) + 11 , str.indexOf( '\n' )) // 獲取參數,去空格 const params = str.substring(str.indexOf( 'Parameters' ) + 12 , index(str, '\n' , 2 )).replace(/ /g, '' ) // 參數數組 const array = params.split( ',' ) // 循環替換占位符,字符串方式替換每次替換第一個 array.map(item => { // 獲取每個參數值 let newValue = item.substring( 0 , item.indexOf( '(' )) // 獲取參數類型 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 // 先求出第一個,再遞歸n-1 if (n === 1 ) { return str.indexOf(reg) } // 注意n-1的索引后一定要加1,負責會一直是第一個reg的索引 return str.indexOf(reg, index(str, reg, n - 1 ) + 1 ) } // 測試index函數 const str = 'hello world ok' const reg = 'o' console.log(index(str, reg, 3 )) </script> </body> </html> |
總結
到此這篇關于Mybatis日志參數快速替換占位符工具的文章就介紹到這了,更多相關Mybatis日志參數替換占位符內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/weixin_43030522/article/details/107778854