用Java统一Logger到SLF4J + Logback的聪明方法/ build.gradle的编写方式/ 2021年

本文是为了那些想要使用SLF4J的人而写的。

    • log4j 2.x を使っていない事を確かにしたい (2021年12月追記)

 

    • SLF4J に統一したはずなのに、たまにコンソールに謎ログが出てる。時刻が出ないとかある(実は log4j 1.x 経由でログがでてる)

あるいは log4j:WARN No appenders could be found for logger (com.example.Log4j1).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info. みたいなログが出る。

Class path contains multiple SLF4J bindings. SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation. なるログが出る

ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console… なるログができる
gradle/maven で exclude すると除外できるのは知ってるけど、新規ライブラリを追加したタイミングで log4j の実装が混入してログがでなくなったりしている
まとめて log4j や commons-logging を取り除きたい

更新

    Spring Boot 2.0 でだいぶ世界観が変わったので書き直しました

提示

关于除外的问题

可以使用以下语法一次性排除:

可以使用下面的句式一起排除。

configurations.all {
    exclude
}

依存版本统一

3.2. 单独使用Spring Boot的依赖管理非常方便。

即使没有使用Spring Boot,使用Gradle Plugin并将其视为好方法似乎是明智的。

plugins {
    id("org.springframework.boot") version "2.6.5" apply false
}

apply {
    plugin("io.spring.dependency-management")
}

dependencyManagement {
    imports {
        mavenBom(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
    }
}

用这个,你就不需要在实际使用时单独写版本号了。

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-web")
}

当类路径中含有多个SLF4J绑定时会报错”Class path contains multiple SLF4J bindings.”

似乎是 IntelliJ 的一个问题,当在依赖库中使用 SLF4J 并在运行时引入另一个版本的库时,通过 IntelliJ 内部进行调试/运行时,会出现两个 Jar 都被包含在 Classpath 中的问题。

基本上,只要进行依赖管理就可以了。

太长不看

第一种模式

在所有项目中,只需加入所需的各种日志库 > SLF4J 的模块,并排除各种日志库的实现即可。

buildscript {
    repositories {
        maven {
            url("https://plugins.gradle.org/m2/")
        }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.6.5")
    }
}

subprojects {
    apply {
        plugin("org.gradle.java")
        plugin("io.spring.dependency-management")
    }

    repositories {
        mavenCentral()
    }

    dependencyManagement {
        imports {
            mavenBom(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES) {
                extra["log4j2.version"] = "2.15.0"
                // Force update log4j2 from latest spring-boot preferred version.
                // It's not required to avoid CVE-2021-44228 because we don't use log4j2,
                // but seeing log4j-api < 2.15.0 is confusing.
            }
        }
    }

    dependencies {
        // Used compile/coding time.
        implementation("org.springframework.boot:spring-boot-starter-logging") // 実際は starter-web の依存とかに入ってることが多い

        // Used Runtime
        runtimeOnly("org.slf4j:log4j-over-slf4j")
        // log4j 1.x だけ個別にルーティングする必要がある
        // 2015 年に EOL のため 2017 年に spring-boot-starter-logging からも取り除かれている
        // https://github.com/spring-projects/spring-boot/issues/11148

        testImplementation("org.springframework.boot:spring-boot-starter-test")
    }

    configurations.all {
        // We are using logback for logging implementation (formatting & appenders).
        // Other logging implementation and "from slf4j bridge" are not necessary.
        // Let's remove those.
        exclude(group = "log4j") // = Old Log4j (1.x) implementation. Replaced by log4j-over-slf4j.
        exclude(module = "slf4j-log4j12") // = SLF4J -> Log4J Implementation by SLF4J. Not used (or cyclic dependences lol).
        exclude(module = "slf4j-jdk14") // = SLF4J -> JDK14 Binding. Not used.
        exclude(module = "slf4j-jcl") // = SLF4J -> Commons Logging. Not used.
        exclude(module = "commons-logging") // Because bridged by org.slf4j:jcl-over-slf4j.
        exclude(module = "commons-logging-api") // Replaced by org.slf4j:jcl-over-slf4j.
        exclude(group = "org.apache.logging.log4j", module = "log4j-core") // Remove log4j 2.x implementation. org.apache.logging.log4j:log4j-to-slf4j (Included in spring-boot-starter-logging) proxies log4j-api:2.x to slf4j.
    }
}

模式 2

建议创建一个专门的日志项目,其中包括日志设置等内容。

待会再写


广告
将在 10 秒后关闭
bannerAds