我的 servlet 应用程序包含许多库 .jar,其中一些包含嵌入式 log4j.xml 或 log4j.properties 文件。我想确保 log4j 首先找到我的 log4j.xml!我尝试在 servlet 中搜索各种类路径元素的优先级规范(例如,WEB-INF/classes 是否总是在 WEB-INF/lib 之前?),或者某种方式来配置或调整 servlet 的类加载器,以便给定的资源目录出现在类路径的早期。到目前为止,我已经画了一个空白。关于确保 servlet .war 文件通过类加载器加载正确的 log4j.xml 有什么建议吗?
6 回答
雄猫 8.5
同上 Tomcat 8.0。
请参阅文档:类加载器 HOW-TO。
雄猫 8.0
答案很简单,取自 Tomcat 文档页面Class Loader HOW-TO。特别注意/WEB-INF/
目录/文件夹的使用。
因此,从 Web 应用程序的角度来看,类或资源加载按以下顺序查看以下存储库:
- JVM 的引导类
/WEB-INF/classes
您的网络应用程序/WEB-INF/lib/*.jar
您的网络应用程序- 系统类加载器类(如上所述)
- 通用类加载器类(如上所述)
如果配置了 Web 应用程序类加载器,则
<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
据我了解,类路径中的资源选择是不确定的(从应用程序开发人员的角度来看)。即使相同的文件被一致地加载,行为也可能发生变化: 1. 当您升级当前容器的版本时。2.如果你切换容器。
最简单的解决方案是从库 jars 中删除嵌入式 log4j 配置文件。嵌入 log4j 配置几乎从来都不是一个好主意,因为它会导致您在此处看到的问题...
它们是您开发的第三方罐子还是罐子?
我们的 web.xml 文件中的 Spring Log4jConfigListener
。
您可以将 log4j 配置文件的位置指定为上下文参数,即您可以将其设置为 /WEB-INF/log4j.xml
这对你来说是一个选择吗?如果您不使用 Spring,我知道您可以通过编程方式设置 Log4j 位置,这也可能有效。
根据我的经验,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 正在为您设置它,您是否至少能够为 设置系统属性log4j.configuration
?我相信该属性指向的位置可以设置在类路径之外。
如果不是,另一种方法(虽然丑陋)是在您的应用程序代码中自己显式运行其中一个配置器。
您需要在 CLASSPATH 中有 log4j.properties。最好的地方是在 WEB-INF/classes 下。
您还必须确保使用您的 log4j.jar 版本。所以,把它放在 WEB-INF/lib 中,只是为了确保你没有使用来自 tomcat 文件夹的一个,因为它可能会导致奇怪的类加载问题。