所以我有4个Maven项目,让他们称之为A,B,C和D.项目A取决于项目B取决于项目C而项目A也取决于项目D.
d
^
|
A - > B - > C
项目A和B使用slf4j
项目C使用java.util.logging
项目D使用log4j
现在我真的不知道如何设置它的日志记录依赖项以使其正常工作。
我拥有的是:
项目D取决于log4j
,而不是其他任何东西
项目C完全不依赖,因为它只使用了Java的日志实用程序
项目B依赖于slf4j-api
以及jul-to-slf4j
来记录C日志的内容
项目A取决于slf4j-api
,slf4j-log4j12
和log4j
项目A是我想要运行的主程序。它有一个log4j.properties文件,用于记录到控制台。
# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1} - %m%n
# Direct all messages there
log4j.rootLogger = INFO, stdout
现在的问题是,当我启动程序时,所有slf4j日志都将被忽略。我尝试使用项目A中的log4j-Logger记录某些内容并将其记录下来。
项目A的依赖树:
[INFO] --- maven-dependency-plugin:2.1:tree (default-cli) @ devopstool ---
[INFO] PROJECT A
[INFO] +- com.google.code.gson:gson:jar:2.3.1:compile
[INFO] +- org.antlr:antlr-runtime:jar:3.4:compile
[INFO] | +- org.antlr:stringtemplate:jar:3.2.1:compile
[INFO] | \- antlr:antlr:jar:2.7.7:compile
[INFO] +- org.tmatesoft.svnkit:svnkit:jar:1.8.9:compile
[INFO] | +- com.jcraft:jsch.agentproxy.svnkit-trilead-ssh2:jar:0.0.7:compile
[INFO] | | \- com.jcraft:jsch.agentproxy.core:jar:0.0.7:compile
[INFO] | +- net.java.dev.jna:jna-platform:jar:4.1.0:compile
[INFO] | +- net.java.dev.jna:jna:jar:4.1.0:compile
[INFO] | +- com.trilead:trilead-ssh2:jar:1.0.0-build217:compile
[INFO] | +- com.jcraft:jsch.agentproxy.connector-factory:jar:0.0.7:compile
[INFO] | | +- com.jcraft:jsch.agentproxy.usocket-jna:jar:0.0.7:compile
[INFO] | | | \- net.java.dev.jna:platform:jar:3.4.0:compile
[INFO] | | +- com.jcraft:jsch.agentproxy.usocket-nc:jar:0.0.7:compile
[INFO] | | +- com.jcraft:jsch.agentproxy.sshagent:jar:0.0.7:compile
[INFO] | | \- com.jcraft:jsch.agentproxy.pageant:jar:0.0.7:compile
[INFO] | +- de.regnis.q.sequence:sequence-library:jar:1.0.3:compile
[INFO] | \- org.tmatesoft.sqljet:sqljet:jar:1.1.10:compile
[INFO] +- org.tmatesoft.svnkit:svnkit-cli:jar:1.8.9:compile
[INFO] +- org.tmatesoft.svnkit:svnkit-javahl16:jar:1.8.9:compile
[INFO] | \- org.apache.subversion:svn-javahl-api:jar:1.8.1:compile
[INFO] +- com.jgoodies:forms:jar:1.2.1:compile
[INFO] +- org.jsoup:jsoup:jar:1.8.2:compile
[INFO] +- PROJECT D
[INFO] | +- com.google.guava:guava:jar:18.0:compile
[INFO] | +- javax.activation:activation:jar:1.1:compile
[INFO] | +- log4j:log4j:jar:1.2.17:compile
[INFO] | +- com.jcraft:jsch:jar:0.1.52:compile
[INFO] | \- org.jetbrains:annotations:jar:13.0:compile
[INFO] +- PROJECT B
[INFO] | +- org.apache.chemistry.opencmis:chemistry-opencmis-client-impl:jar:0.9.0:compile
[INFO] | | +- org.apache.chemistry.opencmis:chemistry-opencmis-client-api:jar:0.9.0:compile
[INFO] | | +- org.apache.chemistry.opencmis:chemistry-opencmis-commons-api:jar:0.9.0:compile
[INFO] | | +- org.apache.chemistry.opencmis:chemistry-opencmis-commons-impl:jar:0.9.0:compile
[INFO] | | | +- org.codehaus.woodstox:woodstox-core-asl:jar:4.2.0:compile
[INFO] | | | | +- javax.xml.stream:stax-api:jar:1.0-2:compile
[INFO] | | | | \- org.codehaus.woodstox:stax2-api:jar:3.1.1:compile
[INFO] | | | \- com.sun.xml.ws:jaxws-rt:jar:2.1.7:compile
[INFO] | | | +- javax.xml.ws:jaxws-api:jar:2.1:compile
[INFO] | | | +- com.sun.xml.stream.buffer:streambuffer:jar:0.9:compile
[INFO] | | | +- com.sun.org.apache.xml.internal:resolver:jar:20050927:compile
[INFO] | | | \- org.jvnet:mimepull:jar:1.3:compile
[INFO] | | +- org.apache.chemistry.opencmis:chemistry-opencmis-client-bindings:jar:0.9.0:compile
[INFO] | | \- org.apache.felix:org.osgi.core:jar:1.0.0:compile
[INFO] | +- org.alfresco.cmis.client:alfresco-opencmis-extension:jar:0.3:compile
[INFO] | +- org.slf4j:slf4j-api:jar:1.7.7:compile
[INFO] | +- commons-configuration:commons-configuration:jar:1.10:compile
[INFO] | | +- commons-lang:commons-lang:jar:2.6:compile
[INFO] | | \- commons-logging:commons-logging:jar:1.1.1:compile
[INFO] | +- PROJECT C
[INFO] | | +- javax.xml.bind:jaxb-api:jar:2.2.7:compile
[INFO] | | +- com.sun.xml.bind:jaxb-impl:jar:2.2.7:compile
[INFO] | | | +- com.sun.xml.bind:jaxb-core:jar:2.2.7:compile
[INFO] | | | | \- com.sun.istack:istack-commons-runtime:jar:2.16:compile
[INFO] | | | \- com.sun.xml.fastinfoset:FastInfoset:jar:1.2.12:compile
[INFO] | | | \- javax.xml.bind:jsr173_api:jar:1.0:compile
[INFO] | | +- com.sun.xml.messaging.saaj:saaj-impl:jar:1.3.23:compile
[INFO] | | | +- javax.xml.soap:javax.xml.soap-api:jar:1.3.5:compile
[INFO] | | | +- org.jvnet.mimepull:mimepull:jar:1.9:compile
[INFO] | | | \- org.jvnet.staxex:stax-ex:jar:1.7.4:compile
[INFO] | | \- commons-codec:commons-codec:jar:1.4:compile
[INFO] | +- commons-cli:commons-cli:jar:1.2:compile
[INFO] | \- org.slf4j:jul-to-slf4j:jar:1.7.7:compile
[INFO] +- com.miglayout:miglayout-swing:jar:5.0:compile
[INFO] | \- com.miglayout:miglayout-core:jar:5.0:compile
[INFO] \- org.slf4j:slf4j-log4j12:jar:1.7.7:compile
答案 0 :(得分:2)
根据您的依赖关系树,您有多个SLF4J绑定。
[INFO] | | | | \- org.slf4j:slf4j-nop:jar:1.5.3:runtime
[INFO] | | | +- org.slf4j:slf4j-jdk14:jar:1.5.6:runtime
[INFO] \- org.slf4j:slf4j-log4j12:jar:1.7.7:compile
如果是这种情况,您会在标准错误输出上找到与此类似的消息(请注意,这可能与标准输出不同,而您实际上并未看到这一点 - 这取决于您执行应用的方式)。
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/frantisek/.m2/repository/org/slf4j/slf4j-nop/1.7.12/slf4j-nop-1.7.12.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/frantisek/.m2/repository/ch/qos/logback/logback-classic/1.1.3/logback-classic-1.1.3.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.helpers.NOPLoggerFactory]
实际上整个maven-assembly-plugin依赖似乎不对,除非你正在开发一个maven插件。
[INFO] | | \- org.apache.maven.plugins:maven-assembly-plugin:jar:2.5.3:compile
要解决此问题,请排除slf4j-nop
和slf4j-jdk14
或删除整个依赖关系。
答案 1 :(得分:1)
让你的整个项目登录到一个日志记录系统是一个非常好的主意,在你的情况下可能是log4j。这简化了一切,并允许您使用一个配置文件等,而不是具有多个配置等。
Slf4j是一个日志记录,你可能知道,所以你可以毫不费力地将它绑定到log4j。一个稍微大一点的问题(但不是无法解决的)将是项目C.让我们从更简单的东西开始:
要将slf4j桥接到log4j,您只需要包含对SLF4J LOG4J 12绑定的依赖:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
这将允许slf4j使用log4j,这意味着将使用您的log4j.xml文件(或类似文件)等。
提示(正如Niklas P在评论中提到的那样编辑):您当然也可以从SLF4j登录到JUL而不是log4j,没有问题,但是将log4j(从项目D)路由到稍微有点棘手JUL(并且需要一个配置文件),所以我不会这样做。但这也是个人偏好的问题(我更喜欢log4j(2))。如果你想这样做,你可以为Slf4j添加jdk14绑定,并尝试将你的log4j东西从项目D路由到JUL,请参阅this answer。
你可能会收到警告说还有其他绑定(在这种情况下,slf4j会随机使用一个)。您必须通过查看“有效pom”(例如Eclipse Maven有一个选项卡)排除其他的,然后从依赖项中排除这些绑定。例如,在我的一个项目中,我有类似的东西......
<dependency>
<groupId>org.zkoss.zk</groupId>
<artifactId>zkspring-core</artifactId>
<exclusions>
<exclusion>
<!-- Exclude logback binding for slf4j -->
<artifactId>logback-classic</artifactId>
<groupId>ch.qos.logback</groupId>
</exclusion>
</exclusions>
<dependency>
您应始终只在类路径上拥有一个绑定。在库的依赖项中包含绑定是一种非常糟糕的做法,因为这是应用程序应该决定的。请参阅http://www.slf4j.org/codes.html
的“多重绑定”部分这将解决您的slf4j / log4j绑定问题。您的下一个问题是项目C,它使用JUL(java.util.logging)。
您可以使用适配器将其桥接到Log4j:
要使用JDK日志记录适配器,必须设置系统属性 java.util.logging.manager to org.apache.logging.log4j.jul.LogManager
这必须通过命令行完成(即使用 -Djava.util.logging.manager = org.apache.logging.log4j.jul.LogManager参数)或在进行任何调用之前使用System.setProperty() 到LogManager或Logger。 见https://logging.apache.org/log4j/2.0/log4j-jul/index.html
并且作为个人注释:由于apache已经宣布end of life为log4j 1.2,我建议考虑切换到log4j2。