原文转自:https://i-blog.csdnimg.cn/blog_migrate/a7a22fb0ed31e78f6e1d058afec0f6b7.png,只做收藏用。
由于项目需要根据日志来跟踪了解系统信息,方便查看传输数据以及异常信息,所以打算用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.日志文件中的异常打印信息