jdk中的logging

java.util.logging

java.util.logging.Logger不是什么新鲜东西了,1.4就有了,可是因为log4j的存在,这个logger一直沉默着,其实在一些测试性的代码中,jdk自带的logger比log4j更方便。

一、创建Logger对象

static Logger getLogger(String name)
为指定子系统查找或创建一个 logger。
static Logger getLogger(String name, String resourceBundleName)
为指定子系统查找或创建一个 logger。注意:name是Logger的名称,当名称相同时候,同一个名称的Logger只创建一个。

二、Logger的级别?比log4j的级别详细,全部定义在java.util.logging.Level里面。各级别按降序排列如下:

  • SEVERE(最高值)
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST(最低值)

此外,还有一个级别 OFF,可用来关闭日志记录,使用级别 ALL 启用所有消息的日志记录。?logger默认的级别是INFO,比INFO更低的日志将不显示。Logger的默认级别定义是在jre安装目录的lib下面。# Limit the message that are printed on the console to INFO and above.
java.util.logging.ConsoleHandler.level = INFO?

三、简单实例?public class TestLogger {
public static void main(String[] args) {
Logger log = Logger.getLogger("lavasoft");
log.setLevel(Level.INFO);
Logger log1 = Logger.getLogger("lavasoft");
System.out.println(log==log1);???? //true
Logger log2 = Logger.getLogger("lavasoft.blog");
log2.setLevel(Level.WARNING); log.info("aaa");
log2.info("bbb");
log2.fine("fine"); }?true
2009-7-28 20:00:30 TestLogger main
信息: aaa Process finished with exit code 0?当注释掉??????? log2.setLevel(Level.WARNING);
输出结果:true
2009-7-28 20:02:02 TestLogger main
信息: aaa
2009-7-28 20:02:02 TestLogger main
信息: bbb Process finished with exit code 0?从这里可以看出,logger的名字是有层级关系的。这和log4j的控制方式完全一致。?下面是API文档的原文:一般使用圆点分隔的层次命名空间来命名 Logger。Logger 名称可以是任意的字符串,但是它们一般应该基于被记录组件的包名或类名,如 java.net 或 javax.swing。此外,可以创建“匿名”的 Logger,其名称未存储在 Logger 命名空间中。 可通过调用某个 getLogger 工厂方法来获得 Logger 对象。这些方法要么创建一个新 Logger,要么返回一个合适的现有 Logger。?

四、Logger的Handler?Handler 对象从 Logger 中获取日志信息,并将这些信息导出。例如,它可将这些信息写入控制台或文件中,也可以将这些信息发送到网络日志服务中,或将其转发到操作系统日志中。
可通过执行 setLevel(Level.OFF) 来禁用 Handler,并可通过执行适当级别的 setLevel 来重新启用。
Handler 类通常使用 LogManager 属性来设置 Handler 的 Filter、Formatter 和 Level 的默认值。java.util.logging.Handler
java.util.logging.MemoryHandler
java.util.logging.StreamHandler
java.util.logging.ConsoleHandler
java.util.logging.FileHandler
java.util.logging.SocketHandler?例子:public class TestLogger {
public static void main(String[] args) throws IOException {
Logger log = Logger.getLogger("lavasoft");
log.setLevel(Level.INFO);
Logger log1 = Logger.getLogger("lavasoft");
System.out.println(log==log1);???? //true
Logger log2 = Logger.getLogger("lavasoft.blog");
//????????????????log2.setLevel(Level.WARNING); ConsoleHandler consoleHandler =new ConsoleHandler();
consoleHandler.setLevel(Level.ALL);
log.addHandler(consoleHandler);
FileHandler fileHandler = new FileHandler("C:/testlog%g.log");
fileHandler.setLevel(Level.INFO);
log.addHandler(fileHandler);
log.info("aaa");
log2.info("bbb");
log2.fine("fine"); }?输出结果:true
2009-7-28 20:36:14 TestLogger main
信息: aaa
2009-7-28 20:36:14 TestLogger main
信息: aaa
2009-7-28 20:36:14 TestLogger main
信息: bbb
2009-7-28 20:36:14 TestLogger main
信息: bbb Process finished with exit code 0?查看C盘:?可见,默认的日志方式是xml格式,很烂。所以最好自定义下logger的格式。需要用Formatter来定义。?

五、Logger的Formatter?Formatter 为格式化 LogRecords 提供支持。
一般来说,每个日志记录 Handler 都有关联的 Formatter。Formatter 接受 LogRecord,并将它转换为一个字符串。
有些 formatter(如 XMLFormatter)需要围绕一组格式化记录来包装头部和尾部字符串。可以使用 getHeader 和 getTail 方法来获得这些字符串。?LogRecord 对象用于在日志框架和单个日志 Handler 之间传递日志请求。
LogRecord(Level level, String msg)
用给定级别和消息值构造 LogRecord。?java.util.logging.Formatter
java.util.logging.SimpleFormatter
java.util.logging.XMLFormatter?看个例子就明白了:public class TestLogger {
public static void main(String[] args) throws IOException {
Logger log = Logger.getLogger("lavasoft");
log.setLevel(Level.INFO);
Logger log1 = Logger.getLogger("lavasoft");
System.out.println(log == log1);???? //true
Logger log2 = Logger.getLogger("lavasoft.blog");
//????????????????log2.setLevel(Level.WARNING); ConsoleHandler consoleHandler = new ConsoleHandler();
consoleHandler.setLevel(Level.ALL);
log.addHandler(consoleHandler);
FileHandler fileHandler = new FileHandler("C:/testlog%g.log");
fileHandler.setLevel(Level.INFO);
fileHandler.setFormatter(new MyLogHander());
log.addHandler(fileHandler); log.info("aaa");
log2.info("bbb");
log2.fine("fine"); } class MyLogHander extends Formatter {
@Override
public String format(LogRecord record) {
return record.getLevel() + ":" + record.getMessage()+"\n"; }?输出:在控制和C盘输出的文件如图?到此,Java自带的Logger内容就没了。感觉格式很不爽。自定义的XML格式很烂。

实例:

一、创建Logger对象

要使用J2SE的日志功能,首先要取得java.util.logging.Logger实例,这可以通过Logger类的两个静态getLogger()方法来取得:

static Logger getLogger(String name)
         查找或创建一个logger。
static Logger getLogger(String name, String resourceBundleName)
         为指定子系统查找或创建一个logger。

注意:name是Logger的名称,当名称相同时候,同一个名称的Logger只创建一个。

下面是简单范例:

import java.util.logging.*;

public class LoggingDemo {

public static void main(String[] args) {

        Logger logger = Logger.getLogger("!LoggingDemo");

        try {

            System.out.println(args![0]);

        }

        catch(!ArrayIndexOutOfBoundsException e) {

            logger.warning("没有提供执行时的自变量!");

        }                

    }

}

执行结果:

2009-4-7 15:41:43 pku.sei.LoggingDemo main
警告:没有提供执行时的自变量!

二、日志级别

在进行信息的记录时,依信息程序的不同,会设定不同等级的信息输出。Java log比log4j的级别详细,全部定义在java.util.logging.Level里面。

各级别按降序排列如下:

  • SEVERE(最高值)
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST(最低值)

此外,还有一个级别OFF,可用来关闭日志记录,使用级别ALL启用所有消息的日志记录。

logger默认的级别是INFO,比INFO更低的日志将不显示。

Logger的默认级别定义是在jre安装目录的lib下面。

# Limit the message that are printed on the console to INFO and above.
java.util.logging.ConsoleHandler.level = INFO

可以通过操作Logger上的几个方法来得到不同等级的信息输出。如下列范例:

import java.util.logging.*;

[ public class LoggingLevelDemo]

{

         public static void main(String[] args)

         {

                   Logger logger = Logger.getLogger("loggingLevelDemo");

                   logger.severe("严重信息");

                   logger.warning("警示信息");

                   logger.info("一般信息");

                   logger.config("设定方面的信息");

                   logger.fine("细微的信息");

                   logger.finer("更细微的信息");

                   logger.finest("最细微的信息");

         }

}

输出:

2009-4-7 15:50:43 pku.sei.LoggingLevelDemo main
严重:严重信息
2009-4-7 15:50:43 pku.sei.LoggingLevelDemo main
警告:警示信息
2009-4-7 15:50:43 pku.sei.LoggingLevelDemo main
信息:一般信息

此示例中config()方法及以下的信息并没有显示出来,这是因为Logger的默认等级是INFO,比这个等级更低的信息,Logger并不会将信息输出。

Logger的默认等级是定义在执行环境的属性文件logging.properties中,这个文件位于JRE安装目录的lib目录下。部分内容如下:

handlers = java.util.logging.ConsoleHandler

java.util.logging.ConsoleHandler.level = INFO

Logger默认的输出媒介控制器(Handler)是java.util.logging.ConsolerHandler,也就是将信息输出至控制台。一个Logger可以拥有多个handler,每个handler可以有自己的日志级别,在通过Logger的级别限制后,实际上还要再经过handler的级别限制。所以在上面的范例中如果想要看到所有的信息,则必须同时设定Logger与!ConsoleHandler的级别。下面的范例示范了如何设定:

import java.util.logging.*;

public class LoggingLevelDemo2

{

         public static void main(String[] args)

         {

                   Logger logger = Logger.getLogger("loggingLevelDemo2");

                   //显示所有等级的信息

                   logger.setLevel(Level.ALL);

                   !ConsoleHandler consoleHandler = new !ConsoleHandler();

                   //显示所有等级的信息

                   consoleHandler.setLevel(Level.ALL);

                   //设定Handler为!ConsoleHandler

                   logger.addHandler(consoleHandler);

                   logger.severe("严重信息");

                   logger.warning("警示信息");

                   logger.info("一般信息");

                   logger.config("设定方面的信息");

                   logger.fine("细微的信息");

                   logger.finer("更细微的信息");

                   logger.finest("最细微的信息");

         }

}

运行结果:

2009-4-7 16:02:10 pku.sei.!LoggingLevelDemo2 main
严重:严重信息
2009-4-7 16:02:10 pku.sei.!LoggingLevelDemo2 main
严重:严重信息
2009-4-7 16:02:10 pku.sei.!LoggingLevelDemo2 main
警告:警示信息
2009-4-7 16:02:10 pku.sei.!LoggingLevelDemo2 main
警告:警示信息
2009-4-7 16:02:10 pku.sei.!LoggingLevelDemo2 main
信息:一般信息
2009-4-7 16:02:10 pku.sei.!LoggingLevelDemo2 main
信息:一般信息
2009-4-7 16:02:10 pku.sei.!LoggingLevelDemo2 main
配置:设定方面的信息
2009-4-7 16:02:10 pku.sei.!LoggingLevelDemo2 main
良好:细微的信息
2009-4-7 16:02:10 pku.sei.!LoggingLevelDemo2 main
较好:更细微的信息
2009-4-7 16:02:10 pku.sei.!LoggingLevelDemo2 main
最好:最细微的信息

Level.ALL表示显示所有的信息,所有这一次的执行结果可显示所有等级的信息。如果要关闭所有的信息,可以设定为Level.OFF。

Logger的Severe(),warning(),info()等方法,实际上是个便捷的方法。也可以直接使用log()方法并指定等级来执行相同的作用,如:

logger.log(Level.SEVERE, "严重信息");

三、Handler

Handler对象从Logger中获取日志信息,并将这些信息导出。例如,它可将这些信息写入控制台或文件中,也可以将这些信息发送到网络日志服务中,或将其转发到操作系统日志中。

Logger默认的输出处理者是ConsoleHandler。!ConsoleHandler的输出是使用System.err对象,而信息的默认等级是INFO,这可以在JRE安装目录下lib目录的logging.properties中看到:

handlers = java.util.logging.ConsoleHandler

java.util.logging.ConsoleHandler.level = INFO

Java SE实现了5个Handler:

(1) java.util.logging.ConsoleHandler 以System.err输出日志。

(2) java.util.logging.FileHandler 将信息输出到文件。

(3) java.util.logging.!StreamHandler以指定的!OutputStream实例输出日志。

(4) java.util.logging.!SocketHandler将信息通过Socket传送至远程主机。

(5) java.util.logging.!MemoryHandler将信息暂存在内存中。

以下代码将信息输出至文件中:

import java.io.IOException;

import java.util.logging.*;

public class HandlerDemo

{

         public static void main(String[] args)

         {

                   Logger logger = Logger.getLogger("handlerDemo");

                   try

                   {

                            !FileHandler fileHandler =

                                     new FileHandler("%h/myLogger.log");

                            logger.addHandler(fileHandler);

                            logger.info("测试信息");

                   }

                   catch (!SecurityException e)

                   {

                            e.printStackTrace();

                   }

                   catch (IOException e)

                   {

                            e.printStackTrace();

                   }

         }

}

执行的结果会在命令行模式显示信息,并将结果输出至文件中。%h表示使用者的根目录(c:\document and settings\hexinyu目录中)。%t可以取得系统的暂存目录,%g自动为文件编号。例如可以设定为%h/myLogger%g.log,表示将.log文件存储在使用者根目录中,并自动为每个文件增加编号。此范例输出的文件内容如下:

<?xml version="1.0" encoding="GBK" standalone="no"?>

<!DOCTYPE log SYSTEM "logger.dtd">

<log>

<record>

  <date>2009-04-07!T16:31:02</date>

  <millis>1239093062781</millis>

  <sequence>0</sequence>

  <logger>handlerDemo</logger>

  <level>INFO</level>

  <class>pku.sei.!HandlerDemo</class>

  <method>main</method>

  <thread>10</thread>

  <message>测试信息</message>

</record>

</log>

fileHandler默认的输出格式是XML格式。输出格式由java.util.logging.Formatter来控制,下一节详细介绍Formatter。

四、Formatter

Formatter为格式化!LogRecords提供支持。
一般来说,每个Handler都有关联的Formatter。Formatter接受LogRecord,并将它转换为一个字符串。

默认提供了两种Formatter:
java.util.logging.SimpleFormatter:标准日志格式,就是我们通常在启动一些诸如 Tomcat JBoss之类的服务器的时候经常能在控制台下看到的那种形式,就像这样:


2004-12-20 23:08:52 org.apache.coyote.http11.Http11Protocol init
信息: Initializing Coyote HTTP/1.1 on http-8080

java.util.logging.XMLFormatter:XML形式的日志格式,如果为Logger添加了一个new XMLFormatter(),那么就会以XML形式输出,不过更常用的是使用上面介绍的!FileHandler输出到XML文件中。

从上一节的例子可知,!FileHandler的默认格式是java.util.logging.XMLFormatter,而!ConsolerHandler的默认格式是java.util.logging.SimpleFormatter,可以使用Handler实例的setFormatter()方法来设定信息的输出格式。例如:

fileHandler.setFormatter(new SimpleFormatter());

!FileHandler的Formatter设定为SimpleFormatter,则输出的日志文件内容就是简单的文字信息,打开文件后会发现与命令行模式下看到的信息内容相同。

五、自定义

1、Handler

用户可以定制自己输出媒介控制器,继承Handler即可,通常只需要实现Handler中三个未定义的抽象方法:

publish:主要方法,把日志记录写入你需要的媒介。

flush:清除缓冲区并保存数据。

close:关闭控制器。


通过重写以上三个方法可以很容易实现一个新的输出媒介控制器。

2、Formatter

除了XMLFormatter与!SimpleFormatter之外,也可以自定义日志的输出格式,只要继承抽象类Formatter,并重新定义其format()方法即可。format()方法会传入一个java.util.logging.!LogRecord对象作为参数,可以使用它来取得一些与程序执行有关的信息。'

3、日志级别

Java的一个日志级别对应一个整数值,Level有9个内置的级别,分别是:

类型          对应的整数
OFF         最大整数( Integer. MAX_VALUE
SEVERE     1000
WARNING   900
INFO         800
CONFIG      700
FINE          500
FINER        400
FINEST      300
ALL           最小整数(Integer. MIN_VALUE


    你也可以定义自己的日志级别,通过继承Level的方式,譬如:

classAlertLevel extends java.util.logging.Level
{
  public AlertLevel()
  {
    super("ALERT", 950);
  }
}
...
Logger logger = Logger.getAnonymousLogger();
logger.log(new AlertLevel(), "A dangerous action!");


    上面定义了一个高于WARNING但低于SEVERE的日志级别。

六、Logger的层次关系

在使用Logger的静态getLogger()方法取得Logger实例时,给getLogger()方法的名称是有意义的。如果给定pku,实际上将从根(Root)logger继承一些特性,像日志级别(Level)以及根logger的输出媒介控制器。如果再取得一个Logger实例,并给定名称pku.sei,则这次取得的Logger将继承pku这个Logger上的特性。从以下范例可以看出Logger在名称上的继承关系:

import java.util.logging.*;

public class LoggerHierarchyDemo

{

         public static void main(String[] args)

         {

                   Logger onlyfunLogger = Logger.getLogger("ysu");

                   Logger caterpillarLogger = Logger.getLogger("ysu.hxy");

                   System.out.println("root logger:"+onlyfunLogger.getParent());

                   System.out.println("onlyfun logger:" + caterpillarLogger.getParent().getName());

                   System.out.println("caterpillar !Logger:" + caterpillarLogger.getName() + "\n");

                   onlyfunLogger.setLevel(Level.WARNING);

                   caterpillarLogger.info("caterpillar ' info");

                   caterpillarLogger.setLevel(Level.INFO);

                   caterpillarLogger.info("caterpillar ' info");

         }

}

getParent()方法可以取得Logger上的上层父Logger,根Logger并没有名称,所以直接调用它的toString()以取得字符串描述。当Logger没有设定等级时,则使用父Logger的等级设定,所以在上面的范例中,onlyfunLogger设定等级为WARNING时,caterpillarLogger调用info()方法时并不会有信息显示(因为WARNING等级比INFO高)。只有在caterpillarLoger设定了自己的等级为INFO之后,才会显示信息。执行结果如下:

root logger:java.util.logging.LogManager$RootLogger@757aef
onlyfun logger:ysu
caterpillar Logger:ysu.hxy

2009-4-7 17:19:20 pku.sei.LoggerHierarchyDemo main
信息: caterpillar ' info

  • Posted: 2011-04-06 21:48     
  • Author:        zhanglei09
  • Categories:          笔记

Attachments

  • handler.PNGDownload       (24.9 KB) -      added by zhanglei09 4 years ago.           

Comments

No comments.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值