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