问题描述: 配置了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 Mapquery(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则可以避免这些不必要的调用。