1.基本日志
要生成简单的日志记录,可以使用全局日志记录器(global logger)并调用其info方法:
Logger.getGlobal().info("File->Open menu item selected");
在默认情况下,这条记录会显示以下内容
May 10,2019 10:12:15 PM LoggingImageViewer fileOpen
INFO: File->Open menu item selected
但是,如果在适当的地方(如main开始)调用
Logger.getGlobal().setLevel(Level.OFF);
将会取消所有日志
2.高级日志
在一个专业的应用程序中,不要将所有的日志都记录到一个全局日志记录器中,而是可以自定义日志记录器。
可以调用getLogger方法创建或获取记录器:
private static final Logger myLogger=Logger.getLogger("com.mycompany.myapp");
与包名类似,日志记录器也具有层次结构。事实上,与包名相比,日志记录器的层次性更强。对包来说,一个包的名字与其父包的名字之间没有语义关系,但是日志记录器的父与子之间将共享某些属性。例如,如果对com.mycompany日志记录器设置了日志级别,它的子记录器也会继承这个级别。
通常,有以下七个日志记录器级别:
在默认情况下,只记录前三个级别。也可以设置其他的级别,例如,
logger.setLevel(Level.FINE);
现在,FINE和更高级别的记录都可以记录下来。
还可以使用Level.ALL开启所有级别的记录,或者使用Level.OFF关闭所有级别的记录。
对于所有的级别有下面几种记录方法:
logger.warning(message);
logger.fine(message);
同时。还可以使用log方法指定级别,例如:
logger.log(Level.FINE,message);
默认的日志记录将显示包含日志调用的类名和方法名,如同堆栈所显示的那样。但是如果虚拟机对执行过程进行优化,就得不到准确的调用信息。此时可以调用logp方法获得调用类和方法的确切位置,这个方法的签名为:
void logp(Level l,String className,String methodName, String message)
下面有一些用来跟踪执行流的方法:
void entering(String className,String methodName)
void entering(String className,String methodName,Object parm)
void entering(String calssName,String methodName,Object[] params)
void exiting(String className,String methodName)
void exiting(String className,String methodName,Object result)
例如:
int read(String file,String pattern)
{
logger.entering("com.mycompany.mylib.Reader","read",new Object[]{file,pattern});
.......
logger.exiting("com.mycompany.mylib.Reader","read",count);
return count;
}
这些调用将生成FINER级别和以字符串ENTRY和RETURN开始的日志记录。
记录日志的常见用途是记录哪些不可预料的异常。可以使用下面两个方法提供日志记录中包含的异常描述内容。
void throwing(String className,String methodName,Throwable t)
void log(Level l,String message,Throwable t)
典型的用法:
if(..)
{
IOException exception=new IOException("...");
logger.throwing("com.mycompany.mylib.Reader","read",exception);
throw exception;
}
还有
try
{
.......
}
catch(IOException e)
{
Logger.getLogger("com.mycompany.myapp").log(Level.WARNING,"Reading image",e);
}
调用throwing可以记录一条FINER级别的记录和一条以THROW开始的信息。
记录日志的常见用途是记录那些不可预料的异常。使用下面两个方法提供日志记录中包含的异常描述内容。
void throwing(String className, String methodName,Throwable t)
void log(Level l,String message,Throwable t)
典型用法:
if(...)
{
IOException exception= new IOException("......");
logger.throwing("com.mycompany.mylib.Reader","read",exception);
throw exception;
}
还有
try
{
.......
}
catch(IOException e)
{
Logger.getLogger("com.mycompany.myapp").log(Level.WARNING,"Reading imagr", e);
}
3.修改日志管理器配置
可以通过编辑配置文件来修改日志系统的各种属性。默认情况,配置文件在:
jre/lib/logging.properties
要想使用另一个配置文件,就要将java.util.logging.config.file特性设置为配置文件的存储位置,并用下列命令启动应用程序:
java -Djava.util.logging.config.file=configFile MainClass
修改默认的日志记录级别,需要编辑配置文件,并修改一下命令行:
.level=INFO
可以通过添加以下内容来指定自己的日志记录级别:
com.company.myapp.level=FINE
即在日志记录器名后面加后缀.level
日志记录并不将消息发送到控制台上,这是处理器的任务。另外,处理器也有级别。要想在控制台上看到FINE级别的消息,就需要进行下列设置:
java.util.logging.ConsoleHandler.level=FINE
4.本地化
我们尽可能希望将日志消息本地化,以便让全球用户都可以阅读它。
本地化的应用程序包含资源包(resource bundle)中的本地特定信息。资源包由各个地区(如美国或德国)的映射集合组成。例如某个资源包可能将字符串“readingFile”映射成英文的“Reading File”或者德文的。
一个程序可以包含多个资源包,一个用于菜单;其他用于日志消息。每个资源包都有一个名字(如com.mycompany.logmessage)要想将映射添加到一个资源包中,需要为每个地区创建一个文件。英文消息映射位于com/mycompany/logmessage_en.properties文件中。可以将这些文件与应用程序的类文件放在一起,以便ResourceBundle类自动地对它们进行定位。这些文件都是纯文本文件,其组成:
readingFile=Achtung! Datei wird eingelesen
renamingFile=Datei wird umbenannt
在请求日志记录器时,可以指定一个资源包:
Logger logger=Logger.getLogger(loggerName,"com.mycompany.logmessages");
然后,为日志消息指定资源包的关键字,而不是实际的日志消息字符串
logger.info("redingFile");
通常需要在本地化的消息中增加一些参数,因此,消息应该包括占位符{0},、{1}等。例如,要想在日志消息中包含文件名,就应该用下列方式包括占位符:
Reading file{0}.
Achtung! Datet {0} wird eingelesen.
然后通过调用下面的一个方法向占位符传递具体的值:
logger.log(Level.INFO,"readingFile",fileName);
logger.log(Level.INFO,"readingFile",new Object[] {oldName,newName});
处理器
在默认情况下,日志记录器将记录发送到ConsoleHandler中,并由他输出到System.err流中。特别是,日志记录器还会将记录发送到父处理器中,而最终的处理器(命名为"")有一个ConsoleHandler。