log4j提供了非常靈活而又強大的日誌功能,java運行庫中的日誌功能反而被忽略了。其實也是挺好用的,最重要的是,用這個的話就不再需要log4j的jar文件。
由於java.util.logging.Logger不會自動加載配置文件,如果想用配置文件控制輸出級別,需要稍微做點工作:
- 使用一個日誌管理類
package logger;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
public class LoggerManager {
private static Map<Class<?>,Logger> loggerCache = new HashMap<Class<?>,Logger>();
// 初始化LogManager
static {
// 讀取配置文件
ClassLoader cl = LoggerManager.class.getClassLoader();
InputStream inputStream = null;
if (cl != null) {
inputStream = cl.getResourceAsStream("log.properties");
} else {
inputStream = ClassLoader
.getSystemResourceAsStream("log.properties");
}
java.util.logging.LogManager logManager = java.util.logging.LogManager
.getLogManager();
if (inputStream == null){
System.err.println("LoggerManager: Log configuration NOT found!");
}else try {
// 重新初始化日誌屬性並重新讀取日誌配置。
logManager.readConfiguration(inputStream);
System.out.println("LoggerManager: Log configuration loaded.");
} catch (Exception e) {
System.err.println(e);
} finally{
try {inputStream.close();}
catch(Exception ex){
ex.printStackTrace();
}
}
}
/**
* 獲取日誌對象
* @param clazz
* @return
*/
public static Logger getLogger(Class<?> clazz) {
Logger logger = loggerCache.get(clazz);
if (logger==null){
logger = Logger.getLogger(clazz.getCanonicalName());
loggerCache.put(clazz, logger);
}
return logger;
}
/**
* 獲取指定Logger的有效Level
* @param logger
* @return
*/
public static Level getEffectiveLevel(Logger logger)
{
Level level = null;
Logger parent = logger;
while (level==null){
if (parent==null)
break;
level = parent.getLevel();
parent = parent.getParent();
}
return level;
}
}
- 然後,這樣使用日誌:
//啓動類,或者最先加載的類用此方法,可以先讀取配置文件,再生成Logger實例
private static Logger logger = LoggerManager.getLogger(DocFillerDemo.class);
//一般的類可以這樣
// private static Logger logger =Logger.getLogger(DocFillerDemo.class.getCanonicalName());
用法舉例:
logger.severe("錯誤信息");
logger.warn("警告信息");
logger.info("一般性信息,例如登錄情況,業務邏輯信息輸出等");
logger.fine("調試信息");
logger.finer("更細的調試信息");
ogger.finest("最細的調試信息");
- 另外需要注意的問題是配置文件
log.properties:
#Levels: SEVERE, WARNING ,INFO,CONFIG,FINE ,FINER,FINEST
#Global level
#LOGGER.level=FINEST
.level=INFO
# Example to customize the SimpleFormatter output format
# to print one-line log message like this:
# <level>: <log message> [<date/time>]
#
#java.util.logging.SimpleFormatter.format="%4$s: %3$s %5$s [%1$tc] %n"
# handlers= java.util.logging.ConsoleHandler,java.util.logging.FileHandler
handlers= java.util.logging.ConsoleHandler
#set default level for ConsoleHandler
java.util.logging.ConsoleHandler.level=ALL
# set formatter
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.FileHandler.level=INFO
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
# lof file size limit
java.util.logging.FileHandler.limit=1024000
# log file roll over count
java.util.logging.FileHandler.count=3
# log file name pattern,default: "%h/java%u.log"
java.util.logging.FileHandler.pattern=C:/SSLog%u.log
#
java.util.logging.FileHandler.append=true
############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################
#set level of com.ordinov.
#mandatory if logger got by: logger = Logger.getLogger(DocDataBySqlDAO.class.getCanonicalName());
com.ordinov.level=ALL
這個文件可以放在當前目錄,classpath目錄(LoggerManager能讀到)。
尤其注意其中幾個leve的設置:
.level=INFO
這是全局默認設置,所有的logger實例的默認值;
com.xxx.level=FINE
設置某一級別的默認值。這個設置覆蓋全局設置,並且可以被更細的級別繼承。也就是說,如果沒有別的設置,com.xxx.aaa 的有效level就是 com.xxx.level的值了;
如果設置了 com.xxx.bbb=FINER,那麼這個設置會影響com.xxx.bbb包以及子包的level。
另外不可忽略的是handler設置:
handlers= java.util.logging.ConsoleHandler
這一行確保所有級別的日誌可以在控制檯輸出
java.util.logging.ConsoleHandler.level=ALL
這一行確保控制檯會輸出所有級別。如果ConsoleHandler.level設置爲INFO,那麼即使com.xxx.level=FINE,屬於這個包的logger的fine級別信息也不會被輸出到控制檯。
當然,還可以加入FileHandler,同時輸出到控制檯和文件,並分別控制輸出級別。本文不做討論,請自行搜索。