【问题标题】:referring to log4j configuration file from a log4j configuration file on class path从类路径上的 log4j 配置文件中引用 log4j 配置文件
【发布时间】:2011-01-03 20:12:02
【问题描述】:

我有一个多个 Web 应用程序正在使用的通用 jar。所有的 Web 应用程序都使用 log4j。每个都有自己的 log4j xml 配置文件,基本相同。我想在包含的 jar 文件和每个单独的 web 项目中放置一个通用 log4j 配置,在该 log4j 配置中,我希望能够简单地引用 jar 文件中的配置。

我在文档中没有看到任何明确说明这是可能的内容。我想知道我是否可以从 Web 项目中删除配置文件并将其粘贴在公共 jar 中,如果它会自动加载,因为它位于类路径上?

最后,我希望能够在不修改 jar 文件中的通用配置的情况下调整特定应用程序的日志记录以进行调试和故障排除。

【问题讨论】:

    标签: java logging jakarta-ee log4j


    【解决方案1】:

    我在一个项目中需要管理数十个 Web 应用程序。每个应用程序的日志记录略有不同,管理起来非常痛苦。我使用了类似于您所描述的策略来标准化 log4j,并且效果很好。

    基本上,我创建了一个包含共享代码的 common.jar。此 jar 包含一个 log4j.xml,它将日志级别设置为 INFO,并将默认 appender 设置为 common.jar 的 stdout。此 log4j 配置用作所有其他应用程序的基线。

    对于这个例子,假设这个类在 common.jar 中:

    public class ThirdPartyLib 
    {
        protected static final Logger log = LogManager.getLogger("third-party-lib");
        public void doSomething()
        {
            log.debug("Third Party App is about to Do something!");
            log.info("Third Party App just did something");
        }
    }
    

    现在,所有其他 Web 应用程序都可以简单地依赖 common.jar。例如,假设这个类在 myapp.war 中:

    public class MyApp
    {
        public void CallThirdParty()
        {
            ThirdPartyLib lib = new ThirdPartyLib();
            lib.doSomething();
        }
    }
    

    由于 log4j.xml 在 common.jar 中,此代码将记录类似这样的内容。换句话说,没有必要将 log4j.xml 放在 myapp.war 中:

    2011-01-03 15:49:22,451 [main] INFO  third-party-lib - Third Party App just did something
    

    现在,如果您想/需要控制 myapp.war 中的日志记录,只需在 myapp.war 中放置一个 log4j.xml 并覆盖 common.jar 中的设置。例如,您可以将级别设置为 DEBUG,然后您会看到:

    2011-01-03 16:03:22,928 [main] DEBUG third-party-lib - Third Party App is about to Do something!
    2011-01-03 16:03:22,928 [main] INFO  third-party-lib - Third Party App just did something
    

    更新 - 是否可以将每个 webapp 配置为记录到单独的文件?

    是的,当然。例如,您可以将日志定向到 RollingFileAppender,而不是 myapp.war 的 log4j.xml 中的 stdout。这很方便,因为您可以将每个单独的 webapp 记录到它自己的单独文件中。

    此外,我编写了一个 servlet 过滤器(类似于 gigadot 建议的),它配置 log4j 以检查外部路径(每个 webapp 的战争之外)是否存在 log4j.xml。这样,log4j.xml 文件可以在战争之外访问,并且我们能够在不重新启动 servlet 容器(在本例中为 tomcat)的情况下设置日志级别。如果外部 log4j.xml 不存在,则默认在每个应用程序类路径上使用 log4j.xml。

    【讨论】:

    • 这与我的想法一致,但是,更复杂的是,每个 Web 应用程序都有一个附加程序,可以根据 Web 应用程序记录到不同的文件。如果我将我的单个项目配置减少到仅此信息,它会覆盖或替换来自 ThirdPartyLib 的配置吗?
    • 嘿,Casey,每个应用程序中 log4j.xml 中的任何配置都将覆盖 common.jar 中 log4j.xml 中的内容。因此,在每个应用程序的 log4j.xml 中添加文件附加程序应该可以正常工作。我用更多信息更新了我的回复。希望这会有所帮助,祝你好运!
    • 谢谢,还有关于将它们存储在战争之外的注释,我觉得有趣,因为我遇到了这个问题,需要在生产中调试某些东西,但不想离开日志级别进行调试等。能够让我们的产品团队中的某个人更新单个文件会很棒。
    【解决方案2】:

    如果您有多个 jar/war 文件,每个文件都有自己的 log4j.xml,并且您不想担心加载哪个 log4j.xml,您可以自己显式加载配置。

    对于 webapp 项目,将以下上下文侦听器作为第一个侦听器放入您的 web.xml 这将从您的首选路径加载 log4j。

    <listener>
        <listener-class>mycompany.server.listener.Log4JInitServletContextListener</listener-class>
    </listener>
    

    Log4JInitServletContextListener 的实现。

    注意:如果您在同一路径中有多个 log4j.xml(可能有多个 jar 文件),那么加载哪个会混淆。因此,请尝试为您的公用 jar 中的配置资源设置一个唯一的包名。

    如您所见,您也可以使用此方法根据条件以编程方式加载 log4j.xml。

    package mycompany.server.listener;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    import org.apache.log4j.xml.DOMConfigurator;
    
    public class Log4JInitServletContextListener implements ServletContextListener {
    
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            org.w3c.dom.Element log4jConfigElement = parseFromInputStream(getClass().getResourceAsStream("/unique/package/name/in/common/jar/log4j.xml"););
            DOMConfigurator.configure(log4jConfigElement);
        }
    
        // omit the rest and implementation of parseFromInputStream method
    }
    

    【讨论】:

    • 不同的方法,有趣。我有点想避免采用程序化方法,但这可能会解决我在工作场所遇到的另一个恼人的问题,其中有不同的环境和日志输出目录 (DEV/PROD)。如果我创建一个侦听器并自己手动加载配置,我可以根据环境变量的值覆盖属性。
    • 目前,我们在 weblogic 服务器中配置了一个属性来表示我们所处的环境,我可以在 log4j 文件中将其引用为 ${env}。
    • 是的,我根据我在系统环境中设置的配置路径加载了我的 log4j。我已经研究了很多方法来解决我的问题,这和你的一样,这是我能做的最好的。起初,我使用 maven 插件来排除所有其他 log4.xml,但在某些情况下有点困难。 Log4j 没有直接处理这个问题的功能。
    【解决方案3】:

    我不确定这是否有帮助,但您可以像这样设置属性文件位置,

    java -Dlog4j.configuration=jar:file:/full/path/to/app.jar!/log4j.properties -jar app.jar 
    

    【讨论】:

    • 是的,这对我没有帮助。不过还是谢谢。
    猜你喜欢
    • 2015-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-27
    • 1970-01-01
    • 1970-01-01
    • 2012-10-20
    • 1970-01-01
    相关资源
    最近更新 更多