从类路径上的log4j配置文件中引用log4j配置文件

时间:2011-01-03 20:12:02

标签: java logging java-ee log4j

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

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

最后,我希望能够调整特定应用程序的日志记录以进行调试和故障排除,而无需修改jar文件中的常见配置。

3 个答案:

答案 0 :(得分: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中的日志记录,那么只需将log4j.xml放在myapp.war中并覆盖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而不是log4j.xml中的stdout for myapp.war。这很方便,因为您可以将每个单独的webapp日志记录到它自己的单独文件中。

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

答案 1 :(得分:1)

如果您有多个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
}

答案 2 :(得分:0)

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

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