一、log4j配置文件
#定义LOG输出级别
log4j.rootLogger=INFO,alog,blog
#自定义log
log4j.logger.secondLogger=INFO,clog
log4j.additivity.secondLogger=false #info级别的alog,clog写入不同的文件
#alog的配置
log4j.appender.alog=com.MyDailyRollingFileAppender(该类继承于 org.apache.log4j.DailyRollingFileAppender,该类代表每天都会生成新文件 )
log4j.appender.alog.DatePattern='.'yyyy-MM-dd
log4j.appender.alog.File=logs/alog.log(绝对路径或相对路径)
#Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容。
log4j.appender.alog.Append=true
log4j.appender.alog.Threshold=INFO (该log对应的级别)
log4j.appender.alog.layout=org.apache.log4j.PatternLayout
log4j.appender.alog.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH\:mm\:ss}]%m%n
#blog的配置
log4j.appender.blog=com.MyDailyRollingFileAppender
log4j.appender.blog.DatePattern='.'yyyy-MM-dd (每日都会生成一个新文件,旧文件就会加上.yyyy-MM-dd格式的后缀)
log4j.appender.blog.File=logs/blog.log (文件保存路径)
log4j.appender.blog.Append=true
log4j.appender.blog.Threshold=ERROR
log4j.appender.blog.layout=org.apache.log4j.PatternLayout
log4j.appender.blog.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH\:mm\:ss}]%m%n (输出为[INFO][2019-12-31 23:23:23] (自定义字符串) (换行))
log4j.appender.clog=com.MyDailyRollingFileAppender
log4j.appender.clog.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.clog.File=logs/clog .log
log4j.appender.clog.Append=true
log4j.appender.clog.Threshold=INFO
log4j.appender.clog.layout=org.apache.log4j.PatternLayout
log4j.appender.clog.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH\:mm\:ss}]%m%n
配置文件详解:
1、DatePattern属性:
可选值有6个:
'.'yyyy-MM,对应monthly(每月)
*'.'yyyy-ww,对应weekly(每周)
'.'yyyy-MM-dd,对应daily(每天)
'.'yyyy-MM-dd-a,对应half-daily(每半天)
'.'yyyy-MM-dd-HH,对应hourly(每小时)
'.'yyyy-MM-dd-HH-mm,对应minutely(每分钟)
ps:
1、不需要处理的字符要加单引号,如上面可选值中的'.'
2、ConversionPattern属性:
-X号: X信息输出时左对齐
%p: 输出日志信息优先级,即DEBUG
%d: 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
%r: 输出自应用启动到输出该log信息耗费的毫秒数
%c: 输出日志信息所属的类目,通常就是所在类的全名
%t: 输出产生该日志事件的线程名
%l: 输出日志事件的发生位置,相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程,以及在代码中的行数
%x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
%%: 输出一个"%"字符
%F: 输出日志消息产生时所在的文件名称
%L: 输出代码中的行号
%m: 输出代码中指定的消息,产生的日志具体信息
%n: 输出一个回车换行符,Windows平台为"\r\n",Unix平台为"\n"
3、MyDailyRollingFileAppender:
默认的log4j 打印日志输出的文件中低级别会包含高级别日志,比如定义了输出级别为info,则日志文件中会包含了:info以及比info高级别的warn,error等信息,造成文件的冗余,DailyRollingFileAppender继承log4j的原始类,重写isAsSevereAsThreshold方法 只判断级别是否相等,不判断优先级
代码如下:
public class MyDailyRollingFileAppender extends DailyRollingFileAppender {
static {
/*这里要注意,项目运行起来后,会自动加载src下面的log4j.properties配置文件,不需要在代码里手动引入,否则日志信息会重复打印两遍,如果文件名不是log4j.properties,则需要手动指定配置文件路径*/
//PropertyConfigurator.configure("log4j.properties");// :读取使用Java的特性文件编写的配置文件。
}
public boolean isAsSevereAsThreshold(Priority priority) { return this.getThreshold().equals(priority); }
public static boolean DEBUG = true;
public static boolean DEBUG_LESSER = true;
private static Logger logger = Logger.getLogger(LogUtils.class);
private static final String tag = "netty ";
private static SimpleDateFormat sdf = new SimpleDateFormat("MM/dd HH:mm:ss", Locale.getDefault());
//5个打印级别
public static void logDebug(String str) { if (DEBUG) logger.debug(tag + "#T#" + sdf.format(new Date()) + "$T$ #M#" +str + "$M$"); }
public static void logInfo(String str) { if (DEBUG) logger.info(tag + "#T#" + sdf.format(new Date()) + "$T$ #M#" +str + "$M$"); }
public static void logWarn(String str) { if (DEBUG) logger.warn(tag + "#T#" + sdf.format(new Date()) + "$T$ #M#" +str + "$M$"); }
public static void logError(String str) { if (DEBUG) logger.error(tag + "#T#" + sdf.format(new Date()) + "$T$ #M#" +str + "$M$"); }
public static void logFatal(String str) { if (DEBUG) logger.fatal(tag + "#T#" + sdf.format(new Date()) + "$T$ #M#" +str + "$M$"); }
}
二、web.xml中配置log4j:
log4jConfigLocation
classpath:log4j.properties
org.springframework.web.util.Log4jConfigListener
三、编写LogUtils类:
public class LogUtils{
private static Logger logger;
private static LogUtils instance;
private static Logger secondLogger;
private LogUtils(){}
public static LogUtils getInstance(){
if (instance == null){ instance = new LogUtils(); }
if (logger == null){ logger = Logger.getLogger(LogUtils.class); }
if (secondLogger == null){ secondLogger = Logger.getLogger("secondLogger");}
return instance;
}
public void logA(){
logger.info("info A");
}
public void logB(){
logger.error("error B");
}
public void logV(){secondLogger .error("error C");}
public static void main(String[] args) {
LogUtils.getInstance().logA(); //C与A一个级别,但时分别写入A和C两个文件,并且不重复写入
LogUtils.getInstance().logB();
LogUtils.getInstance().logC();
}
}