【问题标题】:Logging with embedded Jetty and Tapestry使用嵌入式 Jetty 和 Tapestry 进行日志记录
【发布时间】:2013-09-16 09:34:30
【问题描述】:

我有一个使用 Tapestry 框架的战争网络应用程序。它使用 slf4j + log4j 并且效果很好。

我还有一个带有嵌入式 jetty 8 的简单服务器应用程序,用于部署战争。

我也想在服务器中使用 slf4j + log4j。

因此,我将 slf4j 和 log4j 依赖项添加到我的服务器 pom.xml:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.5</version>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.5</version>
</dependency>

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

我明白了:

SLF4J: Class path contains multiple SLF4J bindings.<br/>
SLF4J: Found binding in [jar:file:/tmp/jetty-0.0.0.0-8080-web-app-0.0.1.war-_-any-/webapp WEB-INF/lib/slf4j-log4j12-1.6.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/martin/monitoring-gui/trunk/release/target/release-0.0.1-webgui-distribution/release-0.0.1/lib/slf4j-log4j12-1.7.5.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]

很公平,Tapestry 依赖自动包含slf4j-log4j12log4j。所以我将以下内容添加到我的 webapp pom.xml tapestry-core 部分:

<exclusions>  
    <exclusion>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
    </exclusion>

    <exclusion>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
    </exclusion>
</exclusions>

现在,实际的绑定和记录器应该只存在于服务器应用程序中。 但是在服务器启动时,我得到:

Exception in thread "main" java.lang.LinkageError: loader constraint violation: when resolving method "org.slf4j.impl.StaticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory;" the class loader (instance of org/eclipse/jetty/webapp/WebAppClassLoader) of the current class, org/slf4j/LoggerFactory, and the class loader (instance of sun/misc/Launcher$AppClassLoader) for resolved class, org/slf4j/impl/StaticLoggerBinder, have different Class objects for the type taticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory; used in the signature
at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:299)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:269)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:281)
at org.apache.tapestry5.TapestryFilter.<init>(TapestryFilter.java:56)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at java.lang.Class.newInstance(Class.java:374)
at org.eclipse.jetty.servlet.ServletContextHandler$Context.createFilter(ServletContextHandler.java:1051)
at org.eclipse.jetty.servlet.FilterHolder.doStart(FilterHolder.java:104)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:763)
at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:265)
at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1242)
at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:717)
at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:494)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:95)
at org.eclipse.jetty.server.Server.doStart(Server.java:282)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
...

一直到我的码头 Server.start() 调用;

我错过了什么?

【问题讨论】:

  • 您是否尝试过在命令行中使用mvn dependency:tree 以确保您没有从其他地方拿起罐子?

标签: log4j jetty slf4j tapestry embedded-jetty


【解决方案1】:

你有一个依赖问题。我没有一直使用排除,而是看到依赖关系树并重新排序 pom.xml 中的标签。这里的规则表明依赖项的第一次出现获胜。因此,当您希望另一个继承的依赖项省略时,只需将依赖项标记移动到您希望省略继承的依赖项的标记之前。

这使得 pom 更具可读性,并且还控制树中依赖项的哪个版本被使用。在极少数情况下,我必须使用标签。

【讨论】:

    【解决方案2】:

    问题是您的类路径中有两个版本的 slf4j-log4j12。从外观上看,您正在设法排除较旧的版本而不是较旧的版本。 Slf4j 抱怨它期待一个比它找到的版本更新的版本。

    在我看来,1.6.1 版本通过您的嵌入式码头服务器进入您的类路径。您是否也通过 maven 设置了您的码头依赖项?如果是这样,也将排除添加到您的码头依赖项中。无论哪种方式,您都需要检查您的类路径并以一种或另一种方式解决冲突的版本

    【讨论】:

      【解决方案3】:

      好的,感谢 joostschouten 和 user2424794 的帮助。我已经成功了。

      mvn dependency:tree 透露,其他 Web 应用程序的依赖项:qpid-client 将另一个 slf4j-api 导入到战争中。
      所以另一个排除是必要的:

      <dependency>
          <groupId>org.apache.qpid</groupId>
          <artifactId>qpid-client</artifactId>
          <version>0.22</version>
          <exclusions>
              <exclusion>
                  <groupId>org.slf4j</groupId>
                  <artifactId>slf4j-api</artifactId>
              </exclusion>
          </exclusions>
      </dependency>
      

      作为记录,tapestry-core 依赖:

      <dependency>
          <groupId>org.apache.tapestry</groupId>
          <artifactId>tapestry-core</artifactId>
          <version>${tapestry-release-version}</version>
          <exclusions>  
              <exclusion>
                  <groupId>org.slf4j</groupId>
                  <artifactId>slf4j-log4j12</artifactId>
              </exclusion>
              <exclusion>
                  <groupId>org.slf4j</groupId>
                  <artifactId>slf4j-api</artifactId>
              </exclusion>
              <exclusion>
                  <groupId>log4j</groupId>
                  <artifactId>log4j</artifactId>
              </exclusion>
          </exclusions>
      </dependency>
      

      剩下的唯一问题是如果没有 slf4j-api,war 将无法编译,因此我将其添加为编译的 war 依赖项,而不是链接 - maven 的 provided 范围:

      <dependency>
           <groupId>org.slf4j</groupId>
           <artifactId>slf4j-api</artifactId>
           <version>1.7.5</version>
           <scope>provided</scope>
      </dependency>
      

      当然,slf4j-apislf4j-log4j12log4j 被添加为服务器的依赖项,服务器将其“提供”给战争应用程序。

      现在一切都可以编译、运行和记录了。

      【讨论】:

      • 您也可以在 maven pom 中使用 &lt;dependencyManagement&gt; 部分。此部分可用于强制依赖的特定版本,无论它如何进入您的依赖树。
      猜你喜欢
      • 1970-01-01
      • 2017-03-17
      • 2018-01-07
      • 2011-12-26
      • 1970-01-01
      • 2011-06-27
      • 1970-01-01
      • 2012-05-22
      • 2012-03-03
      相关资源
      最近更新 更多