? 在我們編寫(xiě)程序的時(shí)候癞松,日志是必不可少的峦嗤,但是在并發(fā)較大或者涉及多線程的系統(tǒng)中院水,每個(gè)用戶的請(qǐng)求所產(chǎn)生的日志交差打印腊徙,也會(huì)導(dǎo)致日志顯示的混亂(如圖1 普通日志)简十,因此將每個(gè)日志標(biāo)志為分類成一個(gè)用戶訪問(wèn)所導(dǎo)致的日志是有一定合理性的(如圖2 日志歸類)。其實(shí)我們通過(guò)圖一和圖二就可以看出差別撬腾,我們可以通過(guò)錯(cuò)誤打印的唯一標(biāo)識(shí)符追蹤之前的處理過(guò)程以及參數(shù)螟蝙。怎么讓每個(gè)請(qǐng)求的日志標(biāo)志成一個(gè)呢?下文將圍繞一個(gè)用戶注冊(cè)實(shí)例的web應(yīng)用民傻,說(shuō)明如何便利生成唯一標(biāo)識(shí)符并在每個(gè)日志中展現(xiàn)出來(lái)的樣例胰默。
? ? 在這里做一個(gè)場(chǎng)景,我們?cè)谟脩暨M(jìn)行注冊(cè)帳號(hào)密碼的時(shí)候漓踢,后臺(tái)將這條記錄插入到數(shù)據(jù)庫(kù)中牵署,并開(kāi)啟一個(gè)線程發(fā)送郵件給對(duì)方的郵箱處,發(fā)送的郵件中默認(rèn)密碼是大于8位的喧半,前后兩位不作處理奴迅,中間做去敏操作(打*號(hào))。
一挺据、方法一(不推薦)
? ? 這是最為簡(jiǎn)單的方法取具,在一個(gè)請(qǐng)求產(chǎn)生的時(shí)候,我們生成一個(gè)唯一標(biāo)識(shí)符作為loggerID扁耐,然后一傳到底暇检,并在打印的時(shí)候,將loggerID打印出來(lái)婉称。具體的我們將以代碼展現(xiàn)块仆。
啟動(dòng)的main函數(shù):
? 總結(jié):雖然可以滿足需求,可以將所有日志歸類為一個(gè)用戶的請(qǐng)求產(chǎn)生的酿矢,但是過(guò)于耦合與繁雜榨乎,需要我們每次都將loggerID當(dāng)作參數(shù)一傳到底。這么繁瑣的方法瘫筐,而且還有一個(gè)問(wèn)題,當(dāng)exception打印出來(lái)的時(shí)候铐姚,并不會(huì)有l(wèi)oggerID出現(xiàn)策肝。
? 方法一有那么多的缺點(diǎn),這當(dāng)然不是我們這個(gè)博文所推薦了的隐绵,以下我們將介紹一個(gè)解耦并且不繁瑣的方式解決這個(gè)問(wèn)題之众。
二、方法二(推薦)
? 在此方法中依许,我們?nèi)匀皇褂玫氖荢pring Boot棺禾,logback與slf4j,之間我們會(huì)運(yùn)用到filter與aop峭跳。具體的做法是膘婶,制作一個(gè)Filter缺前,在每一個(gè)請(qǐng)求產(chǎn)生的時(shí)候,dispatcherServlet派發(fā)之前悬襟,生成一個(gè)唯一標(biāo)識(shí)符作為loggerID衅码,然后保存在MDC下和InheritableThreadLocal下,并在新產(chǎn)生的線程脊岳,在構(gòu)造這個(gè)這個(gè)線程對(duì)象的時(shí)候從InheritableThreadLocal獲取loggerID并將至保存在MDC下逝段。在打印的框架下配置相應(yīng)的打印格式,即可割捅。no bb奶躯,let me show code。
總結(jié):首先巫糙,需要寫(xiě)個(gè)filter,生成loggerID颊乘,保存到mdc與InheritableThreadLocal中参淹;第二,在新開(kāi)啟的線程寫(xiě)上aop(或者其他方式)乏悄,從父線程中獲取loggerID浙值,并保存到MDC中;第三檩小,在logback配置打印到mdc保存的loggerID开呐。這個(gè)方法前期工作需要設(shè)計(jì)好,后續(xù)不用不斷傳輸loggerID规求,成功解耦筐付,也不需要打印的時(shí)候?qū)oggerID顯示寫(xiě)上去了。
說(shuō)明:
1.代碼將會(huì)放到github上阻肿,我將普通打印日志瓦戚、方法一與方法二都放在了同一個(gè)項(xiàng)目,并將他們歸類為不同的包丛塌,person.caspar.commonlogger是沒(méi)有l(wèi)oggerID標(biāo)志的普通項(xiàng)目的實(shí)現(xiàn)较解;person.caspar.mdclogger是方法二的實(shí)現(xiàn);person.caspar.method1是方法一的實(shí)現(xiàn)赴邻。
2.在代碼中我將發(fā)送郵件直接放到了dao中印衔,由于時(shí)間關(guān)系我就懶得抽包,大家不要介意姥敛。
3.該博文的代碼:https://github.com/casparhuan/generateloggerid