Log4j在系统记录日志方面功能很强大,但是,在配置文件路径、日志文件路径及动态修改日志记录器级别等信息时却不够灵活,存在一些不足之处。好在spring提供了相关功能弥补了log4j在这方面的不足。接下来就来看一看spring是如何实现这方面功能的。
spring针对log4j提供了如下功能:
1. 可以通过定期检查配置文件的变化来动态的改变记录级别和策略,不需要重启Web应用。 web.xml配置如下:
<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>6000</param-value>
</context-param>
2. 把日志文件定在 web应用目录下的任何位置,而不需要写绝对路径。
因为系统把web应用目录的路径压入一个叫webapp.root的系统变量。这样写log文件路径时不用写绝对路径了。当然也可以手动修改该系统变量。web.xml配置如下:
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>muse.root</param-value>
</context-param>
注意:不同的应用不可以配置一样的webAppRootKey值,否则会导致系统无法正常启动。
log4j配置如下:log4j.appender.ROLLING_FILE.File=${muse.root}/WEB-INF/logs/muse.log
3. 可以把log4j.properties和其他properties一起放在/WEB-INF/ ,而不是Class-Path。 web.xml配置如下:
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.xml</param-value>
</context-param>
注:如果要使webAppRootKey生效,则该项一定要配置,当然也可指定properties文件,因为如果没有配置的话,Log4jConfigListener是不会调用log4j初始化配置的。
接下来通过应用配置及源码赏析两方面来详细了解一下这些功能。
1 应用配置
1.1 web.xml
所有相关的web.xml配置信息如下:
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>muse.root</param-value>
</context-param>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.xml</param-value>
</context-param>
<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>6000</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
1.2 log4j.properties配置
所有相关的log4j.properties配置信息如下:
log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender
log4j.appender.ROLLING_FILE.Threshold=INFO
log4j.appender.ROLLING_FILE.File=${muse.root}/logs/muse.log
log4j.appender.ROLLING_FILE.Append=true
log4j.appender.ROLLING_FILE.MaxFileSize=5000KB
log4j.appender.ROLLING_FILE.MaxBackupIndex=100
log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLING_FILE.layout.ConversionPattern=%d{yyyy-M-d HH:mm:ss}%x[%5p](%F:%L) %m%n
2 源码赏析
2.1 Log4jConfigListener类
这是应用启动时即调用的监听类。该类不具体处理业务逻辑,直接调用Log4jWebConfigurer.initLogging()。
public class Log4jConfigListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
Log4jWebConfigurer.initLogging(event.getServletContext());
}
}
2.2 Log4jWebConfigurer类
这是一个便于在web环境定制log4j初始化的类。即log4j初始化前需要做的一些事情的处理类,当然它也包括调用处理具体初始化工作的类。
public abstract class Log4jWebConfigurer {
/** 该属性用来指定log4j 配置文件的路径。 */
public static final String CONFIG_LOCATION_PARAM = "log4jConfigLocation";
/** 该属性用来指定检查log4j 配置文件的间隔时间。 */
public static final String REFRESH_INTERVAL_PARAM = "log4jRefreshInterval";
/** 该属性用来指定是否设置web应用根目录环境变量。 */
public static final String EXPOSE_WEB_APP_ROOT_PARAM = "log4jExposeWebAppRoot";
/**
* 初始化log4j,包括设置web应用根目录系统属性。
*/
public static void initLogging(ServletContext servletContext) {
if (exposeWebAppRoot(servletContext)) {
WebUtils.setWebAppRootSystemProperty(servletContext);
}
String location = servletContext.getInitParameter(CONFIG_LOCATION_PARAM);
if (location != null) {
try {
if (!ResourceUtils.isUrl(location)) {
// 解决系统属性占位符的问题。
location = SystemPropertyUtils.resolvePlaceholders(location);
location = WebUtils.getRealPath(servletContext, location);
}
servletContext.log("Initializing log4j from [" + location + "]");
String intervalString = servletContext.getInitParameter(REFRESH_INTERVAL_PARAM);
if (intervalString != null) {
try {
long refreshInterval = Long.parseLong(intervalString);
Log4jConfigurer.initLogging(location, refreshInterval);
}
catch (NumberFormatException ex) {
throw new IllegalArgumentException("Invalid 'log4jRefreshInterval' parameter: " + ex.getMessage());
}
}
else {
Log4jConfigurer.initLogging(location);
}
}
catch (FileNotFoundException ex) {
throw new IllegalArgumentException("Invalid 'log4jConfigLocation' parameter: " + ex.getMessage());
}
}
}
/**
* 返回是否进行web应用根目录系统属性设置。
*/
private static boolean exposeWebAppRoot(ServletContext servletContext) {
String exposeWebAppRootParam = servletContext.getInitParameter(EXPOSE_WEB_APP_ROOT_PARAM);
return (exposeWebAppRootParam == null || Boolean.valueOf(exposeWebAppRootParam));
}
}
2.3 WebUtils类
这个类是web应用程序的五花八门的工具箱。比如设置web应用目录系统属性等。
public abstract class WebUtils {
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";
/**
* 添加一个系统属性用于保存web应用根目录信息。系统属性键可以在web.xml文件的context-param节点定义。默认值为webapp.root。
* 如果不同的应用使用相同的该系统属性键则会报错。
*/
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 + "]");
}
/**
* 根据相对路径得到web应用下的绝对路径
*/
public static String getRealPath(ServletContext servletContext, String path) throws FileNotFoundException {
Assert.notNull(servletContext, "ServletContext must not be null");
if (!path.startsWith("/")) {
path = "/" + path;
}
String realPath = servletContext.getRealPath(path);
if (realPath == null) {
throw new FileNotFoundException(
"ServletContext resource [" + path + "] cannot be resolved to absolute file path - " +
"web application archive not expanded?");
}
return realPath;
}
}
2.4 Log4jConfigurer类
这是一个具体实现log4j配置的类。该类直接调用log4j组件的相关类进行日志记录器的配置。
public abstract class Log4jConfigurer {
public static final String CLASSPATH_URL_PREFIX = "classpath:";
public static final String XML_FILE_EXTENSION = ".xml";
/**
* 从指定的配置文件路径来初始化log4j,该方法不支持定时检查配置文件变更功能。
*/
public static void initLogging(String location) throws FileNotFoundException {
String resolvedLocation = SystemPropertyUtils.resolvePlaceholders(location);
URL url = ResourceUtils.getURL(resolvedLocation);
if (resolvedLocation.toLowerCase().endsWith(XML_FILE_EXTENSION)) {
DOMConfigurator.configure(url);
}
else {
PropertyConfigurator.configure(url);
}
}
/**
* 从指定的配置文件路径来初始化log4j,该方法支持定时检查配置文件变更功能。
*/
public static void initLogging(String location, long refreshInterval) throws FileNotFoundException {
String resolvedLocation = SystemPropertyUtils.resolvePlaceholders(location);
File file = ResourceUtils.getFile(resolvedLocation);
if (!file.exists()) {
throw new FileNotFoundException("Log4j config file [" + resolvedLocation + "] not found");
}
if (resolvedLocation.toLowerCase().endsWith(XML_FILE_EXTENSION)) {
DOMConfigurator.configureAndWatch(file.getAbsolutePath(), refreshInterval);
}
else {
PropertyConfigurator.configureAndWatch(file.getAbsolutePath(), refreshInterval);
}
}
}
2.5 ResourceUtils类
这是一个用来解决文件资源定位的工具类。
public abstract class ResourceUtils {
public static final String CLASSPATH_URL_PREFIX = "classpath:";
/**
* 返回指定的资源定位字符串是否是一个URL。
*/
public static boolean isUrl(String resourceLocation) {
if (resourceLocation == null) {
return false;
}
if (resourceLocation.startsWith(CLASSPATH_URL_PREFIX)) {
return true;
}
try {
new URL(resourceLocation);
return true;
}
catch (MalformedURLException ex) {
return false;
}
}
}
相关推荐
总之,将Spring的日志配置为Log4j,涉及到引入Log4j库、编写`log4j.properties`配置文件、以及在Spring配置文件中声明使用Log4j。理解这些步骤和配置项对于优化日志记录,排查问题以及监控系统运行状态至关重要。
本文将对"Log4j 1.2.17含源码"进行深入探讨,包括其核心组件、配置、使用方法以及源码分析。 首先,Log4j的核心组件主要包括Appender、Layout、Logger和Level。Appender负责输出日志信息到指定的目标,如控制台、...
本文将深入探讨log4j 1.2.15的源码,帮助开发者更好地理解其内部机制,提升对日志处理的掌控能力。 一、log4j概述 log4j是Apache组织开发的一个开源日志组件,主要功能是为Java应用程序提供灵活的日志记录服务。它...
源码学习有助于提升对log4j的理解,便于在实际项目中进行更精细的配置和定制。 **5. 扩展与进阶** 在熟悉了log4j的基本使用后,可以探索更多高级特性,如异步日志记录、自定义Appender和Layout、过滤器的使用等。...
总之,Log4j-1.2.13源码的分析不仅能够加深我们对日志处理的理解,还可以学习到优秀的设计模式和架构思想,是Java开发者的宝贵学习资源。在实际工作中,结合源码可以更好地定制和优化日志记录,提升软件的可维护性和...
Apache Log4j 2 源代码( apache-log4j-2.17.1-src.zip) 是对 Log4j 的升级,它比其前身 Log4j 1.x 提供了重大改进,并提供了 Logback 中可用的许多改进,同时修复了 Logback 架构中的一些固有问题。修复了安全漏洞...
- **资源消耗**:包括CPU、内存和磁盘I/O的使用情况,以了解Log4j2对系统资源的影响。 4. **优化策略** - **日志级别调整**:根据需求调整日志级别,减少不必要的日志记录,可以显著提升性能。 - **异步日志模式...
Apache Log4j是Java平台上的一个著名日志记录框架,其1.2.17版本是该框架的一个历史版本。...尽管Log4j后续有更先进的版本,如Log4j2,但对1.2.17版本的学习仍有助于理解日志处理的基本概念和技术。
本资源包含的是关于`SpringMVC`、`Log4j2`、`Logback`以及`Jackson`的日志脱敏实现源码,提供了多种实现方式,旨在帮助开发者在保障信息安全的同时,充分利用日志进行系统分析。 1. **基于正则表达式的日志脱敏实现...
**Log4j 1.2.8 源码解析** Log4j 是一个广泛使用...通过深入研究 Log4j 1.2.8 的源码,开发者不仅可以更好地掌握日志管理,还可以提升对 Java 多线程、反射、配置解析等技术的理解,为今后的软件开发提供强大的支持。
此次发布的binaries版本包含了编译后的二进制文件,适用于那些不希望从源码编译但需要快速部署和更新Log4j的用户。 描述中提到的“解决了漏洞版本”指的是Log4j 2.x 在2021年末被发现了一个名为“Log4Shell”的高危...
标题中的“log4jdbc-log4j2配置简记”指的是在Java开发中使用log4jdbc-log4j2库来监控和记录SQL查询的过程。log4jdbc是一个开源项目,它允许开发者通过日志系统来追踪数据库操作,而log4j2是log4j的升级版,提供了更...
Apache Log4j是Java平台上的一个著名日志记录框架,广泛应用于各种Java应用程序中,包括服务器、Web应用、企业级软件等。Log4j 1.2.16是该框架的一个版本,提供了丰富的日志功能,允许开发者灵活地控制日志信息的...
"源码"标签暗示我们将讨论Log4j的内部机制或如何查看和理解其代码,这对于学习和定制Log4j功能很有帮助。而"工具"标签则表明Log4j是一个开发者常用的工具,它的使用和配置是提高开发效率的关键。 **压缩包文件名称...
本示例源码将展示如何在Spring Boot项目中集成和使用Log4j进行日志管理。 首先,我们需要在Spring Boot项目的`pom.xml`文件中添加Log4j的依赖。确保你的Maven依赖中有以下内容: ```xml <groupId>org.spring...
在本项目中,"maven-spring-mybatis小型项目开发环境(3)log4j集成",我们将探讨如何在一个基于Maven、Spring和MyBatis的小型应用中整合Log4j日志框架。Log4j是Java应用程序广泛使用的日志记录工具,它提供灵活的日志...
log4j各个版本源码 1.2.8 1.2.15 1.2.17 2.3 这四个版本的源码 Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录...
《深入解析log4j-1.2.15:源码与工具的融合》 在IT行业中,日志记录是软件开发中不可或缺的一部分,它帮助开发者追踪程序运行状态,定位和解决问题。Log4j,作为Java领域最常用的日志框架之一,因其高效、灵活和可...
总结来说,Log4j的动态配置日志输出路径主要涉及对配置文件的解析和重新加载,以及在运行时使用API直接调整日志设置。理解并熟练运用这些方法,可以帮助我们在开发过程中更灵活地管理和监控日志,提高开发效率和问题...
源码说明:- SpringBoot只有1.3和1.3.x以下版本才支持log4j,1.3.x以上版本只支持log4j2(对于log4j来说很多变动)- 引入log4j之后,Springboot推荐优先使用带有-spring的文件名作为日志配置(eg: log4j-spring....