Java 在maven项目中解析多个SLF4J绑定

Java 在maven项目中解析多个SLF4J绑定,java,maven,dependencies,slf4j,logback,Java,Maven,Dependencies,Slf4j,Logback,这是一个听起来像是SE站点上的一堆问题,所以我应该非常详细地说明我的问题。因此,这里是项目的最小值pom.xml: <dependencies> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.0.6<

这是一个听起来像是SE站点上的一堆问题,所以我应该非常详细地说明我的问题。因此,这里是项目的最小值
pom.xml

<dependencies>
     <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.0.6</version>
    </dependency>

   <dependency>
        <groupId>org.codehaus.gmaven.runtime</groupId>
        <artifactId>gmaven-runtime-1.7</artifactId>
        <version>1.3</version>
   </dependency>

</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.2.1</version>
            <configuration>
                <mainClass>org.shabunc.App</mainClass>
            </configuration>
        </plugin>
    </plugins>
</build>
现在,让我们删除排除并再次检查依赖项。我们将得到:

 [INFO] org.shabunc:logdebug:jar:1.0-SNAPSHOT
[INFO] +- ch.qos.logback:logback-classic:jar:1.0.6:compile
[INFO] |  \- org.slf4j:slf4j-api:jar:1.6.5:compile
[INFO] \- org.codehaus.gmaven.runtime:gmaven-runtime-1.7:jar:1.3:compile
[INFO]    +- (org.slf4j:slf4j-api:jar:1.5.10:compile - omitted for conflict with 1.6.5)
[INFO]    +- org.codehaus.gmaven.feature:gmaven-feature-support:jar:1.3:compile
[INFO]    |  \- (org.slf4j:slf4j-api:jar:1.5.10:compile - omitted for conflict with 1.6.5)
[INFO]    \- org.codehaus.gmaven.runtime:gmaven-runtime-support:jar:1.3:compile
[INFO]       +- (org.slf4j:slf4j-api:jar:1.5.10:compile - omitted for conflict with 1.6.5)
[INFO]       \- org.sonatype.gshell:gshell-io:jar:2.0:compile
[INFO]          \- org.sonatype.gossip:gossip:jar:1.0:compile
[INFO]             \- (org.slf4j:slf4j-api:jar:1.5.8:compile - omitted for conflict with 1.6.5)
所以,正如我们所看到的,一切都按预期进行,冲突依赖实际上被排除。但问题是,即使排除了依赖项,我在编译和调用
mvn exec:java
时仍然会收到以下消息:

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/shabunc/.m2/repository/ch/qos/logback/logback-classic/1.0.6/logback-classic-1.0.6.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/shabunc/.m2/repository/org/sonatype/gossip/gossip/1.0/gossip-1.0.jar!/org/slf4j/impl/StaticLoggerBinder.class]

问题是:为什么我仍然看到这个警告,以及在执行过程中应该做些什么才能只访问一个版本的slf4j?

我想您需要处理依赖项的范围,请参阅:

classpathScope
- 定义传递给插件的类路径的范围。根据需要设置为编译、测试、运行时或系统


你所需要做的就是添加这样的内容

compile "org.sonatype.gossip:gossip:1.0" {
    exclude module:'slf4j-jcl'
    exclude module:'slf4j-log4j12'
}

您的问题不是获取两个SLF4J API副本,而是获取两个不同的SLF4J实现。你需要排除流言蜚语,而不是API。这意味着:

<dependency>
    <groupId>org.codehaus.gmaven.runtime</groupId>
    <artifactId>gmaven-runtime-1.7</artifactId>
    <version>1.3</version>
    <exclusions>
      <exclusion>
        <groupId>org.sonatype.gossip</groupId>
        <artifactId>gossip</artifactId>
      </exclusion>
    </exclusions>
</dependency>

org.codehaus.gmaven.runtime
gmaven-runtime-1.7
1.3
org.sonatype.gossip
流言蜚语

Gossip依赖项由
gshell io
声明;希望它实际上不需要八卦,它只需要一个SLF4J SLF4J,您正在以Logback的形式提供它。

请您更具体一点,我仍然不知道设置classpathScope如何帮助解决这个问题。这个问题是由于所使用的八卦jar的传递依赖性造成的。上面的代码将sl4j实现的依赖性排除在流言之外。“类似这样的东西”在这里的意思是“这个Gradle代码的Maven等价物”@TomAnderson ya…很抱歉我没有提到:)@Byter你能不能,请,提供一个maven等效的,因为我仍然不明白你的确切意思。如果你的意思是我也应该添加这些排除,这是行不通的——正如我在这个问题中已经说过的,依赖性:树已经不认为八卦/SLF4J依赖性是项目的一部分。唯一让SLF4J快乐的方法是移除你对回溯的依赖,或者排除gS壳IO对八卦的依赖。然而,我不能保证这不会产生戏剧性的后果。我希望不是这样——对于一个库来说,直接依赖于日志实现是非常糟糕的。检查gshell io是否有真正的Gossip依赖的方法是下载jar(或源代码),并从Gossip中搜索对类型的引用。如果没有,你就安全了。如果有的话,你可能还是安全的,因为代码是经过仔细编写的。但是,我刚刚看了一下,似乎没有经过仔细编写。存在直接依赖关系-请参阅和。这真的很糟糕。编写该代码的人应该坐牢。@shabunc:我的意思是,该代码可以直接依赖于日志API(在本例中为SLF4J),但不应该依赖于特定的实现。这样,代码的用户(在本例中是您)就可以选择正确的实现。库甚至可以指定特定实现的运行时依赖项,提供默认值,但它应该允许排除和替换该依赖项。这就像当你使用JDBC时——你依赖于JDBCAPI,但不依赖于从特定driver.PS到Jason Dillon的类,以防他读到这样的评论:我并不认为你应该坐牢。这只是一个夸张的比喻,表达了可以对相关代码进行改进的观点。我认为社区服务或罚款就足够了。无意冒犯,但声明依赖slf4j api,然后排除slf4j api是错误的。下面的说法也不正确。“让我们确保slf4j api确实只加载一次,就像我们在gmaven运行时依赖项中添加排除/排除部分时所预期的那样。”当依赖项声明工件的不同版本时,例如slf4j api,Maven不会在类路径上多次放置slf4j api。即使Maven这样做了(事实并非如此),slf4j api也不会被多次加载。请编辑您的问题,以免误导未来的读者。Ceki,即使是冒犯也没关系,这会教我一些东西。)事实是slf4j api被多次加载,因此在我试图将其作为war部署到tomcat时会产生冲突。一个slf4j为logblack,另一个为gmaven运行时依赖项的依赖项。如果我遗漏了什么,如果您能说得更清楚,那将是非常感谢的,因为所有这些依赖项解析都不是我所擅长的。如果您使用的是Maven,那么您的类路径上就不会出现不同版本的slf4j api。但是,不同的slf4j绑定(例如slf4j-jdj14.jar、slf4j-log4j.jar或logback-classic.jar)通常同时出现在类路径上。在您的情况下,现在有logback-classic-1.0.6.jar-1.0.jar。Tom Anderson已经为排除“流言蜚语”提供了一个很好的答案。抱歉,可能我只是不理解你的意思,但看起来这正是你所说的不可能的:有不同的SLF4J绑定-SLF4J:请参阅以获取解释。SLF4J:SLF4J api 1.6.x(或更高版本)与此绑定不兼容。SLF4J:您的绑定版本为1.5.5或更低版本。SLF4J:将绑定升级到1.6.x版。或者2.0.x您是否注意到“mvn dependency:tree”生成的输出包含类似“org.slf4j:slf4j api:jar:1.5.10:compile-省略以与1.6.5冲突”这样的行?当Maven检测到工件的冲突(读取不同)版本被拉入时,它将保留声明的最接近当前项目pom的版本。其他版本的工件的其他声明将被忽略(=省略)。因此,相反
<dependency>
    <groupId>org.codehaus.gmaven.runtime</groupId>
    <artifactId>gmaven-runtime-1.7</artifactId>
    <version>1.3</version>
    <exclusions>
      <exclusion>
        <groupId>org.sonatype.gossip</groupId>
        <artifactId>gossip</artifactId>
      </exclusion>
    </exclusions>
</dependency>