在web应用中使用log4j

阅读更多
实习了几个月,都不怎么写博客,今天在使用log4j的时候蛮纠结的,测试的时候是在普通的Java项目里面测试,使用还蛮简单的,结果将log4j移植到web项目中。好吧,问题出现了。折腾了我一个下午,结果还是路径的问题

问题描述: 配置了log4j.properties文件,配置文件放在src目录下,导入了jar包,结果在将日志信息写入文件中时出现问题了,根本就没有写入。

log4j.properties:

log4j.rootLogger=INFO, stdout, R

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%-5p\: %d{ISO8601}\: %C{1}[line\:%L}\: %m%n

log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=WEB-INF/log/offlineMap.log

log4j.appender.R.MaxFileSize=1024KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=5
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%-5p\: %d{ISO8601}\: %C{1}[line\:%L}\: %m%n


在java的类中使用如下:

package com.ylz.dao.map.impl;

import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;

import com.ylz.dao.map.MapQueryDao;
import com.ylz.model.TableInfo;
import com.ylz.utils.MapMerger;
import com.ylz.utils.MapToSqlHelper;

public class SiteDaoImpl implements MapQueryDao {
	private SimpleJdbcTemplate siteJdbcTemplate;
	private static Logger logger = Logger.getLogger(SiteDaoImpl.class);
	
	public SimpleJdbcTemplate getSiteJdbcTemplate() {
		return siteJdbcTemplate;
	}
	public void setSiteJdbcTemplate(SimpleJdbcTemplate siteJdbcTemplate) {
		this.siteJdbcTemplate = siteJdbcTemplate;
	}

	public Map query(TableInfo tableInfo) {
		String sql = MapToSqlHelper.getMapToSqlHelper().parseMapToSql(tableInfo).toString();
		
		Map rsMap = null; 
		try {
			rsMap = this.getSiteJdbcTemplate().queryForMap(sql, new Object[]{tableInfo.getQueryId()});
		} catch(EmptyResultDataAccessException e){
			logger.warn("WARNING : SiteDaoImpl.java query查询结果为空,请注意ID编号是否正确!");
			return null;
		}
		
		return MapMerger.getMapMerger().merge(rsMap,tableInfo.getColumnMap());
	}
}


结果是:只能将日志信息输出到控制台,而无法输出到日志文件中。这不是我想要的结果。

解决方法:
重新让log4j定位properties文件,这时,我把log4j.properties配置文件WEB-INF下面,然后让tomcat启动的时候就解析这个配置文件,然后将日志文件的位置重新赋值。而要在tomcat启动时做点事情,那么我写了一个servlet将load-on-startup设置为1,在web.xml配置文件中如下:
	
  
    Log4jServlet
    com.ylz.servlet.logger.Log4jServlet
    
			configFile
			
			WEB-INF/log4j.properties
	
	1
  


但是,我不让这个servlet被访问,仅仅需要servlet读取我们配置的log4j.properties的位置信息,然后再去重新配置log4j.properties配置文件里面的日志文件存放路径。这样的话,我在servlet的init方法里面做这些事情即可。


package com.ylz.servlet.logger;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import org.apache.log4j.PropertyConfigurator;

public class Log4jServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	public Log4jServlet() {
	}
	
	/**
	 * 初始化log4j配置文件的位置,然后重新设置日志文件的记录位置  
	 * @author LINWENBIN 
	 * @since 2013-5-27
	 * @throws 如果日志文件初始化失败,那么就抛出运行时异常,不然程序继续运行了.     更正,要考虑容错机制的加入.
	 */
	public void init() throws ServletException {
		String log4jConfigFilePath = this.getServletConfig().getInitParameter("configFile");
		String webRootPath = this.getServletContext().getRealPath("/");
		webRootPath = webRootPath.replaceAll("\\\\","/");
		String log4jConfigFileRealName = webRootPath + log4jConfigFilePath;
		Properties prop = new Properties();
		InputStream is = null;
		try {
			is = new FileInputStream(log4jConfigFileRealName);
			prop.load(is);
			String logFilePath = prop.getProperty("log4j.appender.R.File");
			logFilePath = webRootPath + logFilePath;
			System.out.println(logFilePath);
			[b]PropertyConfigurator.configure(prop);[/b]
		} catch (FileNotFoundException e) {
			throw new RuntimeException(e);
		} catch (IOException e) {
			throw new RuntimeException(e);
		} finally{ 
			try {
				is.close();
			} catch (IOException e1) {
				throw new RuntimeException(e1);
			}
		}
	}
}


思考:为什么不用Filter,Listener来实现这个事情呢?
我的理解:因为Filter没办法和tomcat一起启动并且在达到过滤条件的时候就会执行doFilter,这样反而浪费资源。而Listener在符合触发条件的时候,如session的创建,销毁等时刻就会触发各种listener对应的方法,这样也会导致不必要的调用。反而,我们放在servlet的init中然后不给这个servlet配置servlet-mapping则可以避免这些不必要的调用。


你可能感兴趣的:(log4j,log4j集成到web应用)