开发者社区> 问答> 正文

web.xml中配置log4jConfigLocation属性:报错

我在spring工程下的web.xml文件中配置log4j相关属性,代码如下


<!-- 日志记录 -->
  <context-param>
  <!-- 日志配置路径 -->
  <param-name>log4jConfigLocation</param-name>
  <param-value>
  classpath:log4j.properties
  </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>




一开始我把classpath:log4j.properties写成了classpath*:log4j.properties就报错了,如下

java.lang.IllegalArgumentException: Invalid 'log4jConfigLocation' parameter: Log4j config file [F:\tomcat\webapps\hoteldemo\classpath*:log4j.properties] not found


好像配置log4j的时候不能把 classpath写成classpath*。但是在配置 contextConfigLocation 的时候是可以的。我查了资料也都是关于 classpath*和classpath,一个能遍历classpath下jar中的内容,一个不行。然而我想classpath*只是比classpath多遍历内容而已,怎么就不能替换了呢?是不是因为配置log4j有特殊的要求,不是我们手动配置去定义路径的?跟配置contextConfigLocation不是一回事


求解答,找了好多资料都不是我想要的,谢谢了
  

展开
收起
kun坤 2020-06-14 16:31:03 822 0
1 条回答
写回答
取消 提交回答
  • 人家log4j读取web.xml的变量逻辑凭啥一定要跟spring一致呢,这个又没形成标准,具体你还是自己看看Log4jConfigListener里面源码怎么写的######

    [F:\tomcat\webapps\hoteldemo\classpath*:log4j.properties] not found

    首先系统这样说就是找不到你所指向的路径,

    但是contextConfigLocation配置的时候是结合web.xml的配置文件内容一起加载的,系统自动识别支持你这样的classpath*的写法 单写的话肯定是不行的 因为没有描述文件让系统知道你写的代码 所以加载不上就报错



    log4j.rootCategory=debug, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n log4j.category.org.springframework.beans.factory=error  

    主要常用的属性也就这么多了

    ######

    引用来自“838384855”的评论

    [F:\tomcat\webapps\hoteldemo\classpath*:log4j.properties] not found

    首先系统这样说就是找不到你所指向的路径,

    但是contextConfigLocation配置的时候是结合web.xml的配置文件内容一起加载的,系统自动识别支持你这样的classpath*的写法 单写的话肯定是不行的 因为没有描述文件让系统知道你写的代码 所以加载不上就报错



    log4j.rootCategory=debug, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n log4j.category.org.springframework.beans.factory=error  

    主要常用的属性也就这么多了

    这个我已经写了的,写在log4j.properties中,log4j.properties与applicationContext.xml等配置文件都在同一目录下,我今天看了一下源码,Log4jConfigListener的代码有如下内容

    public class Log4jConfigListener implements ServletContextListener {
    
    	public void contextInitialized(ServletContextEvent event) {
    		Log4jWebConfigurer.initLogging(event.getServletContext());
    	}
    
    	public void contextDestroyed(ServletContextEvent event) {
    		Log4jWebConfigurer.shutdownLogging(event.getServletContext());
    	}
    
    }



    然后我看了initLogging,它有一个路径判断:
    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 system property placeholders before potentially
    				// resolving a real path.
    				location = SystemPropertyUtils.resolvePlaceholders(location);
    
    				// 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());
    			}
    		}
    	}



    在initLogging中需要进行路径验证,
    跟踪isurl()函数,其中定义了一些公共变量:
    public static final java.lang.String CLASSPATH_URL_PREFIX = "classpath:";
      
      // Field descriptor #73 Ljava/lang/String;
      public static final java.lang.String FILE_URL_PREFIX = "file:";
      
      // Field descriptor #73 Ljava/lang/String;
      public static final java.lang.String URL_PROTOCOL_FILE = "file";
      
      // Field descriptor #73 Ljava/lang/String;
      public static final java.lang.String URL_PROTOCOL_JAR = "jar";
      
      // Field descriptor #73 Ljava/lang/String;
      public static final java.lang.String URL_PROTOCOL_ZIP = "zip";



      省略了一部分,其中没有classpath*这一变量,因此我觉得log4j中会把classpath*当成是路径变量之一,所以它识别到的路径是错误的,因此而报错,
    但是在contextConfigLocation中,我是可以使用classpath*:applicationContext.xml,它的路径解析是可以写成classpath*的方式的,两者的路径解析貌似不一样,我还没有找到contextConfigLocation的一些配置,还是有些疑惑。

    2020-06-14 16:31:12
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
PostgresChina2018_赖思超_PostgreSQL10_hash索引的WAL日志修改版final 立即下载
Kubernetes下日志实时采集、存储与计算实践 立即下载
日志数据采集与分析对接 立即下载