??xml version="1.0" encoding="utf-8" standalone="yes"?>国产精品一二一区,中文字幕亚洲欧美一区二区三区 ,成人福利视频http://www.aygfsteel.com/hiker/category/21208.htmlzh-cnTue, 18 Sep 2007 08:01:24 GMTTue, 18 Sep 2007 08:01:24 GMT60关于struts2启动tomcat的错?/title><link>http://www.aygfsteel.com/hiker/archive/2007/09/18/146158.html</link><dc:creator>hiker</dc:creator><author>hiker</author><pubDate>Tue, 18 Sep 2007 06:43:00 GMT</pubDate><guid>http://www.aygfsteel.com/hiker/archive/2007/09/18/146158.html</guid><wfw:comment>http://www.aygfsteel.com/hiker/comments/146158.html</wfw:comment><comments>http://www.aygfsteel.com/hiker/archive/2007/09/18/146158.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/hiker/comments/commentRss/146158.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/hiker/services/trackbacks/146158.html</trackback:ping><description><![CDATA[创徏struts.properties<br /> struts.locale=en_utf-8<br /> Q注Q如不创建此文g也可以,但在启动tomcat时候会有个警告Q警? <font color="#c00000"><strong>Settings: Could not parse struts.locale setting, substituting default VM locale</strong></font>Q? <img src ="http://www.aygfsteel.com/hiker/aggbug/146158.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/hiker/" target="_blank">hiker</a> 2007-09-18 14:43 <a href="http://www.aygfsteel.com/hiker/archive/2007/09/18/146158.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Commons-logging + Log4j 入门指南(转摘)http://www.aygfsteel.com/hiker/archive/2007/09/13/144766.htmlhikerhikerThu, 13 Sep 2007 03:03:00 GMThttp://www.aygfsteel.com/hiker/archive/2007/09/13/144766.htmlhttp://www.aygfsteel.com/hiker/comments/144766.htmlhttp://www.aygfsteel.com/hiker/archive/2007/09/13/144766.html#Feedback0http://www.aygfsteel.com/hiker/comments/commentRss/144766.htmlhttp://www.aygfsteel.com/hiker/services/trackbacks/144766.html

hiker 2007-09-13 11:03 发表评论
]]>
几篇关于U程的文?/title><link>http://www.aygfsteel.com/hiker/archive/2007/09/07/143342.html</link><dc:creator>hiker</dc:creator><author>hiker</author><pubDate>Fri, 07 Sep 2007 03:02:00 GMT</pubDate><guid>http://www.aygfsteel.com/hiker/archive/2007/09/07/143342.html</guid><wfw:comment>http://www.aygfsteel.com/hiker/comments/143342.html</wfw:comment><comments>http://www.aygfsteel.com/hiker/archive/2007/09/07/143342.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/hiker/comments/commentRss/143342.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/hiker/services/trackbacks/143342.html</trackback:ping><description><![CDATA[http://blog.csdn.net/buaawhl/archive/2005/01/18/257653.aspx<br /> <br /> http://blog.csdn.net/buaawhl/archive/2003/03/21/19839.aspx<br /> <br /> http://blog.csdn.net/buaawhl/archive/2003/03/18/19837.aspx<br /> <br /> http://blog.csdn.net/buaawhl/archive/2003/03/11/19833.aspx <img src ="http://www.aygfsteel.com/hiker/aggbug/143342.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/hiker/" target="_blank">hiker</a> 2007-09-07 11:02 <a href="http://www.aygfsteel.com/hiker/archive/2007/09/07/143342.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>struts2学习(fn)Qhttp://www.aygfsteel.com/max/http://www.aygfsteel.com/hiker/archive/2007/04/16/110908.htmlhikerhikerMon, 16 Apr 2007 03:06:00 GMThttp://www.aygfsteel.com/hiker/archive/2007/04/16/110908.htmlhttp://www.aygfsteel.com/hiker/comments/110908.htmlhttp://www.aygfsteel.com/hiker/archive/2007/04/16/110908.html#Feedback0http://www.aygfsteel.com/hiker/comments/commentRss/110908.htmlhttp://www.aygfsteel.com/hiker/services/trackbacks/110908.html
http://www.aygfsteel.com/max/


一个优U的bolgQ学?fn)?br /> http://lavasoft.blog.51cto.com/blog/62575/dir/1

hiker 2007-04-16 11:06 发表评论
]]>
Java调试的变q:从System.out.println到l(f)og4j【zz?http://www.aygfsteel.com/hiker/archive/2007/04/03/108198.htmlhikerhikerTue, 03 Apr 2007 06:17:00 GMThttp://www.aygfsteel.com/hiker/archive/2007/04/03/108198.htmlhttp://www.aygfsteel.com/hiker/comments/108198.htmlhttp://www.aygfsteel.com/hiker/archive/2007/04/03/108198.html#Feedback0http://www.aygfsteel.com/hiker/comments/commentRss/108198.htmlhttp://www.aygfsteel.com/hiker/services/trackbacks/108198.htmljungleford如是?o_log4j.jpg

    用惯?a target=_blank>VC的h刚接?a target=_blank>Java大概很不?fn)惯代码的调试,的确Q在M$的大部分IDE都做得相当出Ԍ包括像VJ++q样一直被JavaE序员称为是“垃圾”的类库(记得以前?a target=_blank>瀚v星云?a target=_blank>Java?/u>提有关VJ问题的h是有可能被封的,^_^Q,它的开发工具在调试上都相当Ҏ(gu)。Java也有命o行方式的调试和IDE的调试,但现在的?a target=_blank>JBq样的玩意又是个庞然大物Q低配置的机器可能就是个奢望Q不像VC那样。怎么办呢Q高手们_“我的jdb用得贼熟l?#8221;Q那我会报以景Ԓ的目光,像我q样的菜鸟基本上没使过jdbQ还是老老实实在代码里面System.out.println(...)。直?996q一个叫?#8220;Ƨ洲安全?sh)子市?#8221;QE.U. SEMPERQ的目启动Q?#8220;调试”不再是一?#8220;体力z?#8221;Q而是一UY件设计的艺术Q这个项目组开发的日志理接口后来成ؓApache Jakarta目中的一员,它就是现在我们所熟?zhn)?a target=_blank>log4j。下面的文字概要介l与Java日志记录相关的一些技术,目的不是让?zhn)攑ּ老土的System.out.println(...)Q而是_在Java的世界里可以有许多种选择Q你今天觉得掌握了一仉U武器,明天可能是“q时”的了Q呵c?

始祖QSystem.out.println(...)

    Z么还是要一再提到它Q毕竟我们的?fn)惯不是那么?gu)改变的,而且System.outQ别忘了q有System.errQ是一个直接和控制台打交道?a target=_blank>PrintStream对象Q是l端昄的基Q高U的Logger要在l端昄日志内容Q就必然会用到这个。一个小规模的程序调试,恰当C用System.out.println(...)我认Z然是一U最方便最有效的方法,所以我们仍把它攑֜最开始,以示不能“数典忘祖” :)

不常用的关键字:assert

    assert对多Ch来讲可能q比较陌生,它也是一个调试工P好像?a target=_blank>J2SE 1.4才加q来的东东,一U常见的用法是:

 assert (布尔表达?;


    当表辑ּ为true时没有Q何反映,如果为falsepȝ会抛出一?a target=_blank>AssertionError。如果你要用assertQ在~译时必d?#8220;-source 1.4”的选项Q在q行时则要加?#8220;-ea”选项?br>

后生可畏QJava Logging API一?/font>

    System.out.println(...)对于较高要求的用hq远不够的,它还不是一个日志系l,一个比较完善的日志pȝ应当有输出媒介、优先、格式化、日志过滤、日志管理、参数配|等功能。伴随J2SE 1.4一起发布的Java日志?a target=_blank>java.util.logging适时地满了我们的初步需求,在程序中按一定格式显C和记录丰富的调试信息已l是一件相当easy的事情?/p>

1. 日志记录器:Logger
    Logger是一个直接面向用L(fng)日志功能调用接口Q从用户的角度上看,它完成大部分日志记录工作Q通常你得C个Logger对象Q只需要用一些简单方法,譬如infoQwarningQlogQlogpQlogrb{就能完成Q务,单到和System.out.println(...)一样只用一条语句,但后台可能在向控制台Q向文gQ向数据库,甚至向网l同时输信息Q而这个过E对用户是完全透明的?br>    在用Logger之前Q首先需要通过getLogger()?a target=_blank>getAnonymousLogger()静态方法得C个Logger对象Q想想看Q这里是不是设计模式当中?#8220;工厂Ҏ(gu)”的一个实实在在的应用Q可以参考一下Logger的源代码Q你明?a target=_blank>LogManager?#8220;工厂c?#8221;而Logger?#8220;产品c?#8221;Q凡事都要学以致用嘛Q呵呵)。这里我们需要了解的是Logger?#8220;名字I间”Q?strong>namespaceQ的概念Q通常我们调试旉要清楚地知道某个变量是出现在什么位|,_到哪个类的哪个方法,namespace是q么个用处。我们用getLogger()得到Logger旉要指定这个Logger的名字空_通常是一个包名,譬如“com.jungleford.test”{,如果是指定了namespaceQ那么将在一个全局对象LogManager中注册这个namespaceQLogger会基于namespace形成层次关系Q譬如namespace?#8220;com.jungleford”的Logger是namespace?#8220;com.jungleford.test”的Logger的父Q后者调?a target=_blank>getParent()Ҏ(gu)返回前者,如果当前没有namespace?#8220;com.jungleford”的LoggerQ则查找namespace?#8220;com”的LoggerQ要是按照这个链找不到就q回根LoggerQ其namespace?"Q根Logger的父是null。从理论上说Q这个namespace可以是Q意的Q通常我们是按所调试的对象来定,但如果你是用getAnonymousLogger()Ҏ(gu)产生的LoggerQ那它就没有namespaceQ这?#8220;匿名Logger”的父是根Logger?br>    得到一个Logger对象后就可以记录日志了,下面是一些常用的Ҏ(gu)Q?


finest?a target=_blank>finer?a target=_blank>fine?a target=_blank>info?a target=_blank>config?a target=_blank>warning?a target=_blank>severeQ简z的Ҏ(gu)Q输出的日志为指定的U别。关于日志别我们在后面会详细谈到?br>
logQ不仅可以指定消息和U别Q还可以带一些参敎ͼ甚至可以直接是一个LogRecord对象Q这些参数是LogRecord对象的重要组成部分)?br>
logpQ更加精l了Q不但具有logҎ(gu)的功能,q可以不使用当前的namespaceQ定义新的类名和Ҏ(gu)名?br>
entering?a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Logger.html#exiting(java.lang.String, java.lang.String)" target=_blank>exitingQ这两个Ҏ(gu)在调试的时候特别管用,用来观察一个变量变化的情况Q就如同我们在VC的调试状态下watch一个变量,然后按F10Q呵c?/font>

2. 输出媒介控制QHandler
    日志的意义在于它可以以多UŞ式输出,其是像文gq样可以长久保存的媒介,q是System.out.println(...)所无法办到的。Logging API?a target=_blank>HandlercL供了一个处理日志记录(LogRecordQ它是对一条日志消息的装对象Q的接口Q包括几个已实现的APIQ?/p>


ConsoleHandlerQ向控制台输出?br>
FileHandlerQ向文g输出?br>
SocketHandlerQ向|络输出?/font>


    q三个输出控制器都是StreamHandler的子c,另外Handlerq有一个MemoryHandler的子c,它有Ҏ(gu)的用处,我们在后面将会看到。在E序启动旉认的Handler是ConsoleHandlerQ不q这个是可以配置的,下面会谈到l(f)ogging配置文g的问题?br>    此外用户q可以定制自p出控制器Q承Handler卛_Q通常只需要实现Handler中三个未定义的抽象方法:

publishQ主要方法,把日志记录写入你需要的媒介?br>
flushQ清除缓冲区q保存数据?br>
closeQ关闭控制器?/font>

publishQ主要方法,把日志记录写入你需要的媒介?br>
flushQ清除缓冲区q保存数据?br>
closeQ关闭控制器?/font>


    通过重写以上三个Ҏ(gu)我们可以很容易就实现一个把日志写入数据库的控制器?br>

3. 自定义输出格式:Formatter
    除了可以指定输出媒介之外Q我们可能还希望有多U输出格式,譬如可以是普通文本、HTML表格、XML{等Q以满不同的查看需求。Logging API中的Formatter是q样一个提供日志记录格式化Ҏ(gu)接口的类。默认提供了两种FormatterQ?br>
SimpleFormatterQ标准日志格式,是我们通常在启动一些诸?a target=_blank>Tomcat?a target=_blank>JBoss之类的服务器的时候经常能在控制台下看到的那种形式Q就像这P


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

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


XMLFormatterQXML形式的日志格式,你的Logger如果add了一个new XMLFormatter()Q那么在控制C׃看到下面q样的Ş式,不过更常用的是用上面介l的FileHandler输出到XML文g中:

<?xml version="1.0" encoding="GBK" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
  <date>2004-12-20T23:47:56</date>
  <millis>1103557676224</millis>
  <sequence>0</sequence>
  <logger>Test</logger>
  <level>WARNING</level>
  <class>Test</class>
  <method>main</method>
  <thread>10</thread>
  <message>warning message</message>
</record>

<?xml version="1.0" encoding="GBK" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
  <date>2004-12-20T23:47:56</date>
  <millis>1103557676224</millis>
  <sequence>0</sequence>
  <logger>Test</logger>
  <level>WARNING</level>
  <class>Test</class>
  <method>main</method>
  <thread>10</thread>
  <message>warning message</message>
</record>


    与HandlercMQ我们也可以~写自己的格式化处理器,譬如API里没有将日志输出为我们可通过览器查看的HTML表格形式的FormatterQ我们只需要重?个方法:

formatQ格式化LogRecord中包含的信息?br>
getHeadQ输Z息的头部?br>
getTailQ输Z息的N?/font>

formatQ格式化LogRecord中包含的信息?br>
getHeadQ输Z息的头部?br>
getTailQ输Z息的N?/font>

4. 定义日志U别QLevel
    大家可能都知道Windows?#8220;事g查看?#8221;Q里面有三种事gcdQ?#8220;信息”?#8220;警告”?#8220;错误”。这其实是日志U别的一U描q。Java日志U别?a target=_blank>Levelc表C,一个日志别对应的是一个整数|范围和整型值的范围是一致的Q该整数值愈大,说明警戒U别愈高。Level?个内|的U别Q分别是Q?

cd          对应的整?/strong>
OFF          最大整敎ͼInteger.MAX_VALUEQ?br>SEVERE     1000
WARNING   900
INFO         800
CONFIG      700
FINE          500
FINER        400
FINEST      300
ALL           最整敎ͼInteger.MIN_VALUEQ?/font>


    你也可以定义自己的日志别,但要注意的是Q不是直接创建Level的对象(因ؓ它的构造函数是protected的)Q而是通过l承Level的方式,譬如Q?

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

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


    上面定义了一个高于WARNING但低于SEVERE的日志别?br>    于是可能有朋友会兴冲冲地用以下的语句来记录一个事Ӟ

Logger logger = Logger.getAnonymousLogger();
logger.fine("Everything seems ok.");
//或者是
//logger.log(Level.FINE, "Everything seems ok.");

Logger logger = Logger.getAnonymousLogger();
logger.fine("Everything seems ok.");
//或者是
//logger.log(Level.FINE, "Everything seems ok.");


    但是一E序q行Q奇怪了Q怎么没有打印ZQ何消息呢Q下一节我们来谈这个问题?/font>

5. 日志qo器:Filter
    所谓过滤器是控制哪些日志该输出哪些不该输出的一U组件。上面你写的那条日志没有能在控制台显C出来,是因为logging API预先讑֮的缺省别是INFOQ也是说只有别不低于INFOQ即其整数g于800Q的日志才会被输出,q个是Filter的功能。所以我们可以看到SEVERE、WARNING、INFO以及上面我们定义的ALERT消息Q但看不到FINE、FINER和FINEST消息。当Ӟ你尽可以用Logger?a target=_blank>setLevelҎ(gu)或者修攚w|文件的Ҏ(gu)Q什么是配置文gQ我们后面将会看刎ͼ来重新定义Logger输出的最低别?br>    Filter不仅仅可以按日志U别qoQ你也可以定义自qFilterQ实现其中的isLoggableҎ(gu)Q随便按照LogRecord携带的Q何信息进行过滤,譬如Q顺便复?fn)一下匿名类Q呵呵)Q?

Logger logger = Logger.getAnonymousLogger();
logger.setFilter(new Filter()
{
  public boolean isLoggable(LogRecord rec)
  {
    //从LogRecord里得到过滤信?br>  }
});


6. 预定义参?br>
    LogManager是一个实CSingleton模式的全局对象Q由于是一个唯一的对象,LogManager需要是U程安全的)Q它理着E序启动以后所有已注册Q包层次Q或匿名的LoggerQ以及相关配|信息。这里的配置信息通常是从<JAVA_HOME>\jre\lib\logging.properties文g得到的。logging.properties对于logging API来说是一个很重要的文Ӟ它的内容一般是Q?br>

############################################################
# Default Logging Configuration File
#
# You can use a different file by specifying a filename
# with the java.util.logging.config.file system property.
# For example java -Djava.util.logging.config.file=myfile
############################################################

############################################################
# Global properties
############################################################

# "handlers" specifies a comma separated list of log Handler
# classes. These handlers will be installed during VM startup.
# Note that these classes must be on the system classpath.
# By default we only configure a ConsoleHandler, which will only
# show messages at the INFO and above levels.
handlers= java.util.logging.ConsoleHandler

# To also add the FileHandler, use the following line instead.
#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler

# Default global logging level.
# This specifies which kinds of events are logged across
# all loggers. For any given facility this global level
# can be overriden by a facility specific level
# Note that the ConsoleHandler also has a separate level
# setting to limit messages printed to the console.
.level= INFO

############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################

# default file output is in user's home directory.
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

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

############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################

# For example, set the com.xyz.foo logger to only log SEVERE
# messages:
com.xyz.foo.level = SEVERE


    你可以通过修改q个配置文g来改变运行时Logger的行为,譬如Q?level定义的是上面所说的默认输出的最低日志别;XXXHandler相关属性定义了各种输出媒介{等?br>    q里比较有意思的是关于日志文Ӟ也就是FileHandlerQ当Ӟ你可以在E序中创Z个FileHandlerQ然后添加到l(f)ogger中:
 
FileHandler fhd = new FileHandler("%h/java%u.log", 5000, 1, true);
fhd.setLevel(Level.ALL);
fhd.setFormatter(new XMLFormatter());
logger.addHandler(fhd);
FileHandler fhd = new FileHandler("%h/java%u.log", 5000, 1, true);
fhd.setLevel(Level.ALL);
fhd.setFormatter(new XMLFormatter());
logger.addHandler(fhd);

    q段代码{h(hun)于上面logging.properties中的文字D:
 
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

    q里的pattern代表用{义字W定义的一个日志文件名Q?转义字符?/font> 含义 %t 临时目录 %h 用户目录Q即pȝ属?#8220;user.home”对应的?/font> %g 一个随机生成的数字Q可以重?/font> %u 一个随机生成的非重复数?/font>
    以上面的“%h/java%u.log”ZQ在Windows 2000下代表日志文件可能就是:C:\Documents and Settings\Administrator\javax.log。这里x代表一个不重复的数字,如果是第一ơ,那么是java0.logQ如果在该目录下已经存在了一个java0.log的文Ӟ那么logger׃生一个java1.log的新的日志文件?br>    当然Q你可以在别的地方用自己写的配|文Ӟ不过在启动程序时候需要指?strong>java.logging.config.file
属性:
转义字符?/font> 含义 %t 临时目录 %h 用户目录Q即pȝ属?#8220;user.home”对应的?/font> %g 一个随机生成的数字Q可以重?/font> %u 一个随机生成的非重复数?/font>
    以上面的“%h/java%u.log”ZQ在Windows 2000下代表日志文件可能就是:C:\Documents and Settings\Administrator\javax.log。这里x代表一个不重复的数字,如果是第一ơ,那么是java0.logQ如果在该目录下已经存在了一个java0.log的文Ӟ那么logger׃生一个java1.log的新的日志文件?br>    当然Q你可以在别的地方用自己写的配|文Ӟ不过在启动程序时候需要指?strong>java.logging.config.file属性:
 
java -Djava.logging.config.file=...

7. 资源与本地化
    Logger里还有个Ҏ(gu)?a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Logger.html#logrb(java.util.logging.Level, java.lang.String, java.lang.String, java.lang.String, java.lang.String)" target=_blank>logrbQ可能初学者不太会用到。如果你安装的JDK是国际版的,那么你将会看到在中文Windowsq_下日志输出的INFO、WARNING昄的是“信息”?#8220;警告”{中文字栗因为logrb是一个和Java i18n/l10n相关的方法,你可以定义自q“资源?#8221;QResource BundleQ,然后在logrbҎ(gu)中指定相应的资源名称Q那么在输出日志中你p看到用自己定义的本地语言、时间等昄的信息。如果你对i18n/l10n感兴,可以参?a target=_blank>Java Localization文档?br>

    了解以上lg后,我们回顾一个完整的日志处理的工作过E:
    E序启动日志服务Q创建Logger对象QLogManager按照namespace的层ơ结构组lLoggerQ在同一个namespace里子Logger承父Logger的属性;同时QLogManager从logging.properties中读取相应的属性对Loggerq行初始化,如果在程序中讄了属性则使用新的配置。当应用E序产生一条日志,Logger创Z个LogRecord对象Q该对象装了一条日志的全部信息。Logger需要根据当前设|的Filter来判断这条日志是否需要输出,q将有用的日志传l相应的Handler处理Q而HandlerҎ(gu)当前讄的Formatter和Resource Bundle日志消息{换成一定的昄格式Q然后输出到预定的媒介(控制台、文件等Q中厅R整个过E大致如?所C:

o_logging1.gif

                                                  ?

    前面我们在介lHandler的时候提到过一个特D的cdMemoryHandlerQ这里我们要了解一?#8220;Handler?#8221;的概念,日志在输Z前可能经q多个Handler的处理,MemoryHandler在这U情况下是一个中间角Ԍ它维持一个内存中的日志缓冲区Q当日志没有填满~冲区时将全部日志送到下一个HandlerQ否则新q来的日志将会覆盖最老的那些日志Q因此,使用MemoryHandler可以l护一定容量的日志Q另外,MemoryHandler也可以不需要用Formatter来进行格式化Q从而具有较高的效率。一个用Handler铄例子如图2所C:


?

青出于蓝QApache Jakarta log4j日志工具?/font>

    应付日常的日志需求,J2SE的Logging API可以说已l做得相当出色了Q但q求完美的开发h员可能需要可扩展性更好的专业日志处理工具Qlog4j正是当前比较行的一个工具包Q它提供更多的输出媒介、输出格式和配置选择Q你会发现原来在J2SE里一些仍需要自己手工构建的功能在log4j当中都已lؓ你实C。关于log4j我可能谈得不会太多,可以看看文后所附的“参考资?/u>”Q网上也有很详细的介l,我在q里做的是一个对比,因ؓlog4j和J2SE 1.4 Logging API的用法是很相似的Q一些名UC同的lg你会发现他们所处的C其实是一L(fng)Q?

                 J2SE 1.4中的c?/strong>       log4j中的c?/strong>
日志记录?/font>    Logger                  Logger
日志理?/strong>    LogManager           LogManager
日志对象       LogRecord             LoggingEvent
输出媒介控制 Handler                 Appender
格式?/strong>          Formatter              Layout
U别             Level                    Level
qo?/strong>          Filter                     Filter

    log4j可以做到更精l更完善的控Ӟ譬如J2SE里没有现成向数据库里写日志的Ҏ(gu)Q但log4j却有JDBCAppenderQ它甚至q能向GUI囑Ş界面Q?a target=_blank>LF5AppenderQ一U以JTree方式昄的层ơ结构)、Windows NT事g查看器(NTEventLogAppenderQ、UNIX的syslogd服务Q?a target=_blank>SyslogAppenderQ、电(sh)子邮(SMTPAppenderQ、Telnetl端Q?a target=_blank>TelnetAppenderQ、JMS消息Q?a target=_blank>JMSAppenderQ输出日志,牛吧QJ2SE里默认只能用%JAVA_HOME%\jre\lib\logging.properties做配|文Ӟ但log4j却可以在代码中设|其它\径下的properties文g或XML格式的配|文件。log4j的其它方面同样很丰富QMQlog4j的最大的特点是“灉|”Q无论是Appender、Layoutq是ConfiguratorQ你可以把日志轻村֜弄成几乎M你想要的形式?/font>

框架与标准:JSR议案

    从时间顺序上Ԍlog4j要比J2SE Logging API来得早,很多概念都是log4j先有的,但成Z个标准,则是?a target=_blank>JSR 47的Ş成。可能有不太了解JSRQ这q要谈到JCPQ即“Java Community Process”Q它是一个于1998q成立的旨在为Java技术制定民间标准的开攄l,你可以通过http://www.jcp.org/en/participation/membership甌成ؓ它的付费或免费会员,JCP的主要工作就是制定和发布JSRQJava Specification RequestsQ,JSR对于Java的意义就相当于RFC对于|络技术的意义Q由于JCP会员们的集思广益,使得JSR成ؓJava界的一个重要标准。JSR 47?#8220;Logging API Specification”Q制定了调试和日志框ӞJ2SE Logging API正是该框架的一个实现。由于种U原因,在JSR 47出来以前Qlog4j已l成ZҎ(gu)熟的技术,使得log4j在选择上占据了一定的优势Q但不能因此pJSR 47是过时的规范Q标准L在发展的嘛!

q不是全部:其它日志处理工具

    除了J2SE Logging API和log4jQ日志处理方面还有别的技术:Jakarta?a target=_blank>commonslg目中的JCLQJakarta Commons LoggingQ是一个不错的选择Q它有点cM于GSS-APIQ通用安全服务接口Q中的思想Q其日志服务机制是可以替换的Q也是说既可以用J2SE Logging API也可以用log4jQ但JCL对开发h员提供一致的接口Q这一点相当重要,lg可重用正是Jakarta Commons目q求的一个目标;IBM?a target=_blank>JLog也是在J2SE Logging API之前推出的一个工具包Q但JLog是一个商业品?br>    至于日志API的应用那可就多了Q现在哪个大一点的工具或^C用到日志模块呢?Tomcat、JBoss……

    说了q么多,我们无非需要知道的一件事是Q?#8220;调试”也是一门学问。在我们一个劲地用System.out.println(...)而且用得很爽的时候,也应该想想看Q如何让q样一条菜鸟语句也能变得h性化和丰富多彩?/p>

参考资?/font>



hiker 2007-04-03 14:17 发表评论
]]>
վ֩ģ壺 | Ͷ| տ| | ˿| ƽ| | | | ̩| | ¬| | | | | | | | | | ¡Ң| ˹| ˺| ɽ| | | Դ| | | ɽ| | ʩ| ָ| | ͨ| | Ҿ| ̫| ˶| Ͻ|