如何在单个EAR中为不同的WAR配置多个log4j?

9

我有一个EAR,结构如下:

APP.ear 
- APP1.war
    - WEB-INF/classes/log4j.properties
- APP2.war
    - WEB-INF/classes/log4j.properties
- app1-ejb.jar
- app2-ejb.jar
- log4j.jar
- spring.jar
- commons-lang.jar (...and other jar)

我希望每个WAR都有自己的应用程序日志。但是似乎上述配置不起作用。APP1和APP2的日志都会记录到APP1的日志中。是否有任何方法创建单独的应用程序日志?
4个回答

8
由于类加载器的原因,这是不可能的。类加载器层次结构如下:
应用程序类加载器 -> Ejb 类加载器 -> war 类加载器
要为每个 war 单独设置日志,可以将 log4j.jar 放在 war 中,并让 log4j 使用 war 类加载器。但由于 app1-ejb.jar 和 app2-ebj.jar 都需要使用 log4j,log4j.jar 只能放在顶层。因此,log4j 处于应用程序类加载器级别。
我可以指定单个 log4j 配置来将不同的包记录到不同的文件中。但对于像 Spring 这样的常用库,日志无法分离。

但是由于app1-ejb.jar和app2-ebj.jar都需要使用log4j,因此log4j.jar只能放置在顶层。你不能在每个WAR文件中都包含一个log4j.jar吗? - CodeClimber

1

它没有起作用的原因是log4j存在于根位置,而应该让每个war在其WEB-INF/lib目录中拥有一个Log4j.jar,并从根目录中删除log4j.jar。

有关此更多信息,请参阅我的博客文章http://techcrawler.wordpress.com/


0

Logback是解决这个问题的可行方案。在寻找不同的hack方法来使log4j工作后,我们决定转向Logback。我已经在webapp中使用了Logback jar的以下配置。

一个包含外部文件的webapp内的Logback文件:

    <?xml version="1.0" encoding="UTF-8" ?>
    <configuration scan="true" scanPeriod="10 seconds">
        <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
            <resetJUL>true</resetJUL>
        </contextListener>

        <contextName>${project.artifactId}</contextName>

        <jmxConfigurator />

        <include file="${logback.configuration.filepath}" />
    </configuration>

${logback.configuration.filepath} 会在 Maven 过滤期间被实际路径替换,该路径是配置文件的 Web 应用程序外部的路径(类似于 /opt/server/conf/loback.included.conf)。

然后,logback.included.conf 的内容(此文件是项目的一部分,使用 build-helper:attach-artifact 交付,因此 ${project.artifactId} 也会在 Maven 过滤期间被替换):

    <?xml version="1.0" encoding="UTF-8" ?>
    <included>
        <appender name="file" class="ch.qos.logback.core.FileAppender">
            <file>/var/log/server/${project.artifactId}.log</file>
            <encoder>
                <pattern>[@/%contextName] %date{ISO8601} [%-5level] %thread:[%logger] %msg%n</pattern>
            </encoder>
        </appender>

        <root level="INFO">
            <appender-ref ref="file" />
        </root>
    </included>

唯一的限制是,包含文件的内容必须符合包含者的内容。实际上只是编写规则。


0

你也可以通过在代码中使用 PropertyConfigurator 动态更改属性文件中的 FILE 属性来实现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接