slf4j+log4j+logback總結

java開發過程當中爲了找問題方便或是統計信息方便,總免不了要打各類日誌。以前的各個項目都是配置好的,maven配置的時候,會看到各類類型的Log包:slf4j、log4j、commons-log、logback等等,看着就煩,今天仔細瞭解了一下,有點收穫,記錄一下html

原由java

使用JAVA的kafka api寫main方法進行開發測試,發現總報錯apache

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

解決過程api

第一直覺是缺乏log4j的配置。好辦,classpath下加入log4j.properties(log4j默認應該是直接找classpath下的這個文件,固然,能夠直接指定加載哪一個文件),OK,不報錯了bash

恰好最近的一個項目使用的是logback,並且網上也查了,logback性能要優於log4j(沒有作過測試,先盲目從衆吧),就想直接引入logback。app

POM中加入logback的依賴maven

<dependency>
          <groupId>ch.qos.logback</groupId>
          <artifactId>logback-core</artifactId>
          <version>1.1.2</version>
      </dependency>
      <dependency>
          <groupId>ch.qos.logback</groupId>
          <artifactId>logback-access</artifactId>
          <version>1.1.2</version>
      </dependency>
      <dependency>
          <groupId>ch.qos.logback</groupId>
          <artifactId>logback-classic</artifactId>
          <version>1.1.2</version>
      </dependency>

啓動,報錯性能

log4j:WARN No appenders could be found for logger (kafka.utils.VerifiableProperties).
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: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/Users/zhaohuayu/.m2/repository/org/slf4j/slf4j-log4j12/1.6.1/slf4j-log4j12-1.6.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/Users/zhaohuayu/.m2/repository/ch/qos/logback/logback-classic/1.1.2/logback-classic-1.1.2.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 [org.slf4j.impl.Log4jLoggerFactory]

哦,Class path contains multiple SLF4J bindings。測試

原來slf4j提供的是一個抽象的接口,實現能夠是log4j、logback等,可是,運行時候只能有一個接口實現類。以前引入的kafka包,已經包含了對log4j的依賴,我又引入logback的包,衝突了spa

好辦,去掉對Log4j的依賴

<dependency>
          <groupId>org.apache.kafka</groupId>
          <artifactId>kafka_2.10</artifactId>
          <version>0.8.2.0</version>
          <exclusions>
              <exclusion>
                  <groupId>log4j</groupId>
                  <artifactId>log4j</artifactId>
              </exclusion>
              <exclusion>
                  <groupId>org.slf4j</groupId>
                  <artifactId>slf4j-log4j12</artifactId>
              </exclusion>
          </exclusions>
      </dependency>
      <dependency>
          <groupId>ch.qos.logback</groupId>
          <artifactId>logback-core</artifactId>
          <version>1.1.2</version>
      </dependency>
      <dependency>
          <groupId>ch.qos.logback</groupId>
          <artifactId>logback-access</artifactId>
          <version>1.1.2</version>
      </dependency>
      <dependency>
          <groupId>ch.qos.logback</groupId>
          <artifactId>logback-classic</artifactId>
          <version>1.1.2</version>
      </dependency>

這下總OK了吧,運行:

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Logger
	at kafka.utils.Logging$class.logger(Logging.scala:24)
	at kafka.utils.VerifiableProperties.logger$lzycompute(VerifiableProperties.scala:26)
	at kafka.utils.VerifiableProperties.logger(VerifiableProperties.scala:26)
	at kafka.utils.Logging$class.info(Logging.scala:67)
	at kafka.utils.VerifiableProperties.info(VerifiableProperties.scala:26)
	at kafka.utils.VerifiableProperties.verify(VerifiableProperties.scala:217)
	at kafka.producer.ProducerConfig.<init>(ProducerConfig.scala:57)
	at KafkaProducer.getClient(KafkaProducer.java:26)
	at KafkaProducer.sendMsg(KafkaProducer.java:35)
	at KafkaProducer.main(KafkaProducer.java:41)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

what?

kafka.utils.Logging裏包含了對log4j類的引用……

package kafka.utils;

import kafka.utils.Log4jController.;
import org.apache.log4j.Logger;

怎麼辦?難道使用kafka的項目必須使用log4j?

總有解決方案,

 <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>log4j-over-slf4j</artifactId>
          <version>1.7.7</version>
      </dependency>

再次運行,OK,日誌正常打印了

總結

一、slf4j提供各類抽象接口,日誌應該基於slf4j的API進行日誌打印,這樣不管遷移到那個項目,只須要配一個實現類log4j or logback,都能正常打印日誌

二、slf4j的實現類不能有多個,否則衝突

三、若是項目中有直接引用log4j的,能夠加入log4j-over-slf4j,把舊的日誌log4j適配到slf4j,這時候,再使用logback就能夠了。

分享一個博客中解決各個項目模塊中,各類日誌雜亂的方案

<dependency>  
    <groupId>org.slf4j</groupId>  
    <artifactId>slf4j-api</artifactId>  
    <version>${org.slf4j-version}</version>  
</dependency>  
<dependency>  
    <groupId>org.slf4j</groupId>  
    <artifactId>jcl-over-slf4j</artifactId>  
    <version>${org.slf4j-version}</version>  
</dependency>  
<dependency>  
    <groupId>org.slf4j</groupId>  
    <artifactId>log4j-over-slf4j</artifactId>  
    <version>${org.slf4j-version}</version>  
</dependency>  
<dependency>  
    <groupId>org.slf4j</groupId>  
    <artifactId>jul-to-slf4j</artifactId>  
    <version>${org.slf4j-version}</version>  
</dependency>  
<dependency>  
    <groupId>org.jboss.logging</groupId>  
    <artifactId>jboss-logging</artifactId>  
    <version>3.1.4.GA</version>  
</dependency>  

固然,前提是須要把各個項目中依賴的log實現exclusion掉

相關文章
相關標籤/搜索