【问题标题】:Initializing Log4J with Spring?用 Spring 初始化 Log4J?
【发布时间】:2011-05-22 23:36:21
【问题描述】:

我有一个 Web 应用程序,它使用 Spring 的 Log4jConfigurer 类来初始化我的 Log4J 日志工厂。基本上,它使用不在类路径中的配置文件初始化 Log4J。

这里是配置:

<bean id="log4jInitializer" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" depends-on="sbeHome">
    <property name="targetClass" value="org.springframework.util.Log4jConfigurer" />
    <property name="targetMethod" value="initLogging" />
    <property name="arguments">
        <list>
            <value>#{ MyAppHome + '/conf/log4j.xml'}</value>
        </list>
    </property>
</bean>

但是我在应用程序启动时收到此错误:

log4j:WARN No appenders could be found for logger

大量 Spring 应用程序上下文初始化消息被打印到控制台。我认为这是因为 Spring 在有机会初始化我的记录器之前正在初始化我的应用程序。万一这很重要,我在 Log4J 之上使用 SLF4J。

有什么方法可以让我的 Log4jConfigurer 成为第一个初始化的 bean?还是有其他方法可以解决这个问题?

【问题讨论】:

    标签: java spring web-applications log4j


    【解决方案1】:

    您可以在 web.xml 而不是 spring-context.xml 中配置 Log4j 侦听器

    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>/WEB-INF/classes/log4j.web.properties</param-value>
    </context-param>
    
    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>
    

    所以它在春天开始之前就起来了。

    【讨论】:

    • 我应该提到我的 log4J 属性文件的路径来自一个 JNDI 字符串。如何将该 JNDI 值提供给 。如果我能做到这一点,我想我已经准备好了。
    • 我发现了这个:coderanch.com/t/362833/Servlets/java/log-ServletContextListener——它展示了如何实现你自己的 log4j 配置监听器,它通过 JNDI 获取一些信息
    • 我像他们一样创建了自己的 servlet 上下文侦听器,并且一切正常。谢谢。
    【解决方案2】:

    我们的独立应用程序需要一个SMTPAppender,其中电子邮件配置已经存在于spring 配置文件中,我们不希望它在log4j.properties 中重复。

    我将以下内容放在一起使用 spring 添加一个额外的附加程序。

    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject">
            <bean factory-method="getRootLogger"
                  class="org.apache.log4j.Logger" />
        </property>
        <property name="targetMethod">
            <value>addAppender</value>
        </property>
        <property name="arguments">
            <list>
                <bean init-method="activateOptions"
                      class="org.apache.log4j.net.SMTPAppender">
                    <property name="SMTPHost" ref="mailServer" />
                    <property name="from" ref="mailFrom" />
                    <property name="to" ref="mailTo" />
                    <property name="subject" ref="mailSubject" />
                    <property value="10" name="bufferSize" />
                    <property name="layout">
                        <bean class="org.apache.log4j.PatternLayout">
                            <constructor-arg>
                                <value>%d, [%5p] [%t] [%c] - %m%n</value>
                            </constructor-arg>
                        </bean>
                    </property>
                    <property name="threshold">
                        <bean class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"
                              id="org.apache.log4j.Priority.ERROR" />
                    </property>
                </bean>
            </list>
        </property>
    </bean>
    

    我们在类路径中还有一个log4j.properties 文件,其中详细说明了我们的常规FileAppenders

    我意识到这对于您的要求可能有点过分了 :)

    【讨论】:

      【解决方案3】:

      与其在代码中自己配置 log4j,不如通过添加将 log4j 指向您的(自定义)配置文件的位置

      -Dlog4j.configuration=.../conf/log4j.xml
      

      到您服务器的启动属性?

      更好的是,只需将 log4j.xml 移动到默认位置 - 在类路径上 - 并让 log4j 自动配置自己。

      【讨论】:

      • 我正在尝试将 log4j 文件保留在 WAR 之外,以便我们可以让客户根据需要轻松调整它以进行问题诊断。至于JVM属性,目前我们连启动脚本都没有。客户只需部署 WAR 文件即可。
      • 在某些情况下我们应该在路径-Dlog4j.configuration=file:conf/log4j.properties添加“文件”前缀
      • @matt b 请澄清类路径序列扫描
      【解决方案4】:

      您可以使用类路径而不是硬编码路径。它对我有用

      <bean id="log4jInitializer" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" depends-on="sbeHome">
          <property name="targetClass" value="org.springframework.util.Log4jConfigurer" />
          <property name="targetMethod" value="initLogging" />
          <property name="arguments">
              <list>
                  <value>classpath:/conf/log4j.xml</value>
              </list>
          </property>
      </bean>
      

      【讨论】:

      • 是否可以在此解决方案中使用 URL?
      【解决方案5】:

      如果您使用 Jetty,您可以为每个应用程序添加额外的类路径:

      http://wiki.eclipse.org/Jetty/Reference/Jetty_Classloading#Adding_Extra_Classpaths_to_Jetty

      这将允许您以标准方式加载 log4 属性(从类路径:)

      在 web.xml 中:

             <listener>
                 <listener-class>org.springframework.web.util.Log4jWebConfigurer</listener-class>
             </listener>
             <context-param>
                 <param-name>log4jConfigLocation</param-name>
                 <param-value>classpath:${project.artifactId}-log4j.properties</param-value>
             </context-param>
      

      在 jetty-web.xml 中:

              <Set name="extraClasspath">
                  <SystemProperty name="config.home" default="."/>/contexts/log4j
              </Set>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-09-04
        • 2017-11-11
        • 1970-01-01
        • 2010-11-11
        • 2015-04-13
        • 1970-01-01
        • 2011-03-20
        • 1970-01-01
        相关资源
        最近更新 更多