【问题标题】:Controlling the classpath in a servlet控制 servlet 中的类路径
【发布时间】:2010-09-20 20:37:11
【问题描述】:

我的 servlet 应用程序包含许多库 .jar,其中一些包含嵌入式 log4j.xml 或 log4j.properties 文件。我想确保 log4j 首先找到我的 log4j.xml!我尝试在 servlet 中搜索各种类路径元素的优先级规范(例如,WEB-INF/classes 是否总是在 WEB-INF/lib 之前?),或者以某种方式配置或调整 servlet 的类加载器,以便给定的资源目录出现在类路径的早期。到目前为止,我已经画了一个空白。有关确保 servlet .war 文件通过类加载器加载正确的 log4j.xml 的任何建议?

【问题讨论】:

    标签: java tomcat servlets classpath


    【解决方案1】:

    您的 CLASSPATH 中需要有 log4j.properties。最好的地方是在WEB-INF/classes下。

    您还必须确保使用您的 log4j.jar 版本。所以,把它放在 WEB-INF/lib 中,只是为了确保你没有使用 tomcat 文件夹中的一个,因为它可能会导致奇怪的类加载问题。

    【讨论】:

    • 这并不能真正回答我提出的问题。 WEB-INF/classes 是否保证在 WEB-INF/lib 之前的类路径上?如果我希望我的 log4j.xml 不在 WEB-INF/classes 中而是在另一个目录中怎么办 - 毕竟它不是一个类。
    • 但它必须在类路径中
    【解决方案2】:

    据我了解,类路径中的资源选择是不确定的(从应用程序开发人员的角度来看)。即使一致地加载相同的文件,行为也可能会改变: 1.当您升级当前容器的版本时。 2.如果你切换容器。

    最简单的解决方案是从库 jar 中删除嵌入式 log4j 配置文件。嵌入 log4j 配置几乎从来都不是一个好主意,因为它会导致您在此处看到的问题...

    它们是第三方 jar 还是您开发的 jar?

    【讨论】:

    • 第三方,因此问题。
    • 冒着听起来无情的风险,也许你应该在问题中点名羞辱他们,并提交一个错误......
    • 我建议从 3rd 方 jar 中手动删除 log4j 配置文件。如果您使用 maven、ivy 等来管理依赖关系,这将是一件痛苦的事情。
    • 嗨 johnstok,通常我确实使用 maven,但我正在与一个实习生一起做这个项目,它还没有被 mavenized。因此,手动编辑 .jar 将让我看看这是否是根本原因。好建议,谢谢。
    • 是否可以从该 JAR 中删除 log4j 配置?也让我猜猜,它与轴有关吗?
    【解决方案3】:

    我们是 web.xml 文件中的 Spring Log4jConfigListener

    您可以将 log4j 配置文件的位置指定为上下文参数,即您可以将其设置为 /WEB-INF/log4j.xml

    这对您来说是一个选择吗?如果您不使用 Spring,我知道您可以通过编程方式设置 Log4j 位置,这也可能有效。

    【讨论】:

    • Spring 不是这个项目的一个选项,但它是一个对未来有用的提示,非常感谢!
    【解决方案4】:

    根据我的经验,WEB-INF/classes 通常优先于 WEB-INF/lib 中的 jar,但是,这也取决于您使用的 servlet 容器(例如,我永远无法弄清楚 JRun 的行为)。如果您能告诉我您使用的是哪个容器,那将非常有帮助。

    另外,您确定有问题的 log4j 配置位于 WEB-INF/lib 的 jar 中吗?通常,当我在 servlet 容器情况下遇到类路径问题时,这是因为库位于 Web 应用程序外部

    servlet 规范建议 Web 应用程序类加载器在委托给容器的类加载器 (SRV.9.7.2) 之前加载自己的类,但由于这与 Java 规范背道而驰,并非所有供应商都这样做默认情况下(实际上 Tomcat 是我使用的唯一默认情况下执行此操作的容器)。话虽如此,始终可以配置容器的 Web 应用程序类加载行为。如果您告诉我您使用的是哪个容器,我或许可以为您提供帮助(具体来说,我之前在 WebLogic、WebSphere、Glassfish 和 JRun 上已经成功地做到了这一点)。

    【讨论】:

    • 嗨,杰克,我目前正在使用 Tomcat 6 (tomcat6-6.0.18-1.1.fc9.noarch) 和 Jetty 6.1.11。不,我不完全确定冲突来自我的 .jar 中的 log4j 配置......我们有一些奇怪的日志记录行为,冲突配置似乎是一个很好的假设。
    • 我没有用过Jetty,但是在Tomcat中,你可能可以排除类加载器配置的问题。 log4j.jar 在您的 WEB-INF/lib 目录中吗?
    【解决方案5】:

    如果您无法控制类路径,因为 Tomcat 正在为您设置它,您至少可以为log4j.configuration 设置系统属性吗?我相信该属性指向的位置可以设置在类路径之外。

    如果不是,另一种方法,虽然是一种丑陋的方法,是在您的应用程序代码中自己显式运行其中一个配置器。

    【讨论】:

      【解决方案6】:

      Tomcat 8.5

      同上 Tomcat 8.0。

      请参阅文档:Class Loader HOW-TO

      Tomcat 8.0

      答案很简单,取自 Tomcat 文档页面Class Loader HOW-TO。特别注意/WEB-INF/ 目录/文件夹的使用。

      因此,从 Web 应用程序的角度来看,类或资源加载按以下顺序查看以下存储库:

      • JVM 的引导类
      • /WEB-INF/classes 您的网络应用程序
      • /WEB-INF/lib/*.jar 您的网络应用程序
      • 系统类加载器类(如上所述)
      • 通用类加载器类(如上所述)

      如果 Web 应用程序类加载器是 configured<Loader delegate="true"/>,则顺序变为:

      • JVM 的引导类
      • 系统类加载器类(如上所述)
      • 通用类加载器类(如上所述)
      • /WEB-INF/classes 您的网络应用程序
      • /WEB-INF/lib/*.jar 您的网络应用程序

      雄猫 6

      摘自 Tomcat 6 页面,Class Loader HOW-TO

      因此,从 Web 应用程序的角度来看,类或资源加载按以下顺序查看以下存储库:

      • JVM 的引导类
      • 系统类加载器类(如上所述)
      • /WEB-INF/classes 您的网络应用程序
      • /WEB-INF/lib/*.jar 您的网络应用程序
      • $CATALINA_HOME/lib
      • $CATALINA_HOME/lib/*.jar

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-23
        • 1970-01-01
        • 2013-02-11
        • 2018-11-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多