JAVA日志系統(tǒng)的演變史
我們先看一個故事查邢。項目經(jīng)理A帶著一幫兄弟開發(fā)了一套復雜的企業(yè)ERP系統(tǒng)蔗崎,這個系統(tǒng)一連開發(fā)了好幾年,開發(fā)人員也換了好幾撥扰藕。
階段一:最開始的時候缓苛,項目經(jīng)理A安排小B在系統(tǒng)中添加日志功能,在控制臺上打印一些必要的信息邓深。最開始的時候未桥,由于項目的功能比較少,于是小B就是用System.out.println的方式打印日志信息芥备。經(jīng)理A感覺這樣使用比較方便冬耿,也便于項目小組人員的使用,于是就沿用了下來萌壳。
階段二:此時小B被借調(diào)到其他項目淆党,小C加入到了項目組中。此時項目經(jīng)理A要求改造日志系統(tǒng)讶凉,要求能把日志寫到一個文件中,方便以后分析用戶行為山孔。小C在查看了以前的日志方式之后懂讯,感覺特別low,于是自己寫了一個日志框架台颠,命名為xiaoC-logging.jar褐望,此舉收到了項目經(jīng)理A的好評。
階段三:項目組中加入了一個大牛老D串前,老D發(fā)現(xiàn)xiaoC-logging.jar這個日志框架雖然可以滿足基本的日志要求瘫里,但是還不夠高大上,沒有一些諸如自動歸檔荡碾,異步寫入文件谨读,把日志文件寫入NoSQL數(shù)據(jù)庫中等功能。于是老D開發(fā)了一個更高級的日志框架叫oldD-logging.jar坛吁。
階段四:oldD-logging.jar開發(fā)完成之后劳殖,需要把原來的xiaoC-logging.jar中的日志API做修改铐尚,把之前的日志實現(xiàn)寫下來,換上高大上的oldD-logging.jar哆姻。
階段五:在這個卸載與上新的過程中宣增,老D的工作量陡增,他感覺很累矛缨。不過姜還是老的辣爹脾,他參考了JDBC和spring中面向接口的編程方式,制定了一個日志的門面(一系列的接口)箕昭,以后所有的日志的記錄灵妨,都只面向接口編程,至于今后怎么去實現(xiàn)盟广,都要遵循這個接口就可以了闷串。?
我剛整理了一套2018最新的0基礎入門和進階教程,無私分享筋量,加Java學習裙 :678-241-563 即可獲取烹吵,內(nèi)附:開發(fā)工具和安裝包,以及系統(tǒng)學習路線圖
那么在JAVA開發(fā)中桨武,這正的日志系統(tǒng)是怎么演變的呢肋拔?簡短地描述下日志發(fā)展,最先出現(xiàn)的是apache開源社區(qū)的log4j呀酸,這個日志確實是應用最廣泛的日志工具凉蜂,成為了java日志的事實上的標準。然而性誉,當時Sun公司在jdk1.4中增加了JUL日志實現(xiàn)窿吩,企圖對抗log4j,但是卻造成了混亂错览,這個也是被人詬病的一點纫雁。當然也有其他日志工具的出現(xiàn),這樣必然造成開發(fā)者的混亂倾哺,因為這些日志系統(tǒng)互相沒有關聯(lián)轧邪,替換和統(tǒng)一也就變成了比較棘手的一件事。想象下你的應用使用log4j羞海,然后使用了一個其他團隊的庫忌愚,他們使用了JUL,你的應用就得使用兩個日志系統(tǒng)了却邓,然后又有第二個庫出現(xiàn)了硕糊,使用了simplelog。
這個時候估計讓你崩潰了,這是要鬧哪樣癌幕?這個狀況交給你來想想辦法衙耕,你該如何解決呢?進行抽象勺远,抽象出一個接口層橙喘,對每個日志實現(xiàn)都適配或者轉(zhuǎn)接,這樣這些提供給別人的庫都直接使用抽象層即可胶逢。不錯厅瞎,開源社區(qū)提供了commons-logging抽象,被稱為JCL初坠,也就是日志框架了和簸,確實出色地完成了兼容主流的日志實現(xiàn)(log4j、JUL碟刺、simplelog)锁保,基本一統(tǒng)江湖,就連頂頂大名的spring也是依賴了JCL半沽。
看起來事物確實是美好爽柒,但是美好的日子不長,接下來另一個優(yōu)秀的日志框架slf4j的加入導致了更加混亂的場面者填。比較巧的是slf4j的作者(Ceki Gülcü)就是log4j的作者浩村,他覺得JCL不夠優(yōu)秀,所以他要自己搞一套更優(yōu)雅的出來占哟,于是slf4j日志體系誕生了心墅,并為slf4j實現(xiàn)了一個親子——logback,確實更加優(yōu)雅榨乎,但是由于之前很多代碼庫已經(jīng)使用JCL怎燥,雖然出現(xiàn)slf4j和JCL之間的橋接轉(zhuǎn)換,但是集成的時候問題依然多多蜜暑,對很多新手來說確實會很懊惱铐姚,因為比單獨的log4j時代“復雜”多了,抱怨聲確實很多史煎。到此本來應該完了,但是Ceki Gülcü覺得還是得回頭拯救下自己的“大阿哥”——log4j驳糯,于是log4j2誕生了篇梭,同樣log4j2也參與到了slf4j日志體系中,想必將來會更加混亂酝枢。接下來詳細解讀日志系統(tǒng)的配合使用問題恬偷。slf4j的設計確實比較優(yōu)雅,采用比較熟悉的方式——接口和實現(xiàn)分離帘睦,有個純粹的接口層——slf4j-api工程袍患,這個里邊基本完全定義了日志的接口坦康,所以對于開發(fā)來說,只需要使用這個即可诡延。
有接口就要有實現(xiàn)滞欠,比較推崇的實現(xiàn)是logback,logback完全實現(xiàn)了slf4j-api的接口肆良,并且性能也比log4j更好筛璧,同時實現(xiàn)了變參占位符日志輸出方式等等新特性。剛剛也提到log4j的使用比較普遍惹恃,所以支持這批用戶依然是必須的夭谤,slf4j-log4j12也實現(xiàn)了slf4j-api,這個算是對log4j的適配器巫糙。同樣推理朗儒,也會有對JUL的適配器slf4j-jdk14等等。為了使使用JCL等等其他日志系統(tǒng)后者實現(xiàn)的用戶可以很簡單地切換到slf4j上來参淹,給出了各種橋接工程醉锄,比如:jcl-over-slf4j會把對JCL的調(diào)用都橋接到slf4j上來,可以看出jcl-over-slf4j的api和JCL是相同的承二,所以這兩個jar是不能共存的榆鼠。jul-to-slf4j是把對jul的調(diào)用橋接到slf4j上,log4j-over-slf4j是把對log4j的調(diào)用橋接到slf4j亥鸠。
日志門面和日志實現(xiàn)
我們需要在左邊選一個門面(抽象層)妆够、右邊來選一個實現(xiàn)。那么最優(yōu)選擇就是
日志門面: SLF4J负蚊,日志實現(xiàn):Logback神妹。
SpringBoot的底層是Spring框架,Spring框架默認是用JCL家妆。但是SpringBoot選用 SLF4j和logback鸵荠;
slf4j使用原理規(guī)則
我們進入到slf4j的官網(wǎng),打開用戶手冊伤极,即可看到簡單的用法案例:
slf4j簡單用法
當然在使用之前蛹找,需要導入slf4j的jar和 logback的實現(xiàn)jar,但是如果是換做其他的日志實現(xiàn)哨坪,需要哪些jar包的依賴呢庸疾,官方網(wǎng)站給我們提供了一個圖:
我們看一下這個圖,上面的每一列都是講如何把slf4j(日志門面)與其他日志的實現(xiàn)進行整合的過程当编。其中淺藍色表示抽象的日志API届慈,即我們說的日志門面(slf4j-api.jar),深藍色是具體的日志實現(xiàn),青色表示一個日志的適配器金顿,灰色表示和slf4j沒有直接關聯(lián)的日志實現(xiàn)臊泌。
第一列:日志門面使用的是slf4j-api.jar,但是沒有任何日志實現(xiàn)的話揍拆,那么日志講不會輸出任何內(nèi)容渠概。
第二列:說的是slf4j和logback如何綁定。日志門面使用的是slf4j-api.jar礁凡,那么日志的實現(xiàn)使用logback-classic.jar和logback-core.jar高氮。我們之前講過,logback是slf4j的親兒子顷牌,所以slf4j可以和logback無縫連接剪芍。
第三列:說的是slf4j和log4j如何綁定,我們知道slf4j和log4j的作者是同一個人窟蓝,但是作為借口出現(xiàn)的slf4j出現(xiàn)的要比log4j晚罪裹,所以slf4j和log4j并不能無縫連接,需要一個適配層slf4j-log4j12.jar运挫。然后這個適配器實現(xiàn)了slf4j-api.jar中的接口和抽象類状共,但是是實現(xiàn)還是用的log4j的API去實現(xiàn)。由此解決了log4和slf4j整合的問題谁帕。
第四列:說的是slf4j和JUL(java.util.logging)如何綁定峡继,原理同第三列。
第五列:slf4j本身也提供了一個簡單實現(xiàn)匈挖,叫做slf4j-simple.jar碾牌。二者可以無縫連接。
第六列:slf4j本身也提供了一個沒有任何實現(xiàn)的slf4j-nop.jar儡循。這日志沒有任何操作舶吗,不會輸出日志。
看懂這個圖择膝,就了解了需要導入哪些jar文件的依賴了誓琼。每一個日志的實現(xiàn)框架都有自己的配置文件。但是以后的日志系統(tǒng)里面肴捉,這么多的日志實現(xiàn)腹侣,應該使用什么樣的日志配置文件呢,我們有個原則就是:使用slf4j以后齿穗,配置文件還是做成日志實現(xiàn)框架自己本身的配置文件傲隶。
其他日志框架統(tǒng)一轉(zhuǎn)換為slf4j
回想我們在做ssm框架整合的時候,spring和springmvc使用的是JCL(jarkart commons-logging)缤灵,mybatis使用的是log4j日志框架伦籍,有可能其他的jar文件依賴的是JCL(Java util logging),那么怎么把這些不同的的日志框架轉(zhuǎn)化為同意的slf4j的日志呢腮出,官方網(wǎng)站里給我們提供了一個圖:
第一塊:
說的是一個系統(tǒng)中帖鸦,如果要是用slf4j作統(tǒng)一的日志門面,并且用logback做日志的實現(xiàn)胚嘲,但是此時還有commons-logging作儿、log4j、jul等日志實現(xiàn)怎么辦呢馋劈?此時需要用jcl-over-slfj.jar替代commons-logging攻锰,用log4j-over-slf4j.jar替代log4j.jar,并且添加jul-to-slf4j.jar(不能替換掉JUL妓雾,因為這是JDK自帶的)
第二塊:
說的是一個系統(tǒng)中娶吞,如果要是用slf4j作統(tǒng)一的日志門面,并且用log4j做日志的實現(xiàn)械姻,但是此時還有commons-logging妒蛇、jul等日志實現(xiàn)怎么辦呢?此時需要用jcl-over-slfj.jar替代commons-logging楷拳,并且添加jul-to-slf4j.jar(不能替換掉JUL绣夺,因為這是JDK自帶的),并且添加slf4j和log4j的適配層slf4j-log4j12.jar以及實現(xiàn)層log4j.jar欢揖。
第三塊:
說的是一個系統(tǒng)中陶耍,如果要是用slf4j作統(tǒng)一的日志門面,并且用JUL做日志的實現(xiàn)她混,但是此時還有commons-logging烈钞、log4j等日志實現(xiàn)怎么辦呢?此時需要用jcl-over-slfj.jar替代commons-logging产上,用log4j-over-slf4j.jar替代log4j.jar棵磷,并且添加slf-jdk14.jar作為適配層,最后是用JDK自帶的JUL作為日志的實現(xiàn)晋涣。
總結(jié):如何讓系統(tǒng)中所有的日志都統(tǒng)一到slf4j仪媒;
1、將系統(tǒng)中其他日志框架先排除出去谢鹊;
2算吩、用中間包來替換原有的日志框架(根據(jù)上圖);
3佃扼、我們導入slf4j其他的實現(xiàn)