spring配置中log4j.properties的后备

时间:2014-07-11 00:30:43

标签: spring spring-mvc log4j web.xml

我的配置如下:

 <context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>classpath:META-INF/spring/environments/${env}/log4j.properties</param-value>
</context-param>

我想要的是,如果

  

META-INF /弹簧/环境/ $ {ENV} /log4j.properties

找不到

,我想加载web.xml

  

META-INF /弹簧/环境的/ dev / log4j.properties

有可能吗?

2 个答案:

答案 0 :(得分:1)

如果无法解析${env}并且您收到Could not resolve placeholder 'env' in string value "classpath:META-INF/spring/environments/${env}/log4j.properties"之类的异常,则可以使用以下格式轻松实现:

<param-value>classpath:META-INF/spring/environments/${env:dev}/log4j.properties</param-value>

但我认为这不是你所面临的实际问题。

我相信您已经${env}已正确解析但未找到实际的log4j.properties文件,否则会正确解析(例如META-INF/spring/environments/prod/log4j.properties),位置。

我是这种情况我不认为你想要实现的是开箱即​​用的,我相信你需要一些自定义代码。我这样说是因为处理Log4J配置找不到配置文件的Spring代码不允许任何“默认”回退选项。正如您在Log4jWebConfigurer source code中看到的那样,如果找不到该文件,则最终会抛出IllegalArgumentException

catch (FileNotFoundException ex) {
            throw new IllegalArgumentException("Invalid 'log4jConfigLocation' parameter: " + ex.getMessage());
        }

这就是说,这是我尝试的一个可能的解决方案:

  • 定义您自己的Log4jConfigListener
package com.foo.bar;

import java.io.FileNotFoundException;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;

import org.springframework.util.Log4jConfigurer;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.util.Log4jConfigListener;
import org.springframework.web.util.Log4jWebConfigurer;
import org.springframework.web.util.ServletContextPropertyUtils;
import org.springframework.web.util.WebUtils;

public class MyLog4jConfigListener extends Log4jConfigListener {

    public static final String DEFAULT_CONFIG_LOCATION_PARAM = "defaultLog4jConfigLocation";

    @Override
    public void contextInitialized(ServletContextEvent event) {
        try {
            super.contextInitialized(event);
        } catch (IllegalArgumentException e) {
            // the log4jConfigLocation file hasn't been found, try the default
            if (!successfulDefaultLocationLookup(event)) {
                // if the default parameter hasn't been set or there are issues, fallback to the initial behavior (throwing an IllegalArgumentException)
                throw e;
            }
        }
    }

    private boolean successfulDefaultLocationLookup(ServletContextEvent event) {
        ServletContext servletContext = event.getServletContext();
        String location = servletContext.getInitParameter(DEFAULT_CONFIG_LOCATION_PARAM);
        if (location != null) {
            try {
                // Resolve property placeholders before potentially resolving a real path.
                location = ServletContextPropertyUtils.resolvePlaceholders(location, servletContext);

                // Leave a URL (e.g. "classpath:" or "file:") as-is.
                if (!ResourceUtils.isUrl(location)) {
                    // Consider a plain file path as relative to the web
                    // application root directory.
                    location = WebUtils.getRealPath(servletContext, location);
                }

                // Write log message to server log.
                servletContext.log("Initializing log4j from default location [" + location + "]");

                // Check whether refresh interval was specified.
                String intervalString = servletContext.getInitParameter(Log4jWebConfigurer.REFRESH_INTERVAL_PARAM);
                if (StringUtils.hasText(intervalString)) {
                    // Initialize with refresh interval, i.e. with log4j's watchdog thread,
                    // checking the file in the background.
                    try {
                        long refreshInterval = Long.parseLong(intervalString);
                        Log4jConfigurer.initLogging(location, refreshInterval);
                    }
                    catch (NumberFormatException ex) {
                        servletContext.log("Invalid 'log4jRefreshInterval' parameter for default log4j configuration file lookup: " + ex.getMessage());
                        return false;
                    }
                }
                else {
                    // Initialize without refresh check, i.e. without log4j's watchdog thread.
                    Log4jConfigurer.initLogging(location);
                }

                return true;
            }
            catch (FileNotFoundException ex) {
                servletContext.log("Invalid 'log4jConfigLocation' parameter for default log4j configuration file lookup: " + ex.getMessage());
                return false;
            }
        }

        return false;
    }

}
  • web.xml
  • 中定义自定义侦听器
<listener>
    <listener-class>com.foo.bar.MyLog4jConfigListener</listener-class>
</listener>
  • 除了正常的log4j context-param配置外,还要为默认位置
  • 定义自定义参数
<context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>classpath:META-INF/spring/environments/${env}/log4j.properties</param-value>
</context-param>

<context-param>
    <param-name>defaultLog4jConfigLocation</param-name>
    <param-value>classpath:META-INF/spring/environments/dev/log4j.properties</param-value>
</context-param>

答案 1 :(得分:0)

我不知道如何将其设置为使用条件IF语句,但我认为您可以使用通配符来完成此操作。 Spring 4 docs解释了如何,但由于格式问题,它更容易在Spring 3 docs中阅读。但我会在这里总结一下你。

您可以使用特殊的classpath*:前缀和/或内部Ant样式的正则表达式。

  • 使用Ant风格的模式:
    • classpath:META-INF/spring/environments/**/log4j.properties
    • 此搜索将找到META-INF/spring/environments/的第一个实例,并将下一个目录作为通配符提供。此搜索仅返回找到的第一个内容。
  • 使用classpath*:前缀:
    • classpath*:META-INF/spring/environments/**/log4j.properties
    • 此搜索将返回并合并与此模式匹配的所有文件的结果。