说起LogConfiguratorListener来,还得从配置文件web.xml开始说起,在web.xml配置中,有一项很重要的配置项,那就是日志系统初始化:
<!-- 初始化日志系统 -->
<listener>
<listener-class>com.alibaba.citrus.logconfig.LogConfiguratorListener</listener-class>
</listener>
在WEB应用被起动的时候,这个listener就会被激活,进行日志系统的初始化工作。
LogConfiguratorListener的作用
正如前面所说的,LogConfiguratorListener就是负责在WEB应用起动的时候初始化日志系统,在做这些工作的时候,它会读取init参数,这些参数也同样配置在web.xml文件中,如下:
<context-param>
<param-name>loggingRoot</param-name>
<param-value>/tmp/logs</param-value>
</context-param>
<context-param>
<param-name>loggingLevel</param-name>
<param-value>INFO</param-value>
</context-param>
<context-param>
<param-name>loggingCharset</param-name>
<param-value>UTF-8</param-value>
</context-param>
<context-param>
<param-name>log...</param-name>
<param-value>...</param-value>
</context-param>
LogConfiguratorListener实现
LogConfiguratorListener实现了ServletContextListener接口,ServletContextListener是ServletContext的监听接口,当ServletContext被创建时,ServletContextListener的contextInitialized方法会被调用,日志系统的初始化就在这个方法里实现。当应用被关闭时,ServletContextListener的contextDestroyed方法会被调用,在这个方法里会把日志系统关闭。下面是方法的源码:
public void contextInitialized(ServletContextEvent event) {
ServletContext servletContext = event.getServletContext();
// 取得所有以log开头的init params。
Map<String, String> params = getLogInitParams(servletContext);
// 从context init-param中取得logSystem的值,可能为null。
String[] logSystems = getLogSystems(params);
// 取得指定名称的logConfigurator,如未取得,则抛出异常,listener失败。
logConfigurators = LogConfigurator.getConfigurators(logSystems);
for (LogConfigurator logConfigurator : logConfigurators) {
String logSystem = logConfigurator.getLogSystem();
// 取得指定logConfigurator的配置文件。
String logConfiguration = getLogConfiguration(params, logSystem);
servletContext.log(String.format("Initializing %s system", logSystem));
// 取得log配置文件。
URL logConfigurationResource;
try {
logConfigurationResource = servletContext.getResource(logConfiguration);
} catch (MalformedURLException e) {
logConfigurationResource = null;
}
// 如未找到配置文件,则用默认的值来配置,否则配置之。
if (logConfigurationResource == null) {
servletContext
.log(String
.format("Could not find %s configuration file \"%s\" in webapp context. Using default configurations.",
logSystem, logConfiguration));
logConfigurator.configureDefault();
} else {
Map<String, String> props = logConfigurator.getDefaultProperties();
initProperties(props);
props.putAll(params);
logConfigurator.configure(logConfigurationResource, props);
}
}
}
分析一下上面的源码,看看方法contextInitialized都干了哪些事儿呢?
1、取init参数
在web.xml文件里配置的context-param参数中,查找以log开头的参数。
2、根据init参数,生成日志配置器
在步骤1中取到的以log开头的参数中,查找logSystem参数,里面设置了要采用的日志系统名称,如果有多个的话会以逗号或空格分隔。如果web.xml中没有设置logSystem参数,则默认采用slf4j中的日志系统。拿到logSystem名称后,根据名称构造出LogConfigurator。
3、读取每个日志配置器的配置文件,如果配置文件不存在就用默认值来配置
在web.xml文件中,logConfiguration参数配置了日志系统配置文件的路径,如果web.xml文件中没有这个文件,那么采用默认路径"/WEB-INF/日志系统名称.xml“,如果配置文件找到了,用它来配置步骤2中生成的LogConfigurator;如果没有找到配置文件,则还有一个默认的配置文件,名称是”日志系统名称-default.xml"。