pio*_*b86 4 gwt logging spring log4j jetty
网络上的几个来源都提到了这个问题,但我无法使用那里提供的解决方案来解决它。
问题:发出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].
Run Code Online (Sandbox Code Playgroud)
我的项目描述:我使用 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>
Run Code Online (Sandbox Code Playgroud)
更重要的是,我从 spring 和其他依赖它的项目中排除了 commons-logging。
(不满意)解决方案:仅当 log4j、slf4j-api、slf4j-log4j12 和 jcl-over-slf4j jars 放在我的 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 来解决这个问题?
Jetty 将其org.apache.commons.logging
视为系统类,即它从系统类加载器(即类路径)中加载它的优先级高于 webapp 的WEB-INF/lib
. 在您的情况下,org.apache.commons.logging
由jcl-over-slf4j
. 因此,您的 webapp 中的代码调用 Commons Logging,然后从系统类加载器加载它,它可能使用类的类加载器(与当前线程类加载器相反)初始化 SLF4J,从而使用来自slf4j-log4j12
和log4j
来自系统类的代码装载机。稍后,webapp 中的代码调用 Log4j(可能通过 SLF4J)来初始化日志配置,然后它使用来自 webapp 的 JAR WEB-INF/lib
(如预期的那样)。当涉及到把所有东西放在一起时,问题就来了,从不同的类加载器加载类。
现在来解决这个问题:这并不简单。
简而言之,DevMode 中的类加载是一团糟(参见https://docs.google.com/document/d/1bWfafaPA0m0Z1Swodnx7m3QTv31OdqFkE7aeadN_2BU/edit?usp=sharing,我试图记录它)。
要解决您的问题,您必须ServletContainerLauncher
在 DevMode 中使用您自己的类加载规则,或者更简单地在另一个 servlet 容器(例如mvn jetty:run
或mvn tomcat7:run
或其他)中运行您的 web 应用程序。然后你会在-noserver
模式下运行 DevMode 。
这是一个稍微复杂一些的设置,但它的一大优势是正是您需要的 SuperDevMode;SuperDevMode 将在今年取代 DevMode(DevMode 在 Firefox 中已经死了,在 Linux 上的 Chrome 中——基本上,它在 Linux 上已经死了——,今年晚些时候将在其他平台上从 Chrome 中删除支持,只留下一个工作平台:互联网Windows 上的资源管理器)。
归档时间: |
|
查看次数: |
7486 次 |
最近记录: |