Spring搭建:log4j的配置

在spring搭建项目时,一般都是需要使用log4j。此时,需要在web.xml中配置好log4j,或者log4j.xml中进行路径配置,此时就需要进行log4j的配置了解。

web.xml中的配置

在spring中,使用log4j时,主要2点。一是web.xml中配置log4j;二是项目的webapp下配置log4j.xml。首先是web.xml中配置。如下:

   <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>classpath:log4j.xml</param-value>
    </context-param>
    <context-param>
        <param-name>log4jRefreshInterval</param-name>
        <param-value>60000</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>

web.xml最前面写入以上的配置就可以了。
参数:log4jConfigLocation主要是配置log4j.xml的文件位置。可以指定方式如下:
1.类路径,例如:classpath:log4j.xml;
2.绝对文件路径,例如:d:/log4j.xml;
3.如果不指定,默认采取class路径中的”log4j.properties” 或 “log4j.xml”
参数:log4jRefreshInterval主要检测log4j配置文件刷新时间,动态修改log4j配置。
指定参数:配置文件刷新时间(单位是毫秒)
不指定参数:不再检查log4j配置文件有没有发生,同时log4j的监督线程将不会启动。

注意点:
log4j的listener配置要优先于spring的ContextLoaderListener配置。

log4j.xml中的路径问题

在log4j.xml中配置文件时,可以如下配置:

log4j.appender.myfile.File=${webapp.root}/WEB-INF/demo.log

将路径指定为动态的{webapp.root},它会在项目运行时,进行替换操作,它允许日志文件路径相对于web应用程序的根目录。
当需要使用多个webapp.root时,或者需要换个名字时,可以在web.xml中如下配置:

   <context-param>
        <param-name>webAppRootKey</param-name>
        <param-value>demo.root</param-value>
    </context-param>

如此,log4j中就可以采取如下方式指定了:

log4j.appender.myfile.File=${demo.root}/WEB-INF/demo.log

Log4jConfigListener说明

采取Log4jConfigListener配置时,它的源码如下:

/**
 * <p>This listener should be registered before ContextLoaderListener in {@code web.xml}
 * when using custom log4j initialization.
 */
public class Log4jConfigListener implements ServletContextListener {
    public Log4jConfigListener() {
    }

    public void contextInitialized(ServletContextEvent event) {
        Log4jWebConfigurer.initLogging(event.getServletContext());
    }

    public void contextDestroyed(ServletContextEvent event) {
        Log4jWebConfigurer.shutdownLogging(event.getServletContext());
    }
}

主要使用了Log4jWebConfigurer进行初始化等操作。类说明了,应该在ContextLoaderListener 之前进行初始化操作。其余介绍可参考源码。

Log4jWebConfigurer说明

Log4jWebConfigurer简化源码如下所示:

public abstract class Log4jWebConfigurer {

    /** Parameter specifying the location of the log4j config file */
    public static final String CONFIG_LOCATION_PARAM = "log4jConfigLocation";

    /** Parameter specifying the refresh interval for checking the log4j config file */
    public static final String REFRESH_INTERVAL_PARAM = "log4jRefreshInterval";

    /** Parameter specifying whether to expose the web app root system property */
    public static final String EXPOSE_WEB_APP_ROOT_PARAM = "log4jExposeWebAppRoot";


    /**
     * Initialize log4j, including setting the web app root system property.
     * @param servletContext the current ServletContext
     * @see WebUtils#setWebAppRootSystemProperty
     */
    public static void initLogging(ServletContext servletContext) {
        .....
    }

    /**
     * Shut down log4j, properly releasing all file locks
     * and resetting the web app root system property.
     * @param servletContext the current ServletContext
     * @see WebUtils#removeWebAppRootSystemProperty
     */
    public static void shutdownLogging(ServletContext servletContext) {
        .......
    }

    /**
     * Return whether to expose the web app root system property,
     * checking the corresponding ServletContext init parameter.
     * @see #EXPOSE_WEB_APP_ROOT_PARAM
     */
    private static boolean exposeWebAppRoot(ServletContext servletContext) {
        String exposeWebAppRootParam = servletContext.getInitParameter(EXPOSE_WEB_APP_ROOT_PARAM);
        return (exposeWebAppRootParam == null || Boolean.valueOf(exposeWebAppRootParam));
    }

}

前面的三个参数就是我们在web.xml中进行配置的参数,后面的2个方法是log4j的初始化方法。

log4jConfigLocation说明:

    /** Parameter specifying the location of the log4j config file */
    public static final String CONFIG_LOCATION_PARAM = "log4jConfigLocation";
/*  
 * Location of the log4j config file; either a "classpath:" location (e.g.
 * "classpath:myLog4j.properties"), an absolute file URL (e.g. "file:C:/log4j.properties),
 * or a plain path relative to the web application root directory (e.g.
 * "/WEB-INF/log4j.properties"). If not specified, default log4j initialization
 * will apply ("log4j.properties" or "log4j.xml" in the class path; see the
 * log4j documentation for details).
 */

log4jRefreshInterval说明:

/** Parameter specifying the refresh interval for checking the log4j config file */
    public static final String REFRESH_INTERVAL_PARAM = "log4jRefreshInterval";

/*
 * Interval between config file refresh checks, in milliseconds. If not specified,
 * no refresh checks will happen, which avoids starting log4j's watchdog thread.
 */

log4jExposeWebAppRoot说明:

    /** Parameter specifying whether to expose the web app root system property */
    public static final String EXPOSE_WEB_APP_ROOT_PARAM = "log4jExposeWebAppRoot";

/**
 * Whether the web app root system property should be exposed, allowing for log
 * file paths relative to the web application root directory. Default is "true";
 * specify "false" to suppress expose of the web app root system property. See
 * below for details on how to use this system property in log file locations.
 */

这个参数一般不需要配置,默认是”true”,是否暴漏log4j配置。在 Log4jWebConfigurer的initLogging(ServletContext servletContext)中会去检查,如下所示:

public static void initLogging(ServletContext servletContext) {
        // Expose the web app root system property.
        if (exposeWebAppRoot(servletContext)) {
            WebUtils.setWebAppRootSystemProperty(servletContext);
        }
        .......
}

setWebAppRootSystemProperty方法就说明了webapp的设置和webAppRootKey的设置问题。

    /**
     * Web app root key parameter at the servlet context level
     * (i.e. a context-param in {@code web.xml}): "webAppRootKey".
     */
    public static final String WEB_APP_ROOT_KEY_PARAM = "webAppRootKey";

    /** Default web app root key: "webapp.root" */
    public static final String DEFAULT_WEB_APP_ROOT_KEY = "webapp.root";

    /**
     * Set a system property to the web application root directory.
     * The key of the system property can be defined with the "webAppRootKey"
     * context-param in {@code web.xml}. Default is "webapp.root".
     * <p>Can be used for tools that support substition with {@code System.getProperty}
     * values, like log4j's "${key}" syntax within log file locations.
     * @param servletContext the servlet context of the web application
     * @throws IllegalStateException if the system property is already set,
     * or if the WAR file is not expanded
     * @see #WEB_APP_ROOT_KEY_PARAM
     * @see #DEFAULT_WEB_APP_ROOT_KEY
     * @see WebAppRootListener
     * @see Log4jWebConfigurer
     */
    public static void setWebAppRootSystemProperty(ServletContext servletContext) throws IllegalStateException {
        Assert.notNull(servletContext, "ServletContext must not be null");
        String root = servletContext.getRealPath("/");
        if (root == null) {
            throw new IllegalStateException(
                "Cannot set web app root system property when WAR file is not expanded");
        }
        String param = servletContext.getInitParameter(WEB_APP_ROOT_KEY_PARAM);
        String key = (param != null ? param : DEFAULT_WEB_APP_ROOT_KEY);
        String oldValue = System.getProperty(key);
        if (oldValue != null && !StringUtils.pathEquals(oldValue, root)) {
            throw new IllegalStateException(
                "Web app root system property already set to different value: '" +
                key + "' = [" + oldValue + "] instead of [" + root + "] - " +
                "Choose unique values for the 'webAppRootKey' context-param in your web.xml files!");
        }
        System.setProperty(key, root);
        servletContext.log("Set web app root system property: '" + key + "' = [" + root + "]");
    }

log4j的init方法如下:

/**
     * Initialize log4j, including setting the web app root system property.
     * @param servletContext the current ServletContext
     * @see WebUtils#setWebAppRootSystemProperty
     */
    public static void initLogging(ServletContext servletContext) {
        // Expose the web app root system property.
        if (exposeWebAppRoot(servletContext)) {
            WebUtils.setWebAppRootSystemProperty(servletContext);
        }

        // Only perform custom log4j initialization in case of a config file.
        String location = servletContext.getInitParameter(CONFIG_LOCATION_PARAM);
        if (location != null) {
            // Perform actual log4j initialization; else rely on log4j's default initialization.
            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 [" + location + "]");

                // Check whether refresh interval was specified.
                String intervalString = servletContext.getInitParameter(REFRESH_INTERVAL_PARAM);
                if (intervalString != null) {
                    // 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) {
                        throw new IllegalArgumentException("Invalid 'log4jRefreshInterval' parameter: " + ex.getMessage());
                    }
                }
                else {
                    // Initialize without refresh check, i.e. without log4j's watchdog thread.
                    Log4jConfigurer.initLogging(location);
                }
            }
            catch (FileNotFoundException ex) {
                throw new IllegalArgumentException("Invalid 'log4jConfigLocation' parameter: " + ex.getMessage());
            }
        }
    }

主要:1.检查是否暴漏;2.读取log4j文件;3.替换log4j文件的占位符;4.读取刷新时间,初始化log4j。最终调用Log4jConfigurer方法。

shutdownLogging主要就是关闭log4j了。

    /**
     * Shut down log4j, properly releasing all file locks
     * and resetting the web app root system property.
     * @param servletContext the current ServletContext
     * @see WebUtils#removeWebAppRootSystemProperty
     */
    public static void shutdownLogging(ServletContext servletContext) {
        servletContext.log("Shutting down log4j");
        try {
            Log4jConfigurer.shutdownLogging();
        }
        finally {
            // Remove the web app root system property.
            if (exposeWebAppRoot(servletContext)) {
                WebUtils.removeWebAppRootSystemProperty(servletContext);
            }
        }
    }

以上基本介绍了log4j,具体的实现待考虑下。


参考文档:官方文档—https://docs.spring.io/spring/docs/2.5.x/javadoc-api/org/springframework/web/util/Log4jWebConfigurer.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值