log4j - 在具有单独属性文件的多个 Web 应用程序之间共享 Tomcat5 中的单个 log4j jar 文件

标签 log4j tomcat5.5 web-applications

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

我编写了大约 8 个不同的 Web 应用程序,其中 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”引用更改为特定于每个 webapp,以便每个属性文件有效地定义一个单独的配置。这似乎避免了以下错误“log4j:ERROR A "org.apache.log4j.RollingFileAppender"object is not assignable to a "org.apache.log4j.Appender"variable.

即使用如下内容:

对于 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

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

还有其他选择吗?

最佳答案

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

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

Here's an interesting article on using container-level logging.它描述了您遇到的问题:

When you deploy log4j in the container's lib path for a container that is not "log4j-aware" and you don't set up a "Context Repository Selector" for log4j you lose a major feature - logging configuration becomes totally global across all components in the container. Only one logging configuration file is read (from the container's classpath) and every component in the container sees the same logging configuration. This is just not comparable to commons-logging at all. In most cases this is not acceptable behaviour; however commons-logging might provide a feature to behave in this manner if anybody actually thinks this is useful.

When you deploy log4j in the container's lib path and use the "Context Repository Selector" behaviour to get per-component logging configuration AND log4j is also in the component's path you get class cast exceptions (commons-logging currently suffers from the same issue). This is really a separate problem.

When you deploy log4j in the container's lib path and use the "Context Repository Selector" behaviour to get per-component logging configuration and log4j is not in the component's path then you will get memory leaks in exactly the same way as occurs for commons-logging, and for exactly the same reasons.

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

关于log4j - 在具有单独属性文件的多个 Web 应用程序之间共享 Tomcat5 中的单个 log4j jar 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3549226/

相关文章:

java.lang.NoSuchMethodError : ch. qos.logback.core.rolling.helper.FileNamePattern.getDateTokenConverter() 问题

logging - 如何在 WSO2 ESB 中的每个服务日志中选择主机名

java - 如何将 JSF RI (Mojarra) 日志转发到 slf4j 或 log4j?

java - 我的 log4j 过滤器出了什么问题? (这会让tomcat挂掉!)

java - 在 Tomcat 中部署 war

javascript - 3个依赖于Javascript的下拉列表

python - heroku 中的错误没有运行 python Web 应用程序的 Web 进程

web-applications - 谷歌天空 map 是用什么语言编码的?

java - GWT 中的 SLF4J 和 LogBack 配置(Eclipse 和 Jetty)

java - 使用 tomcat 管理器应用程序相对于复制到 webapp 目录的优势