如何正确配置 gradle build 以避免生成的 jar 中包含 log4j 和 slf4j?

2024-04-15

我的 spring-boot 应用程序遇到问题:我可以在 Eclipse 中运行它,但无法运行 jar 文件(使用 gradle 构建)。 我运行以下命令来构建我的项目:

gradle buid

构建成功:

 gradle build
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:findMainClass
:jar
:bootRepackage
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

Total time: 1.214 secs

这是生成的 jar 文件的片段:

jar -tvf build/libs/springboot-receiver-api-0.1.0.jar | grep log
  9988 Mon Apr 04 20:37:48 CDT 2016 BOOT-INF/lib/slf4j-log4j12-1.7.21.jar
  2308 Wed Sep 21 07:11:50 CDT 2016 BOOT-INF/lib/spring-boot-starter-logging-1.4.1.RELEASE.jar
 66802 Thu May 28 09:49:34 CDT 2015 BOOT-INF/lib/jboss-logging-3.3.0.Final.jar
304075 Tue Mar 29 22:24:50 CDT 2016 BOOT-INF/lib/logback-classic-1.1.7.jar
 23646 Mon Apr 04 20:39:02 CDT 2016 BOOT-INF/lib/log4j-over-slf4j-1.7.21.jar
470782 Tue Mar 29 22:23:42 CDT 2016 BOOT-INF/lib/logback-core-1.1.7.jar
489884 Sun May 06 13:24:48 CDT 2012 BOOT-INF/lib/log4j-1.2.17.jar

当我尝试运行此 jar 文件时,出现以下错误:

  java -jar build/libs/springboot-receiver-api-0.1.0.jar
        SLF4J: Class path contains multiple SLF4J bindings.
        SLF4J: Found binding in [jar:file:/Users/eugene/.Trash/springboot-receiverapi/build/libs/springboot-receiver-api-0.1.0.jar!/BOOT-INF/lib/slf4j-log4j12-1.7.21.jar!/org/slf4j/impl/StaticLoggerBinder.class]
        SLF4J: Found binding in [jar:file:/Users/eugene/.Trash/springboot-receiverapi/build/libs/springboot-receiver-api-0.1.0.jar!/BOOT-INF/lib/logback-classic-1.1.7.jar!/org/slf4j/impl/StaticLoggerBinder.class]
        SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
        SLF4J: Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path, preempting StackOverflowError.
    Exception in thread "main" java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:58)
    Caused by: java.lang.ExceptionInInitializerError
        at org.slf4j.impl.StaticLoggerBinder.<init>(StaticLoggerBinder.java:72)
Caused by: java.lang.IllegalStateException: Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path, preempting StackOverflowError. See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.
    at org.slf4j.impl.Log4jLoggerFactory.<clinit>(Log4jLoggerFactory.java:54)
    ... 19 more

这是我的 build.gradle 文件:

apply plugin: 'java'
apply plugin: 'maven'

group = 'uptake'
version = '0.0.1-snapshot'

description = """Spring-Boot-ReceiverAPI"""

sourceCompatibility = 1.8
targetCompatibility = 1.8
tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}



repositories {

     maven { url "http://repo.maven.apache.org/maven2" }
}
dependencies {
    compile(group: 'org.springframework.boot', name: 'spring-boot-starter-web', version:'1.2.3.RELEASE') {
exclude(module: 'log4j-over-slf4j')
    }
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version:'1.2.3.RELEASE'
    compile group: 'org.postgresql', name: 'postgresql', version:'9.3-1102-jdbc41'
    compile group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-hibernate4', version:'2.8.1'
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version:'2.8.3'
    compile group: 'org.apache.kafka', name: 'kafka_2.10', version:'0.9.0.0'
    compile group: 'org.springframework.integration', name: 'spring-integration-kafka', version:'2.0.1.RELEASE'
    compile group: 'org.apache.zookeeper', name: 'zookeeper', version:'3.4.5'
    compile(group: 'commons-beanutils', name: 'commons-beanutils', version:'1.9.2') {
exclude(module: 'commons-logging')
    }
    compile group: 'org.json', name: 'json', version:'20090211'
    compile group: 'org.codehaus.jackson', name: 'jackson-mapper-asl', version:'1.5.0'
    compile(group: 'org.springframework', name: 'spring-core', version:'4.3.3.RELEASE') {
exclude(module: 'commons-logging')
    }
    compile group: 'com.spotify', name: 'docker-maven-plugin', version:'0.4.13'
}
configurations.all {
    exclude group: "org.slf4j", module: "slf4j-log4j12"
    exclude group: "log4j", module: "log4j"
}

我该怎么做才能避免日志库的冲突,并能够独立运行我的 jar 文件?


几件事,在我看来,你的 build.gradle 应该声明:

  • Spring Boot Gradle 插件
  • 应用 Spring Boot 插件
  • 让 spring boot 管理大部分依赖版本

这个脚本对我有用:

apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'spring-boot'

group = 'uptake'
version = '0.0.1-snapshot'

description = """Spring-Boot-ReceiverAPI"""

sourceCompatibility = 1.8
targetCompatibility = 1.8
tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.springframework.boot:spring-boot-gradle-plugin:1.4.1.RELEASE'
    }
}

repositories {
     maven { url "http://repo.maven.apache.org/maven2" }
}

dependencies {
    compile 'org.springframework.boot:spring-boot-starter'
    compile 'org.springframework.boot:spring-boot-starter-logging'
    compile 'org.springframework.boot:spring-boot-starter-web'
    compile 'org.springframework.boot:spring-boot-starter-data-jpa'
    compile 'org.postgresql:postgresql'
    compile 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate4'
    compile 'com.fasterxml.jackson.core:jackson-core'
    compile 'org.apache.kafka:kafka_2.10:0.9.0.0'
    compile 'org.springframework.integration:spring-integration-kafka:2.0.1.RELEASE'
    compile 'org.apache.zookeeper:zookeeper:3.4.5'
    compile 'commons-beanutils:commons-beanutils'
    compile 'org.json:json'
    compile 'org.codehaus.jackson:jackson-mapper-asl:1.5.0'
    compile 'org.springframework:spring-core'
    compile 'com.spotify:docker-maven-plugin:0.4.13'
}

configurations.all {
    exclude module: 'slf4j-log4j12'
    exclude module: 'jms'
    exclude module: 'jmxtools'
    exclude module: 'jmxri'
}

现在,如果您检查两个模块gradle依赖洞察,只会找到 log4j-over-slf4j:

$ gradle dependencyInsight --dependency slf4j-log4j12
$ No dependencies matching given input were found...

$ gradle dependencyInsight --dependency log4j-over-slf4j
:dependencyInsight
org.slf4j:log4j-over-slf4j:1.7.21 (selected by rule)
\--- org.springframework.boot:spring-boot-starter-logging:1.4.1.RELEASE
     +--- compile
     \--- org.springframework.boot:spring-boot-starter:1.4.1.RELEASE
          +--- compile
          +--- org.springframework.boot:spring-boot-starter-web:1.4.1.RELEASE
          |    \--- compile
          +--- org.springframework.boot:spring-boot-starter-data-jpa:1.4.1.RELEASE
          |    \--- compile
          +--- org.springframework.boot:spring-boot-starter-aop:1.4.1.RELEASE
          |    \--- org.springframework.boot:spring-boot-starter-data-jpa:1.4.1.RELEASE (*)
          \--- org.springframework.boot:spring-boot-starter-jdbc:1.4.1.RELEASE
               \--- org.springframework.boot:spring-boot-starter-data-jpa:1.4.1.RELEASE (*)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何正确配置 gradle build 以避免生成的 jar 中包含 log4j 和 slf4j? 的相关文章

随机推荐