web项目添加log4j.properties 按年月日文件夹产生日志

2019-10-31 1543 星期四 enAn
说明

1. 重写的 Log4jFile extends RollingFileAppender
2. Log4jFile.java 中的格式化类型与log4j.properties中的输出的文件目录一致 log4j.appender.logFile.File=${log.home.dir}/yyyy/MM/dd/web.log
3. 指向自己重写的类      log4j.appender.logFile=com.ecommerce.platform.common.log.Log4jFile
4. 另外log4j.properties中
  log4j.rootLogger的变量logFile,必需与log4j.appender.logFile=com.ecommerce.platform.common.log.Log4jFile保持一致,不然不会输出日志
  5.监听器,把变量设置到环境中 [设置到系统属性集 ]java.util.Properties
  System.out.println(className + "[设置到系统属性集 ]");
				props.setProperty(InitConstant.DUBBO_REGISTRY_APPLICATION, dubbo_registry_application);//dubbo注册的应用名字
				props.setProperty(InitConstant.DUBBO_REGISTRY_ADDRESS,dubbo_registry_address);//dubbo:注册地址
				props.setProperty(InitConstant.DUBBO_CATALINA_HOME, dubbo_catalina_home);//dubbo缓存文件位置
				props.setProperty(InitConstant.LOG_HOME_DIR, log_dir);//log日志文件位置

  

**

log4j.properties和spring-mvc.xml,取监听器中设置的值

**

log4j.properties 设置值
log4j.appender.logFile.File=${log.home.dir}/yyyy/MM/dd/web.log

spring-mvc.xml 设置值
<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
	<dubbo:application name="#{systemProperties['dubbo.registry.application']}" />
	<!-- 使用zookeeper注册中心暴露服务地址 --> 
	<dubbo:registry protocol="zookeeper" address="#{systemProperties['dubbo.registry.address']}" file="#{systemProperties['dubbo.catalina.home']}"/>

log4j.properties配置文件内容

log4j.rootLogger=INFO,DEBUG,console,logFile,ERROR

## 控制台,begin ##
log4j.appender.console=org.apache.log4j.ConsoleAppender 
log4j.appender.console.layout=org.apache.log4j.PatternLayout 
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss} %-5p [%t] %c.%M(%L) - %m%n
## 控制台,end ##

### 输出到控制台,begin ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender 
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n  
### 输出到控制台,end ###

### 日志文件设置,begin ###
log4j.appender.logFile=com.ecommerce.platform.common.log.Log4jFile
#输出DEBUG级别日志到文件中 
log4j.appender.logFile.Threshold=debug 
log4j.appender.logFile.File=${log.home.dir}/yyyy/MM/dd/web.log
log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
log4j.appender.logFile.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.logFile.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss} %-5p [%t] %c.%M(%L) - %m%n
log4j.appender.logFile.MaxFileSize=50MB
### 日志文件设置,end ###

## 指定dao输出sql ##
# 打印sql语句:debug; 执行结果:trace	##
## 指定mapper配置文件中的namespace	##
## (log4j.logger.包名)原因是mybatis设置日志打印级别为TRACE即可输出sql文及sql参数和结果集。 ##
### sql ,begin ###
log4j.logger.com.ibatis=debug
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=debug
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=debug
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=debug
## ********************************* ##
log4j.logger.java.sql.Connection=debug
log4j.logger.java.sql.Statement=debug
log4j.logger.java.sql.PreparedStatement=debug,stdout
## ********************************* ##
log4j.logger.jdbc.sqlonly=OFF
log4j.logger.jdbc.sqltiming=OFF
log4j.logger.jdbc.audit=OFF
log4j.logger.jdbc.resultset=OFF
log4j.logger.jdbc.connection=OFF
### sql ,end ###

把监听器加放web.xml中

<!-- 自定义监听器,加载指定属性文件中的内容 -->
	 <listener>
        <listener-class>com.ecommerce.platform.listener.InitSystemConfigListener</listener-class>
    </listener>

监听器

package com.ecommerce.platform.listener;

import java.util.Map;
import java.util.Properties;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import com.ecommerce.platform.common.constant.InitConstant;
import com.ecommerce.platform.common.exception.CommonConfigException;
import com.ecommerce.platform.common.util.LoadProperties;
import com.ecommerce.platform.common.util.PropertiesUtil;

 /**
 *                    .::::.
 *                  .::::::::.
 *                 :::::::::::  I && YOU
 *             ..:::::::::::'
 *           '::::::::::::'
 *             .::::::::::
 *        '::::::::::::::..
 *             ..::::::::::::.
 *           ``::::::::::::::::
 *            ::::``:::::::::'        .:::.
 *           ::::'   ':::::'       .::::::::.
 *         .::::'      ::::     .:::::::'::::.
 *        .:::'       :::::  .:::::::::' ':::::.
 *       .::'        :::::.:::::::::'      ':::::.
 *      .::'         ::::::::::::::'         ``::::.
 *  ...:::           ::::::::::::'              ``::.
 * ````':.          ':::::::::'                  ::::..
 *                    '.:::::'                    ':'````..
 * 自定义监听器,加载属性文件中定义的变量值,在web.xml中使用,特别是配置log4j的值
 * @author enAn,2019-07-22
 * 参考:https://blog.csdn.net/liufunan/article/details/50715167
 */
public class InitSystemConfigListener implements ServletContextListener {
	public static final String className = "初始化-自定义监听器[InitSystemConfigListener]...";
	 public void contextDestroyed(ServletContextEvent sce) {  
	        System.out.println(className + "web exit ... ");  
	    }
	    public void contextInitialized(ServletContextEvent sce) {
	        try {
	        	Map<String, String> initPropertiesData = PropertiesUtil.getInitProperties();
	        	String log_dir = "";
				String dubbo_catalina_home = "";
				System.out.println(className + "init");
				Properties props= System.getProperties(); //获得系统属性集   
				String os = props.getProperty(InitConstant.OS_NAME);  
				String osVersion = props.getProperty(InitConstant.OS_VERSION); //操作系统版本 
				String javaVersion = props.getProperty(InitConstant.JAVA_VERSION); //Java 运行时环境版本
				System.out.println(className + "当前操作系统是 :" +  os);
				System.out.println(className + "操作系统的版本 :" + osVersion  );
				System.out.println(className + "java版本 :" + javaVersion );//当前操作系统是:Windows 7
				//**************************************************************************************************************
				//加载web.xml中的配置信息
				//将Map通过ServletContext存储到全局作用域中
				ServletContext sct = sce.getServletContext(); 
				System.out.println(className + "项目名称:" + sct.getInitParameter("MakroProject"));
				String classpath =  this.getClass().getResource("/").getPath();
				System.out.println(className + "classpath:" + classpath);
				String type = "";
				if ( os != null && os.toLowerCase().startsWith(InitConstant.WIN)) { 
					//window操作系统[D:/DevelopInstall/Tomcat/apache-tomcat-7.0.41/webapps/ecommerce-web/WEB-INF/classes/]
					classpath = classpath.replaceFirst("/", "");
					type = InitConstant.WIN;
					System.out.println(className + "[type:" + type +  "]" + "1.操作系统:" +InitConstant.WIN + ",classpath:" + classpath);
				}else if(os != null && os.toLowerCase().startsWith(InitConstant.LINUX)) { 
					//linux操作系统
					type = InitConstant.LINUX;
					System.out.println(className + "[type:" + type +  "]" + "1.操作系统:" +InitConstant.LINUX);
				}else {
					throw new CommonConfigException("当前操作系统既不是:" + InitConstant.WIN +"系统,又不是:" + InitConstant.LINUX + "系统");
				}
				String webAppRoot = classpath.replaceAll("WEB-INF/classes/", "");
				System.out.println(className + "webAppRoot:" + webAppRoot);
				String configPath = webAppRoot + "WEB-INF/properties/init.properties";
				System.out.println(className + "配置文件全路径:" + configPath);
				if (type .equals(InitConstant.WIN)) { //window操作系统
					dubbo_catalina_home = LoadProperties.getProperty(configPath, InitConstant.DUBBO_CATALINA_HOME_WIN, "");
					log_dir = LoadProperties.getProperty(configPath, InitConstant.LOG_DIR_WIN,"");
				}else if(type .equals(InitConstant.LINUX)) { //linux操作系统
					dubbo_catalina_home = LoadProperties.getProperty(configPath, InitConstant.DUBBO_CATALINA_HOME_LINUX, "");
					log_dir = LoadProperties.getProperty(configPath, InitConstant.LOG_DIR_LINUX,"");
				}
				String altMsg = "配置属性文件有误,请检查:";
				String dubbo_registry_application = LoadProperties.getProperty(configPath, InitConstant.DUBBO_REGISTRY_APPLICATION, "");
				if(null == dubbo_registry_application || dubbo_registry_application.equals("")) {
					throw new CommonConfigException(altMsg + "dubbo注册的应用名字");
				}
				String dubbo_registry_address = initPropertiesData.get(InitConstant.DUBBO_REGISTRY_ADDRESS);
				if(null == dubbo_registry_address || dubbo_registry_address.equals("")) {
					throw new CommonConfigException(altMsg + "dubbo注册的地址" + ":为空");
				}
				if(null == dubbo_catalina_home || dubbo_catalina_home.equals("")) {
					throw new CommonConfigException(altMsg + "dubbo缓存文件位置" + ":为空");
				}
				if(null == log_dir || log_dir.equals("")) {
					throw new CommonConfigException(altMsg + "log日志文件位置" + ":为空");
				}
				//*****************1.[设置到系统属性集 ]*************************************************************
				System.out.println(className + "[设置到系统属性集 ]");
				props.setProperty(InitConstant.DUBBO_REGISTRY_APPLICATION, dubbo_registry_application);//dubbo注册的应用名字
				props.setProperty(InitConstant.DUBBO_REGISTRY_ADDRESS,dubbo_registry_address);//dubbo:注册地址
				props.setProperty(InitConstant.DUBBO_CATALINA_HOME, dubbo_catalina_home);//dubbo缓存文件位置
				props.setProperty(InitConstant.LOG_HOME_DIR, log_dir);//log日志文件位置
				//***************2.[设置到ServletContext存储到全局作用域中里面]***************************************************************
				System.out.println(className + "[设置到ServletContext存储到全局作用域中里面]");
				sct.setAttribute(InitConstant.DUBBO_REGISTRY_APPLICATION, dubbo_registry_application);
				sct.setAttribute(InitConstant.DUBBO_REGISTRY_ADDRESS, dubbo_registry_address);
				sct.setAttribute(InitConstant.DUBBO_CATALINA_HOME, dubbo_catalina_home);
				sct.setAttribute(InitConstant.LOG_HOME_DIR, log_dir);
				//***********3.[设置到系统里面]**********************
				System.out.println(className + "[设置到系统里面]");
				System.setProperty(InitConstant.DUBBO_REGISTRY_APPLICATION, dubbo_registry_application);
				System.setProperty(InitConstant.DUBBO_REGISTRY_ADDRESS, dubbo_registry_address);
				System.setProperty(InitConstant.DUBBO_CATALINA_HOME, dubbo_catalina_home);
				System.setProperty(InitConstant.LOG_HOME_DIR, log_dir);
				//******************************************************************************
				System.out.println(className + "dubbo注册的应用名字:" + dubbo_registry_application);
				System.out.println(className + "dubbo注册的地址:" + dubbo_registry_address);
				System.out.println(className + "dubbo缓存文件位置:" + dubbo_catalina_home);
				System.out.println(className + "log日志文件位置:" + log_dir);
			} catch (Exception e) {
				e.printStackTrace();
				throw new RuntimeException(className + e.getMessage());
			}
	    }
}

重写log类

package com.ecommerce.platform.common.log;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
 
import org.apache.log4j.RollingFileAppender;
import org.apache.log4j.helpers.CountingQuietWriter;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.spi.LoggingEvent;
 
/**
 * 继承log4j的RollingFileAppender类  
 * 参考:https://blog.csdn.net/a15123837995/article/details/88388797
 * @author Administrator 2019-10-29 星期二
 *
 */
public class Log4jFile extends RollingFileAppender {
	/**
	 * 格式与log4j.properties中属性:log4j.appender.logFile.File匹配对应
	 * log4j.appender.logFile.File=${log.home.dir}/yyyy/MM/interface.log
	 */
	private static String dateFormate = "yyyy/MM/dd";
	private long nextRollover = 0;
	private static Map<String, BeginFileData> fileMaps = new HashMap<String, BeginFileData>();
	private static final SimpleDateFormat sdf = new SimpleDateFormat(dateFormate);
 
	public void rollOver () {
		File target;
		File file;
		int maxBackupIndexLeng = String.valueOf(maxBackupIndex).length();
		if (qw != null) {
			long size = ((CountingQuietWriter) qw).getCount();
			LogLog.debug("rolling over count = " + size);
			nextRollover = size + maxFileSize;
		}
		LogLog.debug("maxBackupIndex=" + maxBackupIndex);
 
		String nowDateString = sdf.format(new Date());
		String newFileName = ((fileName.indexOf(".") != -1) ? fileName.substring(0,fileName.lastIndexOf(".")) : fileName);
		boolean renameSucceeded = true;
		if (maxBackupIndex > 0) {
			file = new File(newFileName + '.' + nowDateString + '.' + getIndex(maxBackupIndex, maxBackupIndexLeng));
			if (file.exists()) {
				renameSucceeded = file.delete();
			}
			for (int i = maxBackupIndex - 1; (i >= 1 && renameSucceeded); i--) {
				file = new File(newFileName + '.' + nowDateString + '.'+ getIndex(i, maxBackupIndexLeng));
				if (file.exists()) {
					target = new File(newFileName + '.' + nowDateString + '.' + getIndex(i + 1, maxBackupIndexLeng));
					LogLog.debug("Renaming file " + file + " to " + target);
					renameSucceeded = file.renameTo(target);
				}
			}
			if (renameSucceeded) {
				BeginFileData beginFileData = fileMaps.get(fileName);
				System.out.println("fileName= " + fileName + "\tbeginFileData="+ beginFileData);
				// 在每天一个日志目录的方式下,检测日期是否变更了,如果变更了就要把变更后的日志文件拷贝到变更后的日期目录下。
				if (newFileName.indexOf(nowDateString) == -1 && beginFileData.getFileName().indexOf(dateFormate) != -1) {
					newFileName = beginFileData.getFileName().replace(dateFormate,nowDateString);
					newFileName = (newFileName.indexOf(".") != -1 ? newFileName.substring(0, newFileName.lastIndexOf(".")) : newFileName);
				}
				target = new File(newFileName + '.' + nowDateString + '.'+ getIndex(1, maxBackupIndexLeng));
				this.closeFile();
				file = new File(fileName);
				LogLog.debug("Renaming file " + file + " to " + target);
				renameSucceeded = file.renameTo(target);
				if (!renameSucceeded) {
					try {
						this.setFile(fileName, true, bufferedIO, bufferSize);
					} catch (IOException e) {
						LogLog.error("setFile(" + fileName + ", true) call failed.", e);
					}
				}
			}
		}
		//
		// if all renames were successful, then
		//
		if (renameSucceeded) {
			try {
				this.setFile(fileName, false, bufferedIO, bufferSize);
				nextRollover = 0;
			} catch (IOException e) {
				LogLog.error("setFile(" + fileName + ", false) call failed.", e);
			}
		}
	}
 
	/**
	 * 文件个数的长度补零,如果文件个数为10那么文件的个数长度就是2位,第一个文件就是01,02,03....
	 * 
	 * @param i
	 * @param maxBackupIndexLeng
	 * @return
	 */
	private String getIndex (int i, int maxBackupIndexLeng) {
		String index = String.valueOf(i);
		int len = index.length();
		for (int j = len; j < maxBackupIndexLeng; j++) {
			index = "0" + index;
		}
		return index + ".log";
	}
 
	/**
	 * This method differentiates RollingFileAppender from its super class.
	 * 
	 * @since 0.9.0
	 */
	protected void subAppend (LoggingEvent event) {
		super.subAppend(event);
		if (fileName != null && qw != null) {
 
			String nowDate = sdf.format(new Date());
			// 检测日期是否已经变更了,如果变更了就要重创建日期目录
			if (!fileMaps.get(fileName).getDate().equals(nowDate)) {
				rollOver();
				return;
			}
 
			long size = ((CountingQuietWriter) qw).getCount();
			if (size >= maxFileSize && size >= nextRollover) {
				rollOver();
			}
		}
	}
 
	@Override
	public synchronized void setFile (String fileName, boolean append,boolean bufferedIO, int bufferSize) throws IOException {
		String nowDate = sdf.format(new Date());
		// 如果文件路径包含了“yyyy-MM-dd”就是每天一个日志目录的方式记录日志(第一次的时候)
		if (fileName.indexOf(dateFormate) != -1) {
			String beginFileName = fileName;
			fileName = fileName.replace(dateFormate, nowDate);
			fileMaps.put(fileName, new BeginFileData(beginFileName, nowDate));
		}
		BeginFileData beginFileData = fileMaps.get(fileName);
		// 检测日期是否已经变更了,如果变更了就要把原始的字符串给fileName变量,把变更后的日期做为开始日期
		if (!beginFileData.getDate().equals(nowDate)) {
			// 获取出第一次的文件名
			beginFileData.setDate(nowDate);
			fileName = beginFileData.getFileName().replace(dateFormate, nowDate);
			fileMaps.put(fileName, beginFileData);
		}
 
		// D:/data/test/yyyy-MM-dd/test.log 替换yyyy-MM-dd为当前日期。
		File file = new File(fileName);
		File parentFile = file.getParentFile();
		if (!parentFile.exists()) {
			parentFile.mkdirs();
		}
 
		super.setFile(fileName, append, this.bufferedIO, this.bufferSize);
	}
 
	@SuppressWarnings("unused")
	private class BeginFileData {
		private String fileName;
		private String date;
		public BeginFileData (String fileName, String date) {
			super();
			this.fileName = fileName;
			this.date = date;
		}
		public String getFileName () {
			return fileName;
		}
		public void setFileName (String fileName) {
			this.fileName = fileName;
		}
		public String getDate () {
			return date;
		}
		public void setDate (String date) {
			this.date = date;
		}
	}
}

项目结构
在这里插入图片描述


版权声明:本文为yuxueyuanwj原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。