由于项目需要根据日志来跟踪了解系统信息,方便查看传输数据以及异常信息,所以打算用log4j来完成这个日志管理的功能。
可惜的是,在使用中发现log4j在打印异常信息时,并不能像控制台那样详细打印出跟踪栈StackTrace内的信息到配置文件指定的日志文件中去。
可能是我能力有限,网上查了很多资料,尝试了很多办法都不行。
后来发现Java API 自带的日志管理java.util.logging.Logger好像可以满足要求,于是尝试了一下,结果如愿以偿,深感欣慰啊。
关于怎么使用Java自带的日志管理,相信网上有很多例子,我就不重复说了。
在这里我只想说一下,在加载配置文件路径时,如果路径不存在,日志管理类LogManager不会主动创建不存在的目录,而是报异常如下:
Can't load log handler "java.util.logging.FileHandler"
java.io.IOException: Couldn't get lock for C:/iMessengerLogs/log%g.log
java.io.IOException: Couldn't get lock for C:/iMessengerLogs/log%g.log
at java.util.logging.FileHandler.openFiles(Unknown Source)
at java.util.logging.FileHandler.<init>(Unknown Source)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.lang.Class.newInstance0(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at java.util.logging.LogManager$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.util.logging.LogManager.loadLoggerHandlers(Unknown Source)
at java.util.logging.LogManager.initializeGlobalHandlers(Unknown Source)
at java.util.logging.LogManager.access$1100(Unknown Source)
at java.util.logging.LogManager$RootLogger.getHandlers(Unknown Source)
at java.util.logging.Logger.log(Unknown Source)
at java.util.logging.Logger.doLog(Unknown Source)
at java.util.logging.Logger.log(Unknown Source)
at java.util.logging.Logger.info(Unknown Source)
at com.log.LoggerTest.main(LoggerTest.java:13)
所以,在加载配置之前必须先读取配置文件中日志文件的目录,判断目录是否存在,如果不存在,则创建目录。
源码如下:
1.MyLogManager.java 日志管理(读取配置文件,创建目录,加载配置文件,获取日志对象)
package com.log;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.logging.LogManager;
import java.util.logging.Logger;
/**
* 日志管理
*
* @author
*
*/
public class MyLogManager {
private static Logger logger;
static {
InputStream is1 = null;
InputStream is2 = null;
try {
// 读取配置文件,创建相应的文件目录
String logFilePath = "";
is1 = new FileInputStream(
"D:\\workspace\\log\\src\\com\\log\\log.properties");
Properties properties = new Properties();
properties.load(is1);
String pattern = properties
.getProperty("java.util.logging.FileHandler.pattern");
logFilePath = pattern.substring(0, pattern.lastIndexOf("/"));
File file = new File(logFilePath);
if (!file.exists()) {
file.mkdirs();
}
// 重新初始化日志属性并重新读取日志配置
is2 = new FileInputStream(
"D:\\workspace\\log\\src\\com\\log\\log.properties");
LogManager logManager = LogManager.getLogManager();
logManager.readConfiguration(is2);
} catch (SecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is1.close();
is2.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 获取日志对象
*
* @param clazz
* @return
*/
public static Logger getLogger(Class<?> clazz) {
logger = Logger.getLogger(clazz.getName());
return logger;
}
}
2.log.properties配置文件(带详细注释)
#Level的五个等级SEVERE(最高值) 、WARNING 、INFO 、CONFIG 、FINE 、FINER 、FINEST(最低值)
#为 Handler 指定默认的级别(默认为 Level.INFO)。
java.util.logging.ConsoleHandler.level=INFO
# 指定要使用的 Formatter 类的名称(默认为 java.util.logging.SimpleFormatter)。
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
# 为 Handler 指定默认的级别(默认为 Level.ALL)
java.util.logging.FileHandler.level=INFO
# 指定要使用的 Formatter 类的名称(默认为 java.util.logging.XMLFormatter)
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
# 指定要写入到任意文件的近似最大量(以字节为单位),如果该数为0,则没有限制(默认为无限制)
java.util.logging.FileHandler.limit=20480
# 指定有多少输出文件参与循环(默认为 1)。
java.util.logging.FileHandler.count=10
# 为生成的输出文件名称指定一个模式。有关细节请参见以下内容(默认为 "%h/java%u.log")
# "/" 本地路径名分隔符
# "%t" 系统临时目录
# "%h" "user.home"系统属性的值
# "%g" 区分循环日志的生成号
# "%u" 解决冲突的惟一号码
# "%%" 转换为单个百分数符号"%"
# 如果未指定 "%g"字段,并且文件计数大于 1,那么生成号将被添加到所生成文件名末尾的小数点后面
java.util.logging.FileHandler.pattern=C:/testLogs/log%g.log
# 指定是否应该将 FileHandler 追加到任何现有文件上(默认为 false)
java.util.logging.FileHandler.append=true
# 指定handler
handlers=java.util.logging.ConsoleHandler,java.util.logging.FileHandler
3.LoggerTest.java日志测试类
package com.log;
import java.io.FileInputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
public class LoggerTest {
private static Logger logger = MyLogManager.getLogger(LoggerTest.class);
public static void main(String[] args) {
try {
logger.info("打印信息");
//不存在的路径
String filePath = "C:\\workspace\\log\\src\\com\\log\\log.properties";
/**
* 会抛出异常:
* java.io.FileNotFoundException: C:\workspace\log\src\com\log\log.properties (系统找不到指定的路径。)
*/
new FileInputStream(filePath);
} catch (Exception e) {
logger.log(Level.SEVERE, e.getMessage(), e);
}
}
}
4.日志文件中的异常打印信息