3

是否可以在 tomcat 5.5 设置中使用单个 log4j jar 文件,多个 webapp 可以使用它并为每个 webapp 单独记录?

我编写了大约 8 个不同的 webapp,其中 log4j 属性文件之间唯一真正的区别是日志文件名。但是,如果我尝试将 log4j 从 webapp WEB-INF/lib 目录移动到 tomcat5 shared/lib 目录,我会遇到问题。

所有的属性文件基本上和下面的一样,我只是在代码中使用 System.setProperty("file.name", ) 设置了 file.name 。真的没有必要,但我在玩弄为所有组件使用单个属性文件的想法。

log4j.rootLogger=DEBUG, LogFile
# stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

# LogFile
log4j.appender.LogFile=org.apache.log4j.RollingFileAppender
log4j.appender.LogFile.File=${file.name}
log4j.appender.LogFile.layout=org.apache.log4j.PatternLayout
log4j.appender.LogFile.MaxFileSize=500KB
log4j.appender.LogFile.MaxBackupIndex=5
log4j.appender.LogFile.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

基本上对于每个组件,我想记录到一个单独的文件,但是问题是如果我在 shared/lib 目录下包含 log4j,无论哪个 webapp 先被访问,都会有效地定义将被所有人使用的日志文件的网络应用程序。即我不能使用单独的配置。

我知道的替代方案:将 log4j 放入每个 war 文件的 WEB-INF/lib 目录中,这样我将获得每个 webapp 的单独配置。

将上面的“LogFile”引用更改为特定于每个 web 应用程序,以便每个属性文件有效地定义单独的配置。这似乎避免了以下错误“ log4j:错误“org.apache.log4j.RollingFileAppender”对象不可分配给“org.apache.log4j.Appender”变量。

即使用如下内容:

对于 WebApp1

log4j.rootLogger=DEBUG, LogFileWebapp1
# stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

# LogFile
log4j.appender.LogFileWebapp1=org.apache.log4j.RollingFileAppender
log4j.appender.LogFileWebapp1.File=${file.name}
log4j.appender.LogFileWebapp1.layout=org.apache.log4j.PatternLayout
log4j.appender.LogFileWebapp1.MaxFileSize=500KB
log4j.appender.LogFileWebapp1.MaxBackupIndex=5
log4j.appender.LogFileWebapp1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

对于 WebApp2

log4j.rootLogger=DEBUG, LogFileWebapp2
# stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

# LogFile
log4j.appender.LogFileWebapp2=org.apache.log4j.RollingFileAppender
log4j.appender.LogFileWebapp2.File=${file.name}
log4j.appender.LogFileWebapp2.layout=org.apache.log4j.PatternLayout
log4j.appender.LogFileWebapp2.MaxFileSize=500KB
log4j.appender.LogFileWebapp2.MaxBackupIndex=5
log4j.appender.LogFileWebapp2.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

我宁愿坚持第一个属性文件的布局,并在 webapps 之间保持尽可能相似,并且也希望不必在每个 webapps 中包含单独的 log4j 副本。理想情况下,我希望只使用从 tomcat 共享 lib 目录到 log4j 系统副本的符号链接。

还有其他选择吗?

4

1 回答 1

6

我不会这样做的。让每个 webapp 都有自己的 log4j.jar 和自己的 log4j.properties 文件。即使你在所有其他方面都能做到这一点,你也永远无法只在一个 webapp 上升级 log4j,而且你很难在不影响其他应用程序的情况下修改一个应用程序的日志记录。

除了维护的痛苦和痛苦之外,如果 log4j 持有类引用,则有可能导致巨大的内存泄漏。每次重新部署 Tomcat 都会创建一个包含所有类的新版本的新应用程序类加载器,由于 log4j 不知道放开它们,因此无法摆脱旧引用,回收内存的唯一方法是重新启动Tomcat 实例。

这是一篇关于使用容器级日志记录的有趣文章。它描述了您遇到的问题:

当您在容器的 lib 路径中为非“log4j-aware”的容器部署 log4j 并且您没有为 log4j 设置“上下文存储库选择器”时,您将失去一个主要功能 - 日志配置在所有组件中变得完全全局容器。只读取一个日志配置文件(从容器的类路径),并且容器中的每个组件都看到相同的日志配置。这根本无法与公共日志记录相提并论。在大多数情况下,这是不可接受的行为;但是,如果有人真的认为这很有用,那么 commons-logging 可能会提供一种以这种方式运行的功能。

当您在容器的 lib 路径中部署 log4j 并使用“上下文存储库选择器”行为来获取每个组件的日志记录配置并且 log4j 也在组件的路径中时,您会获得类转换异常(commons-logging 当前遇到同样的问题)。这确实是一个单独的问题。

当您在容器的 lib 路径中部署 log4j 并使用“上下文存储库选择器”行为来获取每个组件的日志记录配置并且 log4j 不在组件的路径中时,您将获得与 commons-logging 完全相同的方式发生内存泄漏,并且出于完全相同的原因。

最简单的解决方案是通过将 log4j 保存在每个应用程序的 WEB-INF/lib 中来避免该问题。

于 2010-08-23T15:58:05.180 回答