中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java日志出問題的原因有哪些

發布時間:2021-10-12 13:53:44 來源:億速云 閱讀:177 作者:iii 欄目:編程語言

本篇內容主要講解“Java日志出問題的原因有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Java日志出問題的原因有哪些”吧!

用了那么久的日志框架,你是否仍會遇到即使配置了日志,日志依然不知去向?

來接受下面的 8 連發靈魂拷問!

Q1:你是否遇到過配置了logback,啟動時卻提示log4j錯誤的情況?像下面這樣:

log4j:WARN No appenders could be found for logger (org.example.App).  log4j:WARN Please initialize the log4j system properly.  log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

Q2:你是否遇到過 SLF4J 的這種報錯?

SLF4J: Class path contains multiple SLF4J bindings.  SLF4J: Found binding in [jar:file:/C:/Users/jiang/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/C:/Users/jiang/.m2/repository/org/slf4j/slf4j-log4j12/1.7.30/slf4j-log4j12-1.7.30.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]

Q3:你是否遇到過DUBBO日志打印不正常的情況?

Q4:你是否遇到過Mybatis SQL日志打印不出來的情況?

Q5:你是否遇到過JPA/Hibernate SQL日志無法打印的情況?

Q6:你是否遇到過復雜項目中,很多框架內部日志無法打印的情況?

Q7:你是否遇到過Tomcat工程,日志文件打印了多份,catalina.out和其他文件?

Q8:你是否遇到過SpringBoot項目,日志文件打印了多份的問題?

What!你還遇到過其他各種日志配置問題……

## 日志框架的沖突 這些問題,基本都是由于多套日志框架共存或配置錯誤導致的。> 為什么會出現共存或者沖突呢?

一般是以下幾種原因:

  •  項目手動引用了各種日志框架的包,比如同時引用了log4j/log4j2/logback/jboss-logging/jcl等

  •  包管理工具的傳遞依賴(Transitive Dependencies)導致,比如依賴了dubbo,但是dubbo依賴了zkclient,可zkclient又依賴了log4j,此時如果你的項目中還有其他日志框架存在并有使用,那么就會導致多套共存

  •  同一個日志框架多版本共存

JAVA里的各種日志框架

在正式介紹沖突和解決之前,需要先簡單的說一下Java中的各種日志框架:

Java 中的日志框架分為兩種,分別為日志抽象/門面,日志實現

日志抽象/門面

不負責具體的日志打印,如輸出到文件、配置日志內容格式等。這只是一套日志抽象,定義了一套統一的日志打印標準,如Logger對象,Level對象。

slf4j(Simple Logging Facade for Java)和 jcl(Apache Commons Logging)這兩個日志框架就是JAVA中最主流的日志抽象了。

還有一個 jboss-logging,主要用于jboss系列軟件,比如hibernate之類。像 jcl 已經多年不更新了(上一次更新時間還是14年),目前最推薦的是使用 slf4j。

日志實現

Java 中的日志實現框架,主流的有以下幾種:

  •  log4j,Apache(老牌日志框架,不過多年不更新了,新版本為log4j2)

  •  log4j2,Apache(log4j 的新版本,目前異步IO性能最強,配置也較簡單)

  •  logback,QOS(slf4j就是這家公司的產品)

  •  jul(java.util.logging),這是jdk內置

在程序中,可以直接使用日志框架,也可以使用日志抽象+日志實現搭配的方案。不過一般都是用日志抽象+日志實現,這樣更靈活,適配起來更簡單。

目前最主流的方案是 slf4j+logback/log4j2,不過如果是jboss系列的產品,可能用的更多的還是 jboss-logging,畢竟自家產的,總得用上去,是吧!像 JPA/Hibernate 這種框架里,內置的就是 jboss-logging。

SpringBoot + Dubbo 日志框架沖突的例子

舉個例子來說個最常見的傳遞依賴導致的共存沖突:比如我有一個“干凈的”spring-boot項目,干凈到只有一個spring-boot-starter依賴,此時我想集成dubbo,使用zookeeper作為注冊中心,此時我的依賴配置是這樣:

<dependencies>    <dependency>      <groupId>org.springframework.boot</groupId>      <artifactId>spring-boot-starter</artifactId>    </dependency>    <dependency>      <groupId>org.apache.dubbo</groupId>      <artifactId>dubbo-spring-boot-starter</artifactId>      <version>2.7.9</version>    </dependency>    <dependency>      <groupId>org.apache.dubbo</groupId>      <artifactId>dubbo-registry-zookeeper</artifactId>      <version>2.7.9</version>    </dependency>  </dependencies>

現在啟動這個spring-boot項目,會發現一堆紅色錯誤:

SLF4J: Class path contains multiple SLF4J bindings.  SLF4J: Found binding in [jar:file:/C:/Users/jiang/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:/C:/Users/jiang/.m2/repository/org/slf4j/slf4j-log4j12/1.7.30/slf4j-log4j12-1.7.30.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder] ----------------------------------我是分割線----------------------------------------  log4j:WARN No appenders could be found for logger (org.apache.dubbo.common.logger.LoggerFactory).  log4j:WARN Please initialize the log4j system properly.  log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

從錯誤提示上看,錯誤內容分為兩個部分:

  •  slf4j報錯,提示找到多個slf4j的日志綁定

  •  log4j報錯,提示log4j沒有appender配置

出現這個錯誤,就是因為 dubbo 的傳遞依賴中含有 log4j,但是 spring-boot 的默認配置是 slf4j+logback。在依賴了 dubbo 相關包之后,現在項目中同時存在 logback/jcl(apache commons-logging)/log4j/jul-to-slf4j/slf4j-log4j/log4j-to-slf4j。

來看一下依賴圖:

Java日志出問題的原因有哪些

這個時候就亂套了,slf4j-log4j 是 log4j 的 slf4j 實現,作用是調用 slf4j api 的時候使用 log4j 輸出;而 log4j-to-slf4j 的作用是將 log4j 的實現替換為 log4j,這樣一來造成了死循環。

而且還有 logback 的存在,logback 默認實現了 slf4j 的抽象,而 slf4j-log4j 也是一樣實現了 slf4j 的抽象。

logback 項目里共存了兩套 slf4j的實現,那么在使用slf4j接口打印的時候會使用哪個實現呢?

答案是“第一個”,也就是第一個被加載的Slf4j的實現類,但這種依靠ClassLoader加載順序來保證的日志配置順序是非常不靠譜的。

如果想正常使用日志,讓這個項目里所有的框架都正常打印日志,必須將日志框架統一。不過這里的統一并不是至強行修改,而是用“適配/中轉”的方式。

現在項目里雖然有 slf4j-log4j 的配置,但這個配置是適配 log4j2 用的,而我們的依賴了只有 log4j1,實際上這個中轉是無效的。但logback是有效的,而且是 spring-boot 項目的默認配置,這次就選擇 logback 作為項目的統一日志框架吧!

現在項目里存在 log4j(1) 的包,而且啟動時又報 log4j 的錯誤,說明某些代碼調用了 log4j 的 api。但我們又不想用 log4j,所以需要先解決 log4j 的問題。

由于有 log4j 代碼的引用,所以直接刪除 log4j 一定是不可行的。slf4j 提供了一個 log4j-over-slf4j 的包,這個包復制了一份 log4j1 的接口類(Logger等),同時將實現類修改為 slf4j 了。

所以將 log4j 的(傳遞)依賴排除,同時引用 log4j-over-slf4j,就解決了這個 log4j 的問題。現在來修改下 pom 中的依賴(查看依賴圖可以使用 maven 的命令,或者是 IDEA 自帶的 Maven Dependencies Diagram,再或者 Maven Helper 之類的插件)。

<dependency>    <groupId>org.apache.dubbo</groupId>    <artifactId>dubbo-registry-zookeeper</artifactId>    <version>2.7.9</version>    <scope>compile</scope>    <!--排除log4j-->    <exclusions>      <exclusion>        <artifactId>log4j</artifactId>        <groupId>log4j</groupId>      </exclusion>    </exclusions>  </dependency>  <!--增加log4j-slf4j -->  <dependency>      <groupId>org.slf4j</groupId>      <artifactId>log4j-over-slf4j</artifactId>      <version>1.7.30</version>  </dependency>

解決了log4j的問題之后,現在還有 slf4j 有兩個實現的問題,這個問題處理就更簡單了。由于我們計劃使用 logback,那么只需要排除/刪除 slf4j-log4j 這個實現的依賴即可。

<dependency>    <groupId>org.apache.dubbo</groupId>    <artifactId>dubbo-registry-zookeeper</artifactId>    <version>2.7.9</version>    <scope>compile</scope>    <exclusions>      <exclusion>        <artifactId>log4j</artifactId>        <groupId>log4j</groupId>      </exclusion>      <exclusion>        <artifactId>slf4j-log4j12</artifactId>        <groupId>org.slf4j</groupId>      </exclusion>    </exclusions>  </dependency>

修改完成,再次啟動就沒有錯誤了,輕松解決問題

日志適配大全

上面只是介紹了一種轉換的方式,但這么多日志框架,它們之間是可以互相轉換的。

最終目的都是統一一套日志框架,讓最終的日志實現只有一套

這么多的日志適配/轉換方式,全記住肯定是有點難。請看下圖來搭配記憶,如果再遇到沖突,需要將一個日志框架轉換到另一款的時候,只需要按照圖上的路徑,引入相關的依賴包即可。

Java日志出問題的原因有哪些

比如想把slf4j,適配/轉換到log4j2。按照圖上的路徑,只需要引用log4j-slf4j-impl即可。

如果想把jcl,適配/轉換到slf4j,只需要刪除jcl包,然后引用jcl-over-slf4j即可。

圖上的箭頭,有些標了文字的,是需要額外包進行轉換的,有些沒有標文字的,是內置了適配的實現。其實內置實現的這種會更麻煩,因為如果遇到共存基本都需要通過配置環境變量/配置額外屬性的方式來指定一款日志實現。

目前slf4j是適配方案中,最核心的那個框架,算是這個圖的中心樞紐。只要圍繞slf4j做適配/轉化,就沒有處理不了的沖突了。

到此,相信大家對“Java日志出問題的原因有哪些”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

临江市| 镶黄旗| 苏尼特右旗| 周至县| 芦溪县| 罗山县| 安义县| 文昌市| 耒阳市| 金山区| 财经| 玛曲县| 新田县| 通山县| 台东市| 泾川县| 土默特右旗| 股票| 资溪县| 库伦旗| 得荣县| 房山区| 都匀市| 临城县| 萝北县| 景德镇市| 遵化市| 平南县| 康保县| 石楼县| 富锦市| 明水县| 台安县| 绥化市| 武山县| 金秀| 会理县| 茶陵县| 金乡县| 修武县| 甘南县|