当程序 运行 时,在类路径中包含 slf4j 未被拾取

Inclusion of slf4j in classpath not being picked up when program is run

我一直在尝试将 slf4j 包含在项目中,但没有成功。我已将 slf4j-api-1.7.32.jarslf4j-jdk14-1.7.32.jar 添加到 class 路径中,但无论我尝试了什么,我最终都会得到 java.lang.ClassNotFoundException: org.slf4j.LoggerFactory.

错误的开头部分是

Caused by: java.lang.ClassNotFoundException: org.slf4j.LoggerFactory
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
    at com.google.gwt.dev.shell.jetty.JettyLauncher$WebAppContextWithReload$WebAppClassLoaderExtension.findClass(JettyLauncher.java:354)
    at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:366)
    at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:337)
    ...

(如果有帮助,很高兴包含更多内容,但编译器会在此时将其切断)

项目在 Eclipse 中,我试过了

似乎没有任何效果。

然而,奇怪的是,使用完全相同的库集合,它在我编写的 JUnit 测试中运行良好。

今天早上,一位同事发现将一对 slf4j 库添加到 war/WEB-INF/lib 可以正常工作,但这不是一个可行的长期解决方案。

我希望有人有一些好主意!

编辑: 又取得了一些进展。来自 here 需要添加

<Set name="systemClasses">
    <Array type="java.lang.String">
        <!-- we from jetty WebAppContext source code ...-->
        <Item>java.</Item>
        <Item>javax.servlet.</Item>
        <Item>javax.xml.</Item>
        <Item>org.mortbay.</Item>
        <Item>org.xml.</Item>
        <Item>org.w3c.</Item>
        <Item>org.apache.commons.logging.</Item>
        <Item>org.apache.log4j.</Item>
        <!-- and ... added slf4j -->
        <Item>org.slf4j.</Item>
    </Array>
</Set>

jetty-web.xml。现在需要找出部署脚本中需要更改的内容。

解决方案:

添加以下'systemClasses'设置到jetty-web.xml

<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<Configure class="org.mortbay.jetty.webapp.WebAppContext">
    ...
    <Set name="systemClasses">
         <Array type="java.lang.String">

             <!-- we copied these paths from jetty WebAppContext  source code ...-->
             <Item>java.</Item>
             <Item>javax.servlet.</Item>
             <Item>javax.xml.</Item>
             <Item>org.mortbay.</Item>
             <Item>org.xml.</Item>
             <Item>org.w3c.</Item>
             <Item>org.apache.commons.logging.</Item>
             <Item>org.apache.log4j.</Item>

             <!-- and ... added slf4j -->
             <Item>org.slf4j.</Item>

             <!-- we must promote slf4j to system classes, otherwise gwt
                  hosted mode will not allow loading them due to a policy
                  that don't allow server classes to be loaded from the
                  outside world (see gwt JettyLauncher source code). -->

         </Array>
    </Set>
</Configure>

2009 年在此留言板上找到:https://www.mail-archive.com/google-web-toolkit@googlegroups.com/msg14754.html

我们如何找到解决方案:

虽然单步执行 JettyLauncher.WebAppContextWithReload.WebAppClassLoaderExtension.findClass(String name) 显示在第一次加载时,大多数 super.findClass(name) 抛出了一个 ClassNotFoundException,然后当他们通过 isServerPath 时,他们开始使用 systemClassLoader 从 .jar 文件加载它们。现在 systemClassLoader 的父类型 URLClassLoader 有一个字段 ucp (URLClassPath),它有一个包含所有 .jar 文件的列表(在 path 下)它可以从 类 加载。看看这里,slf4j 罐子确实存在,但由于某种原因 isServerPath 返回 true。这是最终找到上述解决方案的原因。