java 控制 servlet 中的类路径
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/264828/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Controlling the classpath in a servlet
提问by Ian Dickinson
My servlet application includes a number of library .jars, some of which contain embedded log4j.xml or log4j.properties files. I'd like to ensure that log4j finds my log4j.xml first! I've tried searching for some specification of the priorities of the various classpath elements in a servlet (e.g. does WEB-INF/classes always precede WEB-INF/lib?), or some way to configure or tweak the servlet's classloader so that a given resource directory appears early in the classpath. So far, I've drawn a blank. Any suggestions on ensuring that a servlet .war file loads the correct log4j.xml via the classloader?
我的 servlet 应用程序包括许多库 .jar,其中一些包含嵌入式 log4j.xml 或 log4j.properties 文件。我想确保 log4j 首先找到我的 log4j.xml!我已经尝试在 servlet 中搜索各种类路径元素的优先级规范(例如,WEB-INF/classes 是否总是在 WEB-INF/lib 之前?),或者某种方式来配置或调整 servlet 的类加载器,以便给定的资源目录出现在类路径的早期。到目前为止,我已经画了一个空白。关于确保 servlet .war 文件通过类加载器加载正确的 log4j.xml 的任何建议?
采纳答案by johnstok
As far as I understand the resource selection from the classpath is non-deterministic (from the point of view of the app developer). Even if the same file is loaded consistently the behaviour could change: 1. When you upgrade the version of your current container. 2. If you switch containers.
据我了解,从类路径中选择的资源是不确定的(从应用程序开发人员的角度来看)。即使始终加载相同的文件,行为也可能会发生变化: 1. 当您升级当前容器的版本时。2.如果你切换容器。
The simplest solution will be to remove embedded log4j config files from library jars. It is almost never a good idea to embed log4j config's as it leads to the problem you are seeing here...
最简单的解决方案是从库 jars 中删除嵌入的 log4j 配置文件。嵌入 log4j 配置几乎从来都不是一个好主意,因为它会导致您在这里看到的问题......
Are they third party jars or jars you developed?
他们是第三方罐子还是你开发的罐子?
回答by Yonatan Maman
Tomcat 8.5
雄猫 8.5
Ditto Tomcat 8.0.
同上 Tomcat 8.0。
See documentation: Class Loader HOW-TO.
请参阅文档:类加载器 HOW-TO。
Tomcat 8.0
雄猫8.0
The answer is simple, taken from the Tomcat documentation page, Class Loader HOW-TO. In particular notice the use of the /WEB-INF/directory/folder.
答案很简单,取自 Tomcat 文档页面Class Loader HOW-TO。特别注意/WEB-INF/目录/文件夹的使用。
Therefore, from the perspective of a web application, class or resource loading looks in the following repositories, in this order:
- Bootstrap classes of your JVM
/WEB-INF/classesof your web application/WEB-INF/lib/*.jarof your web application- System class loader classes (described above)
- Common class loader classes (described above)
If the web application class loader is configuredwith
<Loader delegate="true"/>then the order becomes:
- Bootstrap classes of your JVM
- System class loader classes (described above)
- Common class loader classes (described above)
/WEB-INF/classesof your web application/WEB-INF/lib/*.jarof your web application
因此,从 Web 应用程序的角度来看,类或资源加载按以下顺序查看以下存储库:
- JVM 的引导类
/WEB-INF/classes您的网络应用程序/WEB-INF/lib/*.jar您的网络应用程序- 系统类加载器类(如上所述)
- 常见的类加载器类(如上所述)
如果配置了 Web 应用程序类加载器,
<Loader delegate="true"/>则顺序变为:
- JVM 的引导类
- 系统类加载器类(如上所述)
- 常见的类加载器类(如上所述)
/WEB-INF/classes您的网络应用程序/WEB-INF/lib/*.jar您的网络应用程序
Tomcat 6
雄猫6
Excerpted from Tomcat 6 page, Class Loader HOW-TO.
摘自 Tomcat 6 页面,类加载器 HOW-TO。
Therefore, from the perspective of a web application, class or resource loading looks in the following repositories, in this order:
- Bootstrap classes of your JVM
- System class loader classes (described above)
/WEB-INF/classesof your web application/WEB-INF/lib/*.jarof your web application$CATALINA_HOME/lib$CATALINA_HOME/lib/*.jar
因此,从 Web 应用程序的角度来看,类或资源加载按以下顺序查看以下存储库:
- JVM 的引导类
- 系统类加载器类(如上所述)
/WEB-INF/classes您的网络应用程序/WEB-INF/lib/*.jar您的网络应用程序$CATALINA_HOME/lib$CATALINA_HOME/lib/*.jar
回答by johnstok
We the Spring Log4jConfigListenerin our web.xml file.
我们Log4jConfigListener在 web.xml 文件中使用 Spring 。
You can specify as a context parameter the location of the log4j config file, i.e. you could set it as /WEB-INF/log4j.xml
您可以将 log4j 配置文件的位置指定为上下文参数,即您可以将其设置为 /WEB-INF/log4j.xml
Would this be an option for you? If you're not using Spring I know that you can set the Log4j location programatically which might also work.
这会是你的一个选择吗?如果您不使用 Spring,我知道您可以以编程方式设置 Log4j 位置,这也可能有效。
回答by Hyman Leow
In my experience, WEB-INF/classes typically takes precedence over jars in WEB-INF/lib, however, that also depends on the servlet container you use (I could never figure out the behavior of JRun, for instance). It would help immensely if you could tell me which container you're using.
根据我的经验,WEB-INF/classes 通常优先于 WEB-INF/lib 中的 jar,但是,这也取决于您使用的 servlet 容器(例如,我永远无法弄清楚 JRun 的行为)。如果您能告诉我您使用的是哪个容器,那将非常有帮助。
Also, are you certain that the offending log4j configuration is in a jar in WEB-INF/lib? Typically, when I've run into classpath problems in a servlet container situation, it's because of libraries that reside outsideof the web app.
另外,您确定有问题的 log4j 配置在 WEB-INF/lib 的 jar 中吗?通常,当我碰到一个servlet容器的classpath情况的问题,这是因为图书馆的驻留之外的Web应用程序的。
The servlet specs recommendthat web app classloaders load their own classes before delegating to the container's classloader (SRV.9.7.2), but since this is counter to the Java spec, not all vendors do this by default (in fact Tomcat is the only container I've used that does this by default). With that said, it's always possible to configure your container's web app classloading behavior. If you tell me which container you're using, I may be able to help you (specifically, I have done this successfully before on WebLogic, WebSphere, Glassfish and JRun)).
servlet 规范建议Web 应用程序类加载器在委托给容器的类加载器 (SRV.9.7.2) 之前加载他们自己的类,但由于这与 Java 规范背道而驰,并非所有供应商默认都这样做(实际上 Tomcat 是唯一的)我使用的默认情况下执行此操作的容器)。话虽如此,始终可以配置容器的 Web 应用程序类加载行为。如果您告诉我您使用的是哪个容器,我或许可以为您提供帮助(具体来说,我之前在 WebLogic、WebSphere、Glassfish 和 JRun 上已成功完成此操作))。
回答by matt b
If you're unable to control the classpath, since Tomcat is setting it for you, are you at least able to set a system property for log4j.configuration? I believe that location pointed to by that property can be set outside of the classpath.
如果您无法控制类路径,因为 Tomcat 正在为您设置它,那么您至少可以为 设置系统属性log4j.configuration吗?我相信该属性指向的位置可以设置在类路径之外。
If not, another approach, although an ugly one, would be to explicitly run one of the configurators yourself in your application code.
如果没有,另一种方法(虽然很丑陋)是自己在应用程序代码中显式运行其中一个配置器。
回答by Marko
You need to have log4j.properties in your CLASSPATH. The best place is under WEB-INF/classes.
您的 CLASSPATH 中需要有 log4j.properties。最好的地方是在 WEB-INF/classes 下。
You also have to make sure that you use your version of log4j.jar. So, put it in WEB-INF/lib, just to make sure you are not using one from tomcat folders, since it may cause strange classloading issues.
您还必须确保使用您的 log4j.jar 版本。所以,把它放在 WEB-INF/lib 中,只是为了确保你没有使用 tomcat 文件夹中的一个,因为它可能会导致奇怪的类加载问题。

