【问题标题】:gwt + jetty + spring + log4j ERROR: "DOMConfigurator object is not assignable to a Configurator"gwt + jetty + spring + log4j 错误:“DOMConfigurator 对象不可分配给配置器”
【发布时间】:2014-06-08 09:04:07
【问题描述】:

网络上的多个来源都提到了这个问题,但我无法通过那里提供的解决方案来解决它。

问题: 发出 mvn gwt:run 时从 log4j 抛出以下错误:

[ERROR] log4j:ERROR A "org.apache.log4j.xml.DOMConfigurator" object is not assignable to a "org.apache.log4j.spi.Configurator" variable.
[ERROR] log4j:ERROR The class "org.apache.log4j.spi.Configurator" was loaded by
[ERROR] log4j:ERROR [sun.misc.Launcher$AppClassLoader@23137792] whereas object of type
[ERROR] log4j:ERROR "org.apache.log4j.xml.DOMConfigurator" was loaded by [WebAppClassLoader=Demo@3d1665ac].
[ERROR] log4j:ERROR Could not instantiate configurator [org.apache.log4j.xml.DOMConfigurator].

我的项目描述: 我使用 gwt 提供的默认码头服务器并在爆炸战争中运行它。

<gwt.version>2.6.1</gwt.version>
<spring.version>3.2.6.RELEASE</spring.version>
<log4j.version>1.2.17</log4j.version>
<slf4j.version>1.7.5</slf4j.version>

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>${log4j.version}</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <scope>runtime</scope>
</dependency>
<!-- Normally this jar would be listed in dependencies but in my case causes log4j ERROR. -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
    <version>${slf4j.version}</version>
    <scope>runtime</scope>
</dependency>

此外,我从 spring 和其他依赖它的项目中排除了 commons-logging。

(不满意)解决方案: 只有当 log4j、slf4j-api、slf4j-log4j12 和 jcl-over-slf4j jar 放在我的 WEB-INF/lib 目录中时,日志才能正常工作,但仅当 jcl-over-slf4 不在项目的类路径中时(即我注释掉最后提到的依赖项)。

当 jcl-overl-slf4j 包含在 maven 依赖项中时(见上文),它不仅被添加到目标的 lib 目录中,而且还包含在项目的类路径中。它会导致错误。这个 jar 必须放在 lib 中,但只有当它不包含在类路径中时错误才会消失。 maven-dependency-plugin 用于通过将其复制到 lib 目录并跳过 maven 依赖来解决此问题。

这个解决方案显然只是一种解决方法,因为在 gwt 和 spring 项目的许多标准示例中都提到了所有四个 jar - log4j、slf4j-api、slf4j-log4j12、jcl-over-slf4j。

您能否解释一下为什么会这样?如何通过在 maven 依赖项中正常包含 jcl-over-slf4j 来解决这个问题?

【问题讨论】:

    标签: spring gwt logging log4j jetty


    【解决方案1】:

    Jetty 将org.apache.commons.logging 视为系统类,即它从系统类加载器(即类路径)加载它的优先级高于 web 应用程序的WEB-INF/lib。在您的情况下,org.apache.commons.loggingjcl-over-slf4j 提供。因此,您的 web 应用程序中的代码调用 Commons Logging,然后从系统类加载器加载它,它可能使用类的类加载器(与当前线程类加载器相反)初始化 SLF4J,因此使用来自 slf4j-log4j12 和 @ 的代码来自系统类加载器的 987654327@。稍后,webapp 中的代码调用 Log4j(可能通过 SLF4J)来初始化日志配置,然后它使用来自 webapp 的 WEB-INF/lib 的 JAR(如预期的那样)。将所有内容放在一起时,问题就来了,从不同的类加载器加载类。

    现在解决这个问题:这并不简单。

    简单地说,DevMode 中的类加载是一团糟(请参阅 https://docs.google.com/document/d/1bWfafaPA0m0Z1Swodnx7m3QTv31OdqFkE7aeadN_2BU/edit?usp=sharing 我试图记录它的地方)。

    要解决您的问题,您必须在 DevMode 中使用您自己的 ServletContainerLauncher 和您自己的类加载规则,或者更简单地在另一个 servlet 容器中运行您的 web 应用程序(例如 mvn jetty:runmvn tomcat7:run,或其他)。然后你会在-noserver 模式下运行 DevMode。

    这是一个稍微复杂一点的设置,但它的一大优势是正好是您在 SuperDevMode 中所需要的;和 SuperDevMode 今年将取代 DevMode(DevMode 在 Firefox 中已经死了,在 Linux 上的 Chrome 中——基本上,它在 Linux 上已经死了——今年晚些时候将从其他平台上的 Chrome 中删除支持,只剩下一个工作平台:互联网Windows 上的资源管理器)。

    【讨论】:

    • 感谢您的解释。我将暂时使用我的解决方法,并最终切换到 SuperDevMode。 (没有足够的声望来投票。)
    猜你喜欢
    • 2014-02-01
    • 2014-07-07
    • 1970-01-01
    • 2013-11-13
    • 1970-01-01
    • 2019-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多