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; } } }项目结构