﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-【永恒的瞬间】  -文章分类-Log4j</title><link>http://www.blogjava.net/19851985lili/category/18934.html</link><description>☜GivE mE HapPy ☞




</description><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 03:42:57 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 03:42:57 GMT</pubDate><ttl>60</ttl><item><title>简单的说log4j就是帮助开发人员进行日志输出管理的API类库。它最重要的特点就</title><link>http://www.blogjava.net/19851985lili/articles/97641.html</link><dc:creator>☜♥☞MengChuChen</dc:creator><author>☜♥☞MengChuChen</author><pubDate>Fri, 02 Feb 2007 12:30:00 GMT</pubDate><guid>http://www.blogjava.net/19851985lili/articles/97641.html</guid><wfw:comment>http://www.blogjava.net/19851985lili/comments/97641.html</wfw:comment><comments>http://www.blogjava.net/19851985lili/articles/97641.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/19851985lili/comments/commentRss/97641.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/19851985lili/services/trackbacks/97641.html</trackback:ping><description><![CDATA[
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<font size="2">
						<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt">可以</span>
						<span style="FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-bidi-font-size: 10.5pt">配置文件灵活的设置</span>
						<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt">日志信息的优先级、日志信息的输出目的地以及日志信息的输出格式。<span lang="EN-US"><?XML:NAMESPACE PREFIX = O /?><o:p></o:p></span></span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<font size="2">
						<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt">Log4j除了可以记录程序运行日志信息外还有一重要的功能就是用来</span>
						<span style="FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-bidi-font-size: 10.5pt">显示调试信息。程序员经常会遇到脱离<span lang="EN-US">java ide环境调试程序的情况，这时大多数人会选择使用System.out.println语句输出某个变量值的方法进行调试。这样会带来一个非常麻烦的问题：一旦哪天程序员决定不要显示这些System.out.println的东西了就只能一行行的把这些垃圾语句注释掉。若哪天又需调试变量值，则只能再一行行去掉这些注释恢复System.out.println语句。使用log4j可以很好的处理类似情况。<o:p></o:p></span></span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l1 level1 lfo1; tab-stops: list 21.0pt">
				<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-bidi-font-size: 10.5pt">
						<font size="2">log4j使用方法<o:p></o:p></font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 22.05pt; mso-char-indent-count: 2.1">
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-bidi-font-size: 10.5pt">
						<font size="2">下面介绍的是<span lang="EN-US">log4j一些理论方面的知识，读者觉得枯燥的话可以跳过本节直接阅读第三节实例部分。<o:p></o:p></span></font>
				</span>
		</p>
		<p>
				<span style="FONT-SIZE: 10.5pt">
						<font size="2">　　<span>1、定义配置文件<o:p></o:p></span></font>
				</span>
		</p>
		<p>
				<span style="FONT-SIZE: 10.5pt">
						<font size="2">　<span lang="EN-US"><span style="mso-spacerun: yes">  </span>首先使用配置文件将使我们的应用程序更加灵活配置log日志输出方式包括输出优先级、输出目的地、输出格式。Log4j支持两种配置文件格式，一种是XML格式的文件，一种是Java特性文件log4j.properties（键=值）。下面将介绍使用log4j.properties文件作为配置文件的方法：<o:p></o:p></span></font>
				</span>
		</p>
		<p>
				<font size="2">
						<span style="FONT-SIZE: 10.5pt">　　</span>
						<span lang="EN-US" style="FONT-SIZE: 10.5pt">
								<span style="mso-no-proof: yes">①</span>
						</span>
						<span lang="EN-US" style="FONT-SIZE: 10.5pt">配置根Logger，其语法为：0<o:p></o:p></span>
				</font>
		</p>
		<p>
				<span style="FONT-SIZE: 10.5pt">
						<font size="2">　　<span lang="EN-US">log4j.rootLogger = [ level ] , appenderName, appenderName, … <o:p></o:p></span></font>
				</span>
		</p>
		<p>
				<span style="FONT-SIZE: 10.5pt">
						<font size="2">　　其中，<span lang="EN-US">level 是日志记录的优先级，分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定义的级别。Log4j建议只使用四个级别，优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别，您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别，则应用程序中所有DEBUG级别的日志信息将不被打印出来。 appenderName就是指定日志信息输出到哪个地方。可同时指定多个输出目的地。 <o:p></o:p></span></font>
				</span>
		</p>
		<p>
				<font size="2">
						<span style="FONT-SIZE: 10.5pt">　　</span>
						<span lang="EN-US" style="FONT-SIZE: 10.5pt">
								<span style="mso-no-proof: yes">②</span>
						</span>
						<span lang="EN-US" style="FONT-SIZE: 10.5pt">配置日志信息输出目的地Appender，其语法为：<o:p></o:p></span>
				</font>
		</p>
		<p>
				<span style="FONT-SIZE: 10.5pt">
						<font size="2">　　</font>
						<span lang="EN-US">
								<font size="2">log4j.appender.appenderName = fully.qualified.name.of.appender.class <br />　　log4j.appender.appenderName.option1 = value1 <br />　　… <br />　　log4j.appender.appenderName.option = valueN <o:p></o:p></font>
						</span>
				</span>
		</p>
		<p>
				<span style="FONT-SIZE: 10.5pt">
						<font size="2">　　其中，</font>
						<span lang="EN-US">
								<font size="2">Log4j提供的appender有以下几种： <br />　　org.apache.log4j.ConsoleAppender（控制台）， <br />　　org.apache.log4j.FileAppender（文件）， <br />　　org.apache.log4j.DailyRollingFileAppender（每天产生一个日志文件），<br />　　org.apache.log4j.RollingFileAppender（文件大小到达指定尺寸的时候产生一个新的文件）， <br />　　org.apache.log4j.WriterAppender（将日志信息以流格式发送到任意指定的地方） <o:p></o:p></font>
						</span>
				</span>
		</p>
		<p>
				<font size="2">
						<span style="FONT-SIZE: 10.5pt">　 </span>
						<span lang="EN-US" style="FONT-SIZE: 10.5pt">
								<span style="mso-no-proof: yes">③</span>
						</span>
						<span lang="EN-US" style="FONT-SIZE: 10.5pt">配置日志信息的格式（布局），其语法为：<o:p></o:p></span>
				</font>
		</p>
		<p>
				<span style="FONT-SIZE: 10.5pt">
						<font size="2">　　</font>
						<span lang="EN-US">
								<font size="2">log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class <br />　　log4j.appender.appenderName.layout.option1 = value1 <br />　　… <br />　　log4j.appender.appenderName.layout.option = valueN <o:p></o:p></font>
						</span>
				</span>
		</p>
		<p>
				<span style="FONT-SIZE: 10.5pt">
						<font size="2">　　其中，</font>
						<span lang="EN-US">
								<font size="2">Log4j提供的layout有以下几种： <br />　　org.apache.log4j.HTMLLayout（以HTML表格形式布局）， <br />　　org.apache.log4j.PatternLayout（可以灵活地指定布局模式）， <br />　　org.apache.log4j.SimpleLayout（包含日志信息的级别和信息字符串）， <br />　　org.apache.log4j.TTCCLayout（包含日志产生的时间、线程、类别等等信息） <o:p></o:p></font>
						</span>
				</span>
		</p>
		<p>
				<span style="FONT-SIZE: 10.5pt">
						<font size="2">　　<span lang="EN-US">Log4J采用类似C语言中的printf函数的打印格式格式化日志信息，打印参数如下： %m 输出代码中指定的消息<o:p></o:p></span></font>
				</span>
		</p>
		<p>
				<span style="FONT-SIZE: 10.5pt">
						<font size="2">　　</font>
						<span lang="EN-US">
								<font size="2">%p 输出优先级，即DEBUG，INFO，WARN，ERROR，FATAL <br />　　%r 输出自应用启动到输出该log信息耗费的毫秒数 <br />　　%c 输出所属的类目，通常就是所在类的全名 <br />　　%t 输出产生该日志事件的线程名 <br />　　%n 输出一个回车换行符，Windows平台为“\r\n”，Unix平台为“\n” <br />　　%d 输出日志时间点的日期或时间，默认格式为ISO8601，也可以在其后指定格式，比如：%d{yyy MMM dd HH:mm:ss,SSS}，输出类似：</font>
						</span>
				</span>
				<?XML:NAMESPACE PREFIX = ST1 /?>
				<st1:chsdate isrocdate="False" islunardate="False" day="18" month="10" year="2002">
						<span lang="EN-US" style="FONT-SIZE: 10.5pt">
								<font size="2">2002年10月18日</font>
						</span>
				</st1:chsdate>
				<span lang="EN-US" style="FONT-SIZE: 10.5pt">
						<font size="2"> 22：10：28，921 <br />　　%l 输出日志事件的发生位置，包括类目名、发生的线程，以及在代码中的行数。举例：Testlog4.main(TestLog4.java:10) <o:p></o:p></font>
				</span>
		</p>
		<p>
				<span style="FONT-SIZE: 10.5pt">
						<font size="2">　　<span>2、在代码中使用Log4j <o:p></o:p></span></font>
				</span>
		</p>
		<p>
				<font size="2">
						<span style="FONT-SIZE: 10.5pt">　　</span>
						<span lang="EN-US" style="FONT-SIZE: 10.5pt">
								<span style="mso-no-proof: yes">①</span>
						</span>
						<span lang="EN-US" style="FONT-SIZE: 10.5pt">得到记录器<o:p></o:p></span>
				</font>
		</p>
		<p>
				<span style="FONT-SIZE: 10.5pt">
						<font size="2">　　使用<span lang="EN-US">Log4j，第一步就是获取日志记录器，这个记录器将负责控制日志信息。其语法为： <o:p></o:p></span></font>
				</span>
		</p>
		<p>
				<span style="FONT-SIZE: 10.5pt">
						<font size="2">　　<span lang="EN-US">public static Logger getLogger( String name) <o:p></o:p></span></font>
				</span>
		</p>
		<p>
				<span style="FONT-SIZE: 10.5pt">
						<font size="2">　　通过指定的名字获得记录器，如果必要的话，则为这个名字创建一个新的记录器。<span lang="EN-US">Name一般取本类的名字，比如： <o:p></o:p></span></font>
				</span>
		</p>
		<p>
				<span style="FONT-SIZE: 10.5pt">
						<font size="2">　　<span lang="EN-US">static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () )<o:p></o:p></span></font>
				</span>
		</p>
		<p>
				<font size="2">
						<span style="FONT-SIZE: 10.5pt">　　</span>
						<span lang="EN-US" style="FONT-SIZE: 10.5pt">
								<span style="mso-no-proof: yes">②</span>
						</span>
						<span lang="EN-US" style="FONT-SIZE: 10.5pt">读取配置文件 <o:p></o:p></span>
				</font>
		</p>
		<p>
				<span style="FONT-SIZE: 10.5pt">
						<font size="2">　　当获得了日志记录器之后，第二步将配置<span lang="EN-US">Log4j环境，其语法为：<o:p></o:p></span></font>
				</span>
		</p>
		<p style="TEXT-INDENT: 21pt">
				<span lang="EN-US" style="FONT-SIZE: 10.5pt">
						<font size="2">BasicConfigurator.configure ()： 自动快速地使用缺省Log4j环境。<br />　　PropertyConfigurator.configure ( String configFilename) ：读取使用Java的特性文件编写的配置文件。<o:p></o:p></font>
				</span>
		</p>
		<p style="TEXT-INDENT: 21pt">
				<font size="2">
						<span style="FONT-SIZE: 10.5pt">例：<span lang="EN-US">PropertyConfigurator.configure</span></span>
						<span lang="EN-US" style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 9.0pt">(".\\src\\log4j.properties")</span>
				</font>
				<span lang="EN-US" style="FONT-SIZE: 10.5pt">
						<br />
						<font size="2">　　DOMConfigurator.configure ( String filename ) ：读取XML形式的配置文件。<o:p></o:p></font>
				</span>
		</p>
		<p>
				<font size="2">
						<span style="FONT-SIZE: 10.5pt">　　</span>
						<span lang="EN-US" style="FONT-SIZE: 10.5pt">
								<span style="mso-no-proof: yes">③</span>
						</span>
						<span lang="EN-US" style="FONT-SIZE: 10.5pt">插入记录信息（格式化日志信息）<o:p></o:p></span>
				</font>
		</p>
		<p>
				<span style="FONT-SIZE: 10.5pt">
						<font size="2">　　当上两个必要步骤执行完毕，就可轻松地使用不同优先级别的日志记录语句插入到您想记录日志的任何地方，其语法如下：<span lang="EN-US"><o:p></o:p></span></font>
				</span>
		</p>
		<p>
				<span style="FONT-SIZE: 10.5pt">
						<font size="2">　　</font>
						<span lang="EN-US">
								<font size="2">Logger.debug ( Object message ) ;<br />　　Logger.info ( Object message ) ;<br />　　Logger.warn ( Object message ) ;<br />　　Logger.error ( Object message ) ;<o:p></o:p></font>
						</span>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l1 level1 lfo1; tab-stops: list 21.0pt">
				<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt">
						<font size="2">log4j范例程序<o:p></o:p></font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt">
						<font size="2">下面将使用一个最简单的范例程序来进一步说明<span lang="EN-US">log4j的使用方法。程序代码如下：<o:p></o:p></span></font>
				</span>
		</p>
		<p style="LINE-HEIGHT: 6pt; mso-line-height-rule: exactly">
				<span lang="EN-US" style="COLOR: navy">
						<o:p>
								<font size="2">
								</font>
						</o:p>
				</span>
		</p>
		<p style="LINE-HEIGHT: 8pt; mso-line-height-rule: exactly">
				<span>
						<font size="2">import org.apache.log4j.*;<o:p></o:p></font>
				</span>
		</p>
		<p style="LINE-HEIGHT: 8pt; mso-line-height-rule: exactly">
				<span lang="EN-US" style="COLOR: black">
						<font size="2">
								<o:p>
								</o:p>
						</font>
				</span>
		</p>
		<p style="LINE-HEIGHT: 8pt; mso-line-height-rule: exactly">
				<font size="2">
						<span>public class</span>
						<span lang="EN-US" style="COLOR: black"> LogTest </span>
						<span lang="EN-US" style="COLOR: navy">{</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p style="LINE-HEIGHT: 8pt; mso-line-height-rule: exactly">
				<span lang="EN-US" style="COLOR: black">
						<font size="2">
								<o:p>
								</o:p>
						</font>
				</span>
		</p>
		<p style="LINE-HEIGHT: 8pt; mso-line-height-rule: exactly">
				<span lang="EN-US" style="COLOR: black">
						<font size="2">
								<o:p>
								</o:p>
						</font>
				</span>
		</p>
		<p style="LINE-HEIGHT: 8pt; mso-line-height-rule: exactly">
				<font size="2">
						<span>
								<span style="mso-spacerun: yes">    </span>static</span>
						<span lang="EN-US" style="COLOR: black"> Logger logger = Logger.getLogger(LogTest.class.getName());<o:p></o:p></span>
				</font>
		</p>
		<p style="LINE-HEIGHT: 8pt; mso-line-height-rule: exactly">
				<span lang="EN-US" style="COLOR: black">
						<font size="2">
								<o:p>
								</o:p>
						</font>
				</span>
		</p>
		<p style="LINE-HEIGHT: 8pt; mso-line-height-rule: exactly">
				<font size="2">
						<span>
								<span style="mso-spacerun: yes">    </span>public</span>
						<span> static</span>
						<span> void</span>
						<span lang="EN-US" style="COLOR: black"> main(String[] args) </span>
						<span lang="EN-US" style="COLOR: navy">{</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p style="LINE-HEIGHT: 8pt; mso-line-height-rule: exactly">
				<span lang="EN-US" style="COLOR: black">
						<font size="2">
								<o:p>
								</o:p>
						</font>
				</span>
		</p>
		<p style="LINE-HEIGHT: 8pt; mso-line-height-rule: exactly">
				<font size="2">
						<span lang="EN-US" style="COLOR: black">
								<span style="mso-spacerun: yes">        </span>
						</span>
						<span lang="EN-US" style="FONT-SIZE: 10.5pt">PropertyConfigurator.configure ( “.\\src\</span>
						<span lang="EN-US" style="COLOR: black; FONT-FAMILY: Arial">log4j.properties</span>
						<span lang="EN-US" style="FONT-SIZE: 10.5pt">”)</span>
						<span style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Courier New'; mso-ascii-font-family: 'Courier New'">；</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p style="TEXT-INDENT: 40pt; LINE-HEIGHT: 8pt; mso-char-indent-count: 4.0; mso-line-height-rule: exactly">
				<font size="2">
						<span lang="EN-US" style="COLOR: black">logger.debug(</span>
						<span lang="EN-US" style="COLOR: red">"Debug ..."</span>
						<span lang="EN-US" style="COLOR: black">);<o:p></o:p></span>
				</font>
		</p>
		<p style="LINE-HEIGHT: 8pt; mso-line-height-rule: exactly">
				<span lang="EN-US" style="COLOR: black">
						<font size="2">
								<o:p>
								</o:p>
						</font>
				</span>
		</p>
		<p style="LINE-HEIGHT: 8pt; mso-line-height-rule: exactly">
				<font size="2">
						<span lang="EN-US" style="COLOR: black">
								<span style="mso-spacerun: yes">        </span>logger.info(</span>
						<span lang="EN-US" style="COLOR: red">"Info ..."</span>
						<span lang="EN-US" style="COLOR: black">);<o:p></o:p></span>
				</font>
		</p>
		<p style="LINE-HEIGHT: 8pt; mso-line-height-rule: exactly">
				<span lang="EN-US" style="COLOR: black">
						<font size="2">
								<o:p>
								</o:p>
						</font>
				</span>
		</p>
		<p style="LINE-HEIGHT: 8pt; mso-line-height-rule: exactly">
				<font size="2">
						<span lang="EN-US" style="COLOR: black">
								<span style="mso-spacerun: yes">        </span>logger.warn(</span>
						<span lang="EN-US" style="COLOR: red">"Warn ..."</span>
						<span lang="EN-US" style="COLOR: black">);<o:p></o:p></span>
				</font>
		</p>
		<p style="LINE-HEIGHT: 8pt; mso-line-height-rule: exactly">
				<span lang="EN-US" style="COLOR: black">
						<font size="2">
								<o:p>
								</o:p>
						</font>
				</span>
		</p>
		<p style="LINE-HEIGHT: 8pt; mso-line-height-rule: exactly">
				<font size="2">
						<span lang="EN-US" style="COLOR: black">
								<span style="mso-spacerun: yes">        </span>logger.error(</span>
						<span lang="EN-US" style="COLOR: red">"Error ..."</span>
						<span lang="EN-US" style="COLOR: black">);<o:p></o:p></span>
				</font>
		</p>
		<p style="LINE-HEIGHT: 8pt; mso-line-height-rule: exactly">
				<span lang="EN-US" style="COLOR: black">
						<font size="2">
								<o:p>
								</o:p>
						</font>
				</span>
		</p>
		<p style="LINE-HEIGHT: 6pt; mso-line-height-rule: exactly">
				<font size="2">
						<span lang="EN-US" style="COLOR: black">
								<span style="mso-spacerun: yes">    </span>
						</span>
						<span lang="EN-US" style="COLOR: navy">}</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p style="LINE-HEIGHT: 6pt; mso-line-height-rule: exactly">
				<font size="2">
						<span lang="EN-US" style="COLOR: navy">}</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt">
						<font size="2">程序说明：<span lang="EN-US"><o:p></o:p></span></font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 10.5pt; mso-char-indent-count: 1.0">
				<font size="2">
						<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt">
								<span style="mso-no-proof: yes">①</span>
						</span>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial"> static Logger logger = Logger.getLogger(LogTest.class.getName());</span>
						<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">就是创建一个属于</span>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">LogTest</span>
						<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">类的</span>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">Logger</span>
						<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">对象，创建时要告知</span>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">Logger</span>
						<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">你当前的</span>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">Class</span>
						<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">是什么。</span>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 10pt; mso-char-indent-count: 1.0">
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial; mso-no-proof: yes">②</span>
				<font size="2">
						<span lang="EN-US" style="mso-bidi-font-size: 10.5pt"> PropertyConfigurator.configure ( “</span>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">log4j.properties</span>
						<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">”)</span>
						<span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'">就是说使用当前工程目录下的</span>
						<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">src</span>
						<span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'">文件夹中的</span>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">log4j.properties</span>
						<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">文件作为配置文件。若将</span>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">log4j.properties</span>
						<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">放在工程根目录下也可不写此句，程序会自动找到配置文件。</span>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 10pt; mso-char-indent-count: 1.0">
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial; mso-no-proof: yes">③</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial"> logger.debug</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">就是输出</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">debug</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">的信息，</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">logger.info</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">就是输出提示信息，</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">logger.warn</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">就是显示警告信息，</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">logger.error</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">就是显示错误信息。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">下面是配置文件</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">log4j.properties</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">的内容：</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">
						<o:p>
						</o:p>
				</span>
		</p>
		<p>
				<font size="2">
						<span lang="EN-US" style="COLOR: black">log4j.rootCategory=DEBUG, stdout</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Courier New'; mso-ascii-font-family: 'Courier New'">，</span>
						<span lang="EN-US" style="COLOR: black">R<o:p></o:p></span>
				</font>
		</p>
		<p>
				<span lang="EN-US" style="COLOR: black">
						<font size="2">log4j.appender.stdout=org.apache.log4j.ConsoleAppender<o:p></o:p></font>
				</span>
		</p>
		<p>
				<span lang="EN-US" style="COLOR: black">
						<font size="2">log4j.appender.stdout.layout=org.apache.log4j.PatternLayout<o:p></o:p></font>
				</span>
		</p>
		<p>
				<span lang="EN-US" style="COLOR: black">
						<font size="2">log4j.appender.stdout.layout.ConversionPattern=%5p (%F:%L) - %m%n<o:p></o:p></font>
				</span>
		</p>
		<p>
				<span lang="EN-US" style="COLOR: black">
						<font size="2">log4j.appender.R=org.apache.log4j.RollingFileAppender<o:p></o:p></font>
				</span>
		</p>
		<p>
				<span lang="EN-US" style="COLOR: black">
						<font size="2">log4j.appender.R.File=log.txt<o:p></o:p></font>
				</span>
		</p>
		<p>
				<span lang="EN-US" style="COLOR: black">
						<font size="2">log4j.appender.R.MaxFileSize=100KB<o:p></o:p></font>
				</span>
		</p>
		<p>
				<span lang="EN-US" style="COLOR: black">
						<font size="2">log4j.appender.R.MaxBackupIndex=1<o:p></o:p></font>
				</span>
		</p>
		<p>
				<span lang="EN-US" style="COLOR: black">
						<font size="2">log4j.appender.R.layout=org.apache.log4j.PatternLayout<o:p></o:p></font>
				</span>
		</p>
		<p>
				<font size="2">
						<span lang="EN-US" style="COLOR: black">log4j.appender.R.layout.ConversionPattern=%d</span>
						<span lang="EN-US" style="COLOR: navy">{</span>
						<span lang="EN-US" style="COLOR: black">yyyy MMM dd HH:mm:ss</span>
						<span lang="EN-US" style="COLOR: navy">}</span>
						<span lang="EN-US" style="COLOR: black"> %-5p %c - %m%n<o:p></o:p></span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt">
						<font size="2">程序说明：<span lang="EN-US"><o:p></o:p></span></font>
				</span>
		</p>
		<p>
				<font size="2">
						<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt">
								<span style="mso-no-proof: yes">①</span>
						</span>
						<span lang="EN-US" style="COLOR: black"> log4j.rootCategory=DEBUG, stdout</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体; mso-hansi-font-family: 'Courier New'; mso-ascii-font-family: 'Courier New'">，</span>
						<span lang="EN-US" style="COLOR: black">R<o:p></o:p></span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">就是说我要显示所有优先权等於和高于</span>
				<span>Debug的信息。<br />"stdout"，</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">”R”</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">表示我定义了两个输出端</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">(</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">随便什么名字都好</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">)</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial; mso-no-proof: yes">②</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">下面的三行说</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">stdout</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">输出端其实是标准输出</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">Console</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">，也就是屏幕。输出的格式是</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">Pattern</span>
				<font size="2">
						<span lang="EN-US" style="COLOR: black">Layout</span>
						<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">。转换方式是</span>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">%5p (%F:%L) - %m%n</span>
						<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">，即前五格用来显示优先权，再显示当前的文件名，加当前的行数。最后是</span>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">logger.debug()</span>
						<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">或</span>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">logger.info()</span>
						<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">或</span>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">logger.warn()</span>
						<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">或</span>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">logger.error()</span>
						<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">里的信息。</span>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">%n</span>
						<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">表示回车空行。</span>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial; mso-no-proof: yes">③</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">再加上下面六行则</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">log</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">信息不光显示在屏幕上，而且将被保存在一个叫</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">"log.txt"</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">的文件里，文件最大为</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">100KB</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">。如果文件大小超过</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">100KB</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">，文件会被备份成</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">"log.txt.1"</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">，新的</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">"log.txt"</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">继续记录</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">log</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">信息。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">接下来我们可以改变</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">log4j.properties</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">，而不需重新编译就可以控制</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">log</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">信息是否显示、</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">log</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">信息的输出端类型、输出方式、输出格式，等等。举例如下：</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial; mso-no-proof: yes">①</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">在</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">log4j.properties</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">文件里把</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">"log4j.rootCategory=DEBUG,stdout,R"</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">改写成</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">"log4j.rootCategory=OFF, stdout,R"</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">，这样所有的</span>
				<span>log信息都不会显示了；解决了本文开始提出的问题。<br />②</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">在</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">log4j.properties</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">文件里把</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">"log4j.rootCategory=DEBUG,stdout,R"</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">改写成</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">"log4j.rootCategory=INFO, stdout,R"</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">，这样只显示</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">INFO, WARN, ERROR</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">的</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">log</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">信息，而</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">DEBUG</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Arial; mso-hansi-font-family: Arial; mso-ascii-font-family: Arial">信息不会被显示；</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: Arial">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt">
						<o:p>
								<font size="2">
								</font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l1 level1 lfo1; tab-stops: list 21.0pt">
				<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt">
						<font size="2">在<span lang="EN-US">web程序中使用log4j注意问题<o:p></o:p></span></font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 0cm; mso-list: l0 level1 lfo2; tab-stops: list 0cm">
				<font size="2">
						<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-bidi-font-size: 10.5pt">
								<span style="mso-list: Ignore">1、<span style="FONT: 7pt 'Times New Roman'">    </span></span>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt">由于<span lang="EN-US">jsp或servlet在执行状态时没有当前路径概念，所有使用</span></span>
						<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">PropertyConfigurator.configure</span>
						<span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'">（</span>
						<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">String</span>
						<span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'">）语句找</span>
						<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">log4j.properties</span>
						<span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'">文件时要给出相对于当前</span>
						<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">jsp</span>
						<span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'">或</span>
						<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">servlet</span>
						<span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'">的路径转化成为一个绝对的文件系统路径。方法是使用</span>
						<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">servletcontext.getrealpath(string)</span>
						<span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 10.5pt; mso-ascii-font-family: 'Times New Roman'">语句。例：</span>
						<span lang="EN-US" style="mso-bidi-font-size: 10.5pt">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Times New Roman'">//得到当前jsp路径</span>
				<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Times New Roman'">String prefix =<span style="mso-spacerun: yes">  </span>getServletContext().getRealPath(</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Times New Roman'">"/"<span style="COLOR: black">);<o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Times New Roman'">//读取</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Times New Roman'">log4j.properties</span>
				<span lang="EN-US" style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Times New Roman'">PropertyConfigurator.configure(prefix+</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Times New Roman'">"\\WEB-INF\\log4j.properties"<span style="COLOR: black">);<o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Times New Roman'">2、相应的log4j.properties设置某个属性时也要在程序中设置绝对路径。例：<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-hansi-font-family: 'Times New Roman'">log4j.appender.R.File属性设置日志文件存放位置。我们可以用读写.properties配置文件的方法进行灵活设置。<span style="COLOR: black"><o:p></o:p></span></span>
		</p>
<img src ="http://www.blogjava.net/19851985lili/aggbug/97641.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/19851985lili/" target="_blank">☜♥☞MengChuChen</a> 2007-02-02 20:30 <a href="http://www.blogjava.net/19851985lili/articles/97641.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Log4j简明手册（3/3） </title><link>http://www.blogjava.net/19851985lili/articles/91587.html</link><dc:creator>☜♥☞MengChuChen</dc:creator><author>☜♥☞MengChuChen</author><pubDate>Wed, 03 Jan 2007 09:04:00 GMT</pubDate><guid>http://www.blogjava.net/19851985lili/articles/91587.html</guid><wfw:comment>http://www.blogjava.net/19851985lili/comments/91587.html</wfw:comment><comments>http://www.blogjava.net/19851985lili/articles/91587.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/19851985lili/comments/commentRss/91587.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/19851985lili/services/trackbacks/91587.html</trackback:ping><description><![CDATA[
		<a href="http://blog.csdn.net/chensheng913/archive/2004/07/27/53799.aspx">
				<img height="13" src="http://blog.csdn.net/images/authorship.gif" width="15" border="0" />
				<font color="#000080"> Log4j简明手册（3/3）</font>
		</a>
		<div class="postText">
				<font color="#a52a2a" size="4">7. Nested Diagnostic Contexts<br /><br />在现实世界中的系统经常不得不同时处理多个客户端请求。在这样的一个典型的多线程的系统中，不同的线程将处理不同的客户端。Logging特别能够适应这种复杂的分布式的应用程序的调试和跟踪。一个常见的区分每个客户端所输出的Logging的方法是为每个客户端实例化一个新的独立的Logger。这导致Logger的大量产生，管理的成本也超过了logging本身。 <br /><br />唯一标识每个log请求是一个轻量级的技术。Neil Harrison 在名为“Patterns for Logging Diagnostic Messages”的书中描述了这个方法in Pattern Languages of Program Design 3, edited by R. Martin, D. Riehle, and F. Buschmann (Addison-Wesley, 1997). <br /><br />为了唯一标识每个请求，用户把上下文信息推入NDC(Nested Diagnostic Context)中。<br /><br />NDC类示例如下：<br /><br />public class NDC {<br /><br />// Used when printing the diagnostic<br /><br />public static String get();<br /><br />// Remove the top of the context from the NDC.<br /><br />public static String pop();<br /><br />// Add diagnostic context for the current thread.<br /><br />public static void push(String message);<br /><br />// Remove the diagnostic context for this thread.<br /><br />public static void remove();<br /><br />}<br /><br />NDC如同一个堆栈样管理每个线程。注意所有the org.apache.log4j.NDC 类的方法都是静态的。假设NDC输出被开启，每次一个log 请求被生成时，适当的log4j组件为将要输出log的线程包含完整的NDC堆栈。这是在没有用户的干预的情况下做到的，用户只负责在NDC中定位正确的信息，通过在代码中正确位置插入很少的push和pop方法就行了。相反的，在代码中per-client实现方法有着很大变化。<br /><br />为了演示这个点，让我们以一个发送内容到匿名客户端的servlet为例。这个servlet可以在开始执行每个其他代码前的初始化时建立NDC。上下文信息可以是客户主机的名字和其他的请求中固有的信息。<br /><br />典型的信息包括cookies。因此，即使servlet同时为多个客户同时提供服务，log 被同样的代码初始化，例如属于同一个logger，依然可以被区别，因为每个客户请求将有不同的NDC堆栈。与之相比，Contrast this with the complexity of passing a freshly instantiated logger to all code exercised during the client's request。<br /><br />不过，一些诡异的程序，例如虚拟主机的web server记录日志，不是一般的依靠虚拟主机的上下文，还要依靠软件的组件发出请求。近来log4j的发布版本支持多层的树形结构。这个增强允许每个虚拟主机可以处理在树型结构中属于它自己的logger。<br /><br />8. 优化<br />一个经常引用的依靠于logging的参数是可以计算的花费。这是一个合理的概念，一个适度的应用程序可能产生成千上万个日志请求。许多努力花在测量和调试logging的优化上。Log4j要求快速和弹性：速度最重要，弹性是其次。<br /><br />用户应该注意随后的优化建议。<br /><br />1.日志为禁用时，日志的优化。<br /><br />当日志被彻底的关闭，一个日志请求的花费等于一个方法的调用加上整数的比较时间。<br /><br />在233mhz的Pentium II 机器上这个花费通常在5-50纳秒之间。<br /><br />然而，方法调用包括参数构建的隐藏花费。<br /><br />例如，对于logger cat，<br /><br />logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));<br /><br />引起了构建信息参数的花费，例如，转化整数i和entry[i]到一个string，并且连接中间字符串，不管信息是否被输出。这个参数的构建花费可能是很高，它主要决定于被调用的参数的大小。<br /><br />避免参数构建的花费应如下，<br /><br />if(logger<br /><br />如果logger的debug被关闭这将不会招致参数构建的花费。另一方面，如果logger是debug的话，它将产生两次判断 logger是否能用的花费。一次是在debugenabled，一次是debug。这是无关紧要的，因为判断日志的能用 只占日志实际花费时间的约1%。<br /><br />在Log4j里，日志请求在Logger 类的实例里。Logger 是一个类，而不是一个接口。这大量的减少了在方法调用上的弹性化的花费。<br /><br />当然用户采用预处理或编译时间技术去编译出所有的日志声明。这将导致完美的执行成效。然而因为二进制应用程序不包括任何的日志声明的结果，日志不可能对那个二进制程序开启。以我的观点，以这种较大的代价来换取较小的性能优化是不值得的。<br /><br />2。当日志状态为启用时，日志的优化。<br /><br />这是本质上的优化logger的层次。当日志状态为开，Log4j依然需要比较请求的级别与logger的级别。然而， logger可能没有被安排一个级别；它们将从它们的father继承。这样，在继承之前，logger可能需要搜索它的ancestor。<br /><br />这里有一个认真的努力使层次的搜索尽可能的快。例如，子logger仅仅连接到它的存在的father logger。<br /><br />在先前展示的BasicConfigurator 例子中，名为com.foo.bar 的logger是连接到跟根logger，因此绕过 了不存在的logger com和com.foo。这将显著的改善执行的速度，特别是解析logger的层结构时。<br /><br />典型的层次结构的解析的花费是logger彻底关闭时的三倍。<br /><br />3.日志信息的输出时，日志的优化。<br /><br />这是主要花费在日志输出的格式化和发送它到它的输出源上。这里我们再一次的付出努力以使格式化执行的尽可能快。同appender一样。实际上典型的花费大约是100-300毫秒。<br /><br />详情看org.apache.log4.performance.Logging。<br /><br />虽然Log4j有许多特点，但是它的第一个设计目标还是速度。一些Log4j的组件已经被重写过很多次以改善性能。不过，投稿者经常提出了新的优化。你应该满意的知道，以SimpleLayout的配置执行测试已经展示了Log4j的输出同System.out.println一样快。<br /><br />9. 总结<br />Log4j是一个用java写成的流行的日志包。一个它与众不同的特点是在logger中的继承的概念。用logger的继承可以以任意的间隔控制日志的状态输出。这个减少了体积和最小化日志的代价。<br /><br />易管理性是Log4j API的优点之一。只要日志定义被加入到代码中，它们就可以用配置文件来控制。它们可以有选择的被禁用，并且发送到不同的多个输出源上，以用户选择好的格式。<br /><br />Log4j的包被设计成，不需花费沉重的执行代价就可以保留它们在产品中。</font>
		</div>
<img src ="http://www.blogjava.net/19851985lili/aggbug/91587.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/19851985lili/" target="_blank">☜♥☞MengChuChen</a> 2007-01-03 17:04 <a href="http://www.blogjava.net/19851985lili/articles/91587.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>g4j简明手册（2/3） </title><link>http://www.blogjava.net/19851985lili/articles/91585.html</link><dc:creator>☜♥☞MengChuChen</dc:creator><author>☜♥☞MengChuChen</author><pubDate>Wed, 03 Jan 2007 09:03:00 GMT</pubDate><guid>http://www.blogjava.net/19851985lili/articles/91585.html</guid><wfw:comment>http://www.blogjava.net/19851985lili/comments/91585.html</wfw:comment><comments>http://www.blogjava.net/19851985lili/articles/91585.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/19851985lili/comments/commentRss/91585.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/19851985lili/services/trackbacks/91585.html</trackback:ping><description><![CDATA[
		<font color="#a52a2a" size="4">4. 配置<br /><br />插入日志请求到应用程序的代码中需要大量的预先计划和最终努力。观察显示大约4%的代码是用来输出的。<br /><br />因此，大小适度的程序都被嵌入有成千个日志输出语句。为了以无需手工的方式管理这些日志的输出状态，给日志输出以编号和规范变得势在必行。 <br /><br />Log4j在程序中有充分的可配置性。然而，用配置文件配置Log4j具有更大的弹性。目前，它的配置文件支持xml和java properties（key=value）文件两种格式。<br /><br />让我们以一个例子来演示它是如何做的。假定有一个用了Log4j的程序MyApp。<br /><br /><br />import com.foo.Bar;<br /><br />// Import Log4j classes.<br /><br />import org.apache.Log4j.Logger;<br /><br />import org.apache.Log4j.BasicConfigurator;<br /><br />public class MyApp {<br /><br />// Define a static logger variable so that it references the<br /><br />// Logger instance named "MyApp".<br /><br />static Logger logger = Logger.getLogger(MyApp.class);<br /><br />public static void main(String[] args) {<br /><br />// Set up a simple configuration that logs on the console.<br /><br />BasicConfigurator.configure();<br /><br />logger.info("Entering application.");<br /><br />Bar bar = new Bar();<br /><br />bar.doIt();<br /><br />logger.info("Exiting application.");<br /><br />}<br /><br />}<br /><br />MyApp以引入Log4j的相关类开始，接着它定义了一个静态logger变量，并给予值为"MyApp"类的全路径名称。<br /><br />MYApp用了定义在包com.foo中的类Bar.<br /><br />package com.foo;<br /><br />import org.apache.Log4j.Logger;<br /><br />public class Bar {<br /><br />static Logger logger = Logger.getLogger(Bar.class);<br /><br />public void doIt() {<br /><br />logger.debug("Did it again!");<br /><br />}<br /><br />}<br /><br />调用BasicConfigurator.configure()方法创建了一个相当简单的Log4j的设置。它加入一<br /><br />个ConsoleAppender到根logger。输出将被采用了"%-4r [%t] %-5p %c %x - %m%n"模式<br /><br />的PatternLayout所格式化。<br /><br />注意，根logger默认被分配了Level.DEBUG的级别。<br /><br />MyApp的输出为：<br /><br />0 [main] INFO MyApp - Entering application.<br /><br />36 [main] DEBUG com.foo.Bar - Did it again!<br /><br />51 [main] INFO MyApp - Exiting application.<br /><br />随后的图形描述了在调用BasicConfigurator.configure()方法后MyApp的对象图。<br /><br /><br /><br /><br /><br />一边要提醒的是，Log4j的子logger只连接到已经存在的它们的父代。特别的是，名为<br /><br />com.foo.bar的logger是直接连接到根logger，而不是围绕着没用的com或com.foo<br /><br />logger。这显著的提高了程序性能并且减少的内存占用。<br /><br />MyApp类配置Log4j是通过调用BasicConfigurator.configure 方法。其它的类仅仅<br /><br />需要引入org.apache.Log4j.Logger 类，找到它们希望用的logger，并且用它就行。<br /><br />以前的例子通常输出同样的日志信息。幸运的是，修改MyApp是容易的，以便日志输<br /><br />出可以在运行时刻被控制。这里是一个小小修改的版本。<br /><br /><br /><br />import com.foo.Bar;<br /><br />import org.apache.Log4j.Logger;<br /><br />import org.apache.Log4j.PropertyConfigurator;<br /><br />public class MyApp {<br /><br />static Logger logger = Logger.getLogger(MyApp.class.getName());<br /><br />public static void main(String[] args) {<br /><br />// BasicConfigurator replaced with PropertyConfigurator.<br /><br />PropertyConfigurator.configure(args[0]);<br /><br />logger.info("Entering application.");<br /><br />Bar bar = new Bar();<br /><br />bar.doIt();<br /><br />logger.info("Exiting application.");<br /><br />}<br /><br />}<br /><br />修改后的 MyApp通知程序调用PropertyConfigurator()方法解析一个配置文件，并且根<br /><br />据这个配置文件来设置日志。<br /><br />这里是一个配置文件的例子，它将产生同以前BasicConfigurator 基本例子一样<br /><br />的输出结果。<br /><br /># Set root logger level to DEBUG and its only appender to A1.<br /><br />Log4j.rootLogger=DEBUG, A1<br /><br /># A1 is set to be a ConsoleAppender.<br /><br />Log4j.appender.A1=org.apache.Log4j.ConsoleAppender<br /><br /># A1 uses PatternLayout.<br /><br />Log4j.appender.A1.layout=org.apache.Log4j.PatternLayout<br /><br />Log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n<br /><br />假设我们不在对com.foo包的任何类的输出感兴趣的话，随后的配置文件向我们展示<br /><br />了实现这个目的的方法之一。<br /><br />Log4j.rootLogger=DEBUG, A1<br /><br />Log4j.appender.A1=org.apache.Log4j.ConsoleAppender<br /><br />Log4j.appender.A1.layout=org.apache.Log4j.PatternLayout<br /><br /># Print the date in ISO 8601 format<br /><br />Log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n<br /><br /># Print only messages of level WARN or above in the package com.foo.<br /><br />Log4j.logger.com.foo=WARN<br /><br />以这个配置文件配置好的MyApp将输出如下：<br /><br />2000-09-07 14:07:41,508 [main] INFO MyApp - Entering application.<br /><br />2000-09-07 14:07:41,529 [main] INFO MyApp - Exiting application.<br /><br />当logger com.foo.bar没有被分配一个级别，它将从com.foo继承，在配置文件中<br /><br />它被设置了WARN的级别。在Bar.doIt方法中定义的log为DEBUG级别，低于WARN，<br /><br />因此doIt() 方法的日志请求被禁用。<br /><br />这里是另外一个配置文件，它使用了多个appenders.<br /><br />Log4j.rootLogger=debug, stdout, R<br /><br />Log4j.appender.stdout=org.apache.Log4j.ConsoleAppender<br /><br />Log4j.appender.stdout.layout=org.apache.Log4j.PatternLayout<br /><br /># Pattern to output the caller's file name and line number.<br /><br />Log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n<br /><br />Log4j.appender.R=org.apache.Log4j.RollingFileAppender<br /><br />Log4j.appender.R.File=example.log<br /><br />Log4j.appender.R.MaxFileSize=100KB<br /><br /># Keep one backup file<br /><br />Log4j.appender.R.MaxBackupIndex=1<br /><br />Log4j.appender.R.layout=org.apache.Log4j.PatternLayout<br /><br />Log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n<br /><br />以这个配置文件调用加强了的MyApp类将输出如下信息.<br /><br />INFO [main] (MyApp2.java:12) - Entering application.<br /><br />DEBUG [main] (Bar.java:8) - Doing it again!<br /><br />INFO [main] (MyApp2.java:15) - Exiting application.<br /><br />另外,因为根logger有被分配第二个appender,所以输出也将被定向到example.log文件。<br /><br />这个文件大小达到100kb时将自动备份。备份时老版本的example.log文件自动被移到<br /><br />文件example.log.1中。<br /><br />注意我们不需要重新编译代码就可以获得这些不同的日志行为。我们一样可以容易<br /><br />的使日志输出到UNIX Syslog daemon, 重定向所有的com.foo到NT Event logger,<br /><br />或者转发日志到一个远程的Log4j服务器,它根据本地server的策略来进行日志输出。例<br /><br />如转发日志事件到第二个Log4j服务器.<br /><br /><br /><br />5. 默认的初始化过程<br />Log4j类库不对它的环境做任何假设。特别是没有默认的Log4j appender。在一些特别<br /><br />的有着良好定义的环境下，logger的静态inializer将尝试自动的配置Log4j。<br /><br />java语言的特性保证类的静态initializer当且仅当装载类到内存之时只会被调用一次。<br /><br />要记住的重要一点是，不同的类装载器可能装载同一个类的完全不同的拷贝。<br /><br />这些同样类的拷贝被虚拟机认为是完全不相干的。<br /><br />默认的initialization是非常有用的，特别是在一些应用程序所依靠的运行环境被准确的<br /><br />定位的情况下。例如，同一样的应用程序可以被用做一个标准的应用程序，或一个<br /><br />applet，或一个在web-server控制下的servlet。<br /><br />准确的默认的initialization原理被定义如下：<br /><br />1.设置系统属性Log4j.defaultInitOverride为"false"以外的其它值，那么Log4j将<br /><br />跳过默认的initialization过程。<br /><br />2.设置资源变量字符串给系统属性Log4j.configuration。定义默认initialization<br /><br />文件的最好的方法是通过系统属性Log4j.configuration。万一系统属性<br /><br />Log4j.configuration没有被定义，那么设置字符串变量resource 给它的默认值<br /><br />Log4j.properties。<br /><br />3.尝试转换resource 变量为一个URL。<br /><br />4.如果变量resource的值不能被转换为一个URL，例如由于MalformedURLException违<br /><br />例，那么通过调用<br /><br />org.apache.Log4j.helpers.Loader.getResource(resource, Logger.class) 方法从<br /><br />classpath中搜索resource，它将返回一个URL，并通知"Log4j.properties"的值是一个错<br /><br />误的URL。<br /><br />看See Loader.getResource(java.lang.String) 查看搜索位置的列表。<br /><br />5.如果没有URL被发现，那么放弃默认的initialization。否则用URL配置Log4j。<br /><br />PropertyConfigurator将用来解析URL，配置Log4j，除非URL以".xml"为结尾。<br /><br />在这种情况下的话DOMConfigurator将被调用。你可以有机会定义一个自定义的<br /><br />configurator。<br /><br />系统属性Log4j.configuratorClass 的值取自你的自定义的类名的全路径。<br /><br />你自定义的configurator必须实现configurator接口。<br /><br /><br /><br />6. 配置范例<br />6.1 Tomcat下的初始化<br />默认的Log4j initialization典型的应用是在web-server 环境下。在tomcat3.x和tomcat4.x<br /><br />下，你应该将配置文件Log4j.properties放在你的web应用程序的WEB-INF/classes 目录<br /><br />下。<br /><br />Log4j将发现属性文件，并且以此初始化。这是使它工作的最容易的方法。<br /><br />你也可以选择在运行tomcat前设置系统属性Log4j.configuration 。对于tomcat 3.x，<br /><br />TOMCAT_OPTS 系统变量是用来设置命令行的选项。对于tomcat4.0，用系统环境变<br /><br />量CATALINA_OPTS 代替了TOMCAT_OPTS。<br /><br />Example 1 <br /><br />UNIX 命令行<br /><br />export TOMCAT_OPTS="-DLog4j.configuration=foobar.txt"<br /><br />告诉Log4j用文件foobar.txt作为默认的配置文件。这个文件应该放在WEB-INF/classes <br /><br />目录下。这个文件将被PropertyConfigurator所读。每个web-application将用不同的默认<br /><br />配置文件，因为每个文件是和它的web-application 相关的。<br /><br />Example 2 <br /><br />UNIX 命令行<br /><br />export TOMCAT_OPTS="-DLog4j.debug -DLog4j.configuration=foobar.xml"<br /><br />告诉Log4j输出Log4j-internal的调试信息，并且用foobar.xml作为默认的配置文件。<br /><br />这个文件应该放在你的web-application的WEB-INF/classes 目录下。因为有.xml的<br /><br />扩展名，它将被DOMConfigurator所读。每个web-application将用不同的默认<br /><br />配置文件。因为每个文件都和它所在的web-application 相关的。<br /><br />Example 3 <br /><br />UNIX 命令行<br /><br />set TOMCAT_OPTS=-DLog4j.configuration=foobar.lcf -DLog4j.configuratorClass=com.foo.BarConfigurator<br /><br />告诉Log4j用文件foobar.lcf作为默认的配置文件。这个文件应该放在你的<br /><br />web-application的WEB-INF/classes 目录下。因为定义了Log4j.configuratorClass 系统属<br /><br />性，文件将用自定义的com.foo.barconfigurator类来解析。每个web-application将用不<br /><br />同的默认配置文件。因为每个文件都和它所在的web-application 相关的。<br /><br />Example 4 <br /><br />UNIX 命令行<br /><br />set TOMCAT_OPTS=-DLog4j.configuration=file:/c:/foobar.lcf<br /><br />告诉Log4j用文件foobar.lcf作为默认的配置文件。这个配置文件用URL file:/c:/foobar.lcf<br /><br />定义了全路径名。这样同样的配置文件将被所有的web-application所用。<br /><br />不同的web-application将通过它们自己的类装载器来装载Log4j。这样，每个Log4j的环<br /><br />境将独立的运作，而没有任何的相互同步。例如：在多个web-application中定义了<br /><br />完全相同的输出源的FileAppenders将尝试写同样的文件。结果好象是缺乏安全性的。<br /><br />你必须确保每个不同的web-application的Log4j配置没有用到同样的系统资源。<br /><br /><br /><br />6.2 Servlet 的初始化<br />用一个特别的servlet来做Log4j的初始化也是可以的。如下是一个例子：<br /><br />package com.foo;<br /><br />import org.apache.Log4j.PropertyConfigurator;<br /><br />import javax.servlet.http.HttpServlet;<br /><br />import javax.servlet.http.HttpServletRequest;<br /><br />import javax.servlet.http.HttpServletResponse;<br /><br />import java.io.PrintWriter;<br /><br />import java.io.IOException;<br /><br />public class Log4jInit extends HttpServlet {<br /><br />public void init() {<br /><br />String prefix = getServletContext().getRealPath("/");<br /><br />String file = getInitParameter("Log4j-init-file");<br /><br />// if the Log4j-init-file is not set, then no point in trying<br /><br />if(file != null) {<br /><br />PropertyConfigurator.configure(prefix+file);<br /><br />}<br /><br />}<br /><br />public void doGet(HttpServletRequest req, HttpServletResponse res) {<br /><br />}<br /><br />}<br /><br />在web.xml中定义随后的servlet为你的web-application。<br /><br /><servlet><br /><br /><servlet-name>Log4j-init</servlet-name><br /><br /><servlet-class>com.foo.Log4jInit</servlet-class><br /><br /><init-param><br /><br /><param-name>Log4j-init-file</param-name><br /><br /><param-value>WEB-INF/classes/Log4j.lcf</param-value><br /><br /></init-param><br /><br /><load-on-startup>1</load-on-startup><br /><br /></servlet><br /><br />写一个初始化的servlet是最有弹性的初始化Log4j的方法。代码中没有任何限制，你可<br /><br />以在servlet的init方法中定义它。</font>
		<br />
		<br />
		<br />
<img src ="http://www.blogjava.net/19851985lili/aggbug/91585.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/19851985lili/" target="_blank">☜♥☞MengChuChen</a> 2007-01-03 17:03 <a href="http://www.blogjava.net/19851985lili/articles/91585.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Log4j简明手册1</title><link>http://www.blogjava.net/19851985lili/articles/91583.html</link><dc:creator>☜♥☞MengChuChen</dc:creator><author>☜♥☞MengChuChen</author><pubDate>Wed, 03 Jan 2007 09:00:00 GMT</pubDate><guid>http://www.blogjava.net/19851985lili/articles/91583.html</guid><wfw:comment>http://www.blogjava.net/19851985lili/comments/91583.html</wfw:comment><comments>http://www.blogjava.net/19851985lili/articles/91583.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/19851985lili/comments/commentRss/91583.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/19851985lili/services/trackbacks/91583.html</trackback:ping><description><![CDATA[
		<font color="#a52a2a" size="4">Log4j简明手册<br /><br />1. 概述<br />本文主要描述Log4j的API的唯一特性和它的设计原理。Log4j是一个基于许多作者的开放源码的项目。它允许开发员以任意的间隔来控制日志的输出。它通过设在外部的配置文件而达到运行时灵活的设置。最重要的是，Log4j有一个平稳的学习曲线。注意：根据来自用户的反馈判断，它很容易使人上瘾。<br /><br />2. 导言<br /><br />几乎所有的大型应用程序都包括它的自己的日志和跟踪API。顺应这个规则，E.U. SEMPER 项目决定写它自己的跟踪PAI。这是1996年初。在无数次加强，几次变形和许多工作后，那个API变成了如今的Log4j，一个流行的java日志包。这个包以Apache Software License协议发布，一个成熟的开放源吗协议。最新的Log4j版本，包括全部的源码，class文件和文档，你可以在http://jakarta.apache.org/Log4j/上找到。顺便，Log4j已经给C, C++, C#, Python, Ruby, and Eiffel 语言都提供了接口。<br /><br />为了调试而插入日志输出到代码里是一个低技术成分的方法，但它可能也是唯一的方法，因为调试器并不是一直可用或者可以适应的，尤其对于多线程的分布使式的大型程序而言。<br /><br />经验指出调试是软件开发周期中一个重要的组成部分。<br /><br />Log4j拥有几个优点：<br /><br />首先，它提供关于运行程序的准确的环境。一旦代码被插入，不需要人工干预就可以产生调试信息。<br /><br />其次，日志输出可以被有计划的保存在永久媒体中以便日后研究。<br /><br />另外，除了在开发周期中，一个充分详尽的日志包可以被用来作为以后的统计工具。<br /><br />Log4j当然还有它的缺点，它可能减慢程序。如果太详细，它可能导致屏幕盲目滚动。排除这些情况，Log4j是可靠的，快速的，可以扩展的。因为日志很少是一个应用程序的主要目的, 设计者们正努力使得Log4j API学习和使用简单化。<br /><br />3. 日志类别、输出源和布局<br /><br />Log4j有三个主要的组件：日志类别（Loggers）、输出源（ Appenders）和布局（Layouts）。这三种类型的组件一起工作使得开发员可以根据信息的类型和级别记录它们，并且在运行时控制这些信息的输出格式和位置。<br /><br />3.1 日志类别的层次结构(Loggers)<br /><br />Log4j首要的相对于简单的使用System.out.println()方法的优点是基于它的在禁止一些特定的信息输出的同时不妨碍其它信息的输出的能力。这个能力源自于日志命名空间，也就是说，所有日志声明的空间，它根据一些开发员选择的公式而分类。以前的观察引导我们选择类别作为包的中心概念。然而，自从Log4j的1.2版本，Logger类被Catalog类所取代，对于那些熟悉Log4j以前版本的人来说，Logger类可以被想象成仅仅是Category 类的别名。<br /><br />Loggers 被指定为实体，Logger的名字是大小写敏感的，它们遵循以下的命名<br /><br />规则：<br /><br />2 命名继承<br /><br />如果类别的名称（后面加一个点）是其子类别名称的前缀，则它就是另一个类别的祖辈。<br /><br />如果一个类别(Logger)和它的子类别之间没有其它的继承关系，我们就称之为parent与child的关系。<br /><br />例如，类别"com.foo"是类别"com.foo.Bar"的parent。相似的，"java"是"java.util"的parent，是"java.util.Vector"的父辈。.这个命名规则应该被大多数的开发员所熟悉。<br /><br />根(root) 类别位于logger继承结构的最上层。它有两种例外：<br /><br />1.它一直存在<br /><br />2.它不能根据名称而获得。 <br /><br />调用类的静态方法Logger.getRootLogger可以得到它。其它所有的Logger可以通过静态方法Logger.getLogger而得到它们自己的实例。这个方法取希望的Logger名作为参数。Logger的一些基本的方法示例如下：<br /><br />package org.apache.Log4j;<br /><br />public Logger class {<br /><br />// Creation &amp; retrieval methods:<br /><br />public static Logger getRootLogger();<br /><br />public static Logger getLogger(String name);<br /><br />// printing methods:<br /><br />public void debug(Object message);<br /><br />public void info(Object message);<br /><br />public void warn(Object message);<br /><br />public void error(Object message);<br /><br />// generic printing method:<br /><br />public void log(Level l, Object message);<br /><br />}<br /><br />Loggers可以被分配的级别。所有级别的集合包括：<br /><br />DEBUG<br /><br />INFO<br /><br />WARN<br /><br />ERROR<br /><br />FATAL<br /><br />它们被定义于org.apache.Log4j.Level 类。虽然我们不鼓励，但是你们可以通过继承Level类来定义你们自己的级别。我们随后将介绍一个比较好的方法。<br /><br />如果一个Logger没有被分配一个级别，那么它将从一个被分配了级别的最接近它的ancestor哪里继承。<br /><br />正规的说：<br /><br />2 级别继承<br /><br />对于一个给定的Logger C，它的继承的级别等于从C开始上溯到的第一个拥有非空级别的Logger的级别。<br /><br />为了保证所有的Logger最终能够继承到一个级别，根Logger通常有一个已经定义了的级别。<br /><br />以下四个表中的数据演示了根据以上规则得到的结果。<br /><br />类别名<br />分配的级别<br />继承的级别<br /><br />root<br />Proot<br />Proot<br /><br />X <br />none<br />Proot<br /><br />X.Y <br />none<br />Proot<br /><br />X.Y.Z<br />none<br />Proot<br /><br />Example 1<br /><br /><br /><br />在例子1中，只有根Logger定义了一个级别，它的级别的值--"Proot"被所有其它的Loggers X, X.Y, 和X.Y.Z所继承。<br /><br />类别名<br />分配的级别<br />继承的级别<br /><br />root<br />Proot<br />Proot<br /><br />X <br />Px<br />Px<br /><br />X.Y <br />Pxy<br />Pxy<br /><br />X.Y.Z<br />Pxyz<br />Pxyz<br /><br />Example 2<br /><br /><br /><br />在例子2中，所有的Logger都有一个被分配的级别值，所以它们不需要级别继承。<br /><br />类别名<br />分配的级别<br />继承的级别<br /><br />root<br />Proot<br />Proot<br /><br />X <br />Px<br />Px<br /><br />X.Y <br />none<br />Px<br /><br />X.Y.Z<br />Pxyz<br />Pxyz<br /><br />Example 3<br /><br /><br /><br />在例子3中，根Logger，以及X和X.Y.Z被分别分配了级别Proot，Px和Pxyz。Logger X.Y从它的parent X继承了级别值Px。<br /><br />类别名<br />分配的级别<br />继承的级别<br /><br />root<br />Proot<br />Proot<br /><br />X <br />Px<br />Px<br /><br />X.Y <br />none<br />Px<br /><br />X.Y.Z<br />none<br />Px<br /><br />Example 4<br /><br /><br /><br />在例子4中，根Logger和X被分别分配了级别"Proot"和"Px"，Logger X.Y 和 X.Y.Z从被分配了级别的最接近它们的ancestor X那里得到继承。<br /><br />我们需要通过调用Logger的输出的实例方法之一来实现日志请求。这些输出的方法是debug, info, warn, error, fatal 和 log.<br /><br />通过定义输出方法来区分日志的请求的级别。例如，如果c是一个Logger的实例，那么声明 c.info 就是一个INFO级别的日志请求。<br /><br />如果一个日志的请求的级别高于或等于日志的级别那么它就能被启用。反之，将被禁用。一个没有被安排级别的Logger将从它的父辈中得到继承。这个规则总结如下。<br /><br />2 基本的选择规则<br /><br />假如在一个级别为q的Logger中发生一个级别为p的日志请求，如果p&gt;=q,那么请求将被启用。<br /><br />这是Log4j的核心原则。它假设级别是有序的。对于标准级别，我们定义DEBUG &lt; INFO &lt; WARN &lt; ERROR &lt; FATAL. <br /><br />以下是关于这条规则的一个例子。<br /><br />// get a logger instance named "com.foo"<br /><br />Logger logger = Logger.getLogger("com.foo");<br /><br />// Now set its level. Normally you do not need to set the <br /><br />// level of a logger progamitcally. This is usually done <br /><br />// in configuration files.<br /><br />cat.setLevel(Level.INFO);<br /><br />Logger barlogger = Logger.getLogger("com.foo.Bar");<br /><br />// This request is enabled, because WARN &gt;= INFO.<br /><br />logger.warn("Low fuel level.");<br /><br />// This request is disabled, because DEBUG &lt; INFO.<br /><br />logger.debug("Starting search for nearest gas station."); <br /><br />// The logger instance barlogger, named "com.foo.Bar",<br /><br />// will inherit its level from the logger named <br /><br />// "com.foo" Thus, the following request is enabled <br /><br />// because INFO &gt;= INFO. <br /><br />barlogger.info("Located nearest gas station."); <br /><br />// This request is disabled, because DEBUG &lt; INFO.<br /><br />barlogger.debug("Exiting gas station search"); <br /><br />调用getLogger方法将返回一个同名的Logger对象的实例。<br /><br />例如，<br /><br />Categoty x = Logger.getLogger("wombat");<br /><br />Categoty y = Logger.getLogger("wombat");<br /><br />x和y参照的是同一个Logger对象。<br /><br />这样我们就可以先定义一个Logger，然后在代码的其它地方不需传参就可以重新得到我们已经定义了的Logger的实例.<br /><br />同基本的生物学理论--父先于子相反，Log4j 的loggers可以以任何顺序创造和配置。特别是，一个后实例化的"parent"logger能够找到并且连接它的子logger。<br /><br />配置Log4j的环境通常在一个应用程序被初始化的时候进行，最好的方法是通过读一个配置文件。这个方法我们将简短介绍。<br /><br />Log4j使得通过软件组件命名logger很容易。我们可以通过Logger的静态的初始化方法在每一个类里定义一个logger，令logger的名字等于类名的全局名，而实现logger的命名。这是一个实效的简单的定义一个logger的方法。因为日志输出带有产生日志的类的名字，这个命名策略使得我们更容易定位到一个日志信息的来源。虽然普通，但却是命名logger的常用策略之一。Log4j没有限制定义logger的可能。开发员可以自由的按照它们的意愿定义logger的名称。<br /><br />然而，以类的所在位置来命名Logger好象是目前已知的最好方法。<br /><br />3.2 输出源（Appenders）和布局（Layouts）<br /><br />有选择的能用或者禁用日志请求仅仅是Log4j的一部分功能。Log4j允许日志请求被输出到多个输出源。用Log4j的话说，一个输出源被称做一个Appender. 。Appender包括console（控制台）, files（文件）, GUI components（图形的组件）, remote socket servers（socket 服务）, JMS（java信息服务）, NT Event Loggers（NT的事件日志）, and remote UNIX Syslog daemons（远程UNIX的后台日志服务）。它也可以做到异步记录。<br /><br />一个logger可以设置超过一个的appender。<br /><br />用addAppender 方法添加一个appender到一个给定的logger。对于一个给定的logger它每个生效的日志请求都被转发到该logger所有的appender上和该logger的父辈logger的appender上。换句话说，appender自动从它的父辈获得继承。举例来说，如果一个根logger拥有一个console appender，那么所有生效的日志请求至少会被输出到console上。如果一个名为C的logger有一个file类型的appender，那么它就会对它自己以及所有它的子logger生效。我们也可以通过设置appender的additivity flag 为false，来重载appender的默认行为，以便继承的属性不在生效。<br /><br />调节输出源（appender）添加性的规则如下。<br /><br />输出源的可添加性（Appender Additivity ）<br /><br />一个名为C的logger的日志定义的输出将延续到它自身以及它的ancestor logger的appenders。这就是术语"appender additivity"的含义。 <br /><br />然而，logger C的一个ancestor logger P，它的附加标志被设为false，那么C的输出将被定位到所有C的appender，以及从它开始上溯到P的所有ancestor logger的appender。<br /><br />Loggers的附加标记（additivity flag）默认为true。<br /><br />下表是一个例子。<br /><br />Logger<br />Name <br />Added<br />Appenders <br />Additivity<br />Flag <br />Output Targets <br />Comment <br /><br />root <br />A1 <br />not applicable <br />A1 <br />The root logger is anonymous but can be accessed with the Logger.getRootLogger() method. There is no default appender attached to root. <br /><br />x <br />A-x1, A-x2 <br />true <br />A1, A-x1, A-x2 <br />Appenders of "x" and root. <br /><br />x.y <br />none <br />true <br />A1, A-x1, A-x2 <br />Appenders of "x" and root. <br /><br />x.y.z <br />A-xyz1 <br />true <br />A1, A-x1, A-x2, A-xyz1 <br />Appenders in "x.y.z", "x" and root. <br /><br />security <br />A-sec <br />false <br />A-sec <br />No appender accumulation since the additivity flag is set to false. <br /><br />security.access <br />none <br />true <br />A-sec <br />Only appenders of "security" because the additivity flag in "security" is set to false. <br /><br /><br />经常，用户希望自定义不但输出源，而且定义输出格式。这个是通过在一个appender上附加一个layout来完成的。layout是负责根据用户的希望来格式化日志请求。而appender是负责发送格式化的输出到它的目的地。PatternLayout，作为Log4j标准版中的一部分，让用户指以类似C语言的printf方法的格式来指定日志的输出格式。<br /><br />例如，转化模式为"%r [%t] %-5p %c - %m%n" 的PatternLayout 将输出类似如下的信息：<br /><br />176 [main] INFO org.foo.Bar - Located nearest gas station.<br /><br />第一个栏位是自从程序开始后消逝的毫秒数。<br /><br />第二个栏位是做出日志的线程。<br /><br />第三个栏位是log的级别。<br /><br />第四个栏位是日志请求相关的logger的名字。而"-"后的文字是信息的表述。<br /><br />Log4j将根据用户定义的公式来修饰日志信息的内容。例如，如果你经常需要记录Oranges，一个在你当前的项目被用到的对象类型，那么你可以注册一个OrangeRenderer ，它将在一个orange需要被记录时被调用。<br /><br />对象渲染类似的类的结构继承。例如，假设oranges是fruits，如果你注册了一个FruitRenderer，所有的水果包括oranges将被FruitRenderer所渲染。除非你注册了一个orange。<br /><br />对象渲染必须实现ObjectRenderer接口。</font>
<img src ="http://www.blogjava.net/19851985lili/aggbug/91583.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/19851985lili/" target="_blank">☜♥☞MengChuChen</a> 2007-01-03 17:00 <a href="http://www.blogjava.net/19851985lili/articles/91583.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java中的日志操作方法---Log4J </title><link>http://www.blogjava.net/19851985lili/articles/91576.html</link><dc:creator>☜♥☞MengChuChen</dc:creator><author>☜♥☞MengChuChen</author><pubDate>Wed, 03 Jan 2007 08:46:00 GMT</pubDate><guid>http://www.blogjava.net/19851985lili/articles/91576.html</guid><wfw:comment>http://www.blogjava.net/19851985lili/comments/91576.html</wfw:comment><comments>http://www.blogjava.net/19851985lili/articles/91576.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/19851985lili/comments/commentRss/91576.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/19851985lili/services/trackbacks/91576.html</trackback:ping><description><![CDATA[在应用程序中输出日志有有三个目的： 
<p>（1）监视代码中变量的变化情况，把数据周期性地记录到文件中供其他应用进行统计分析工作。</p><p>（2）跟踪代码运行进轨迹，作为日后审计的依据。</p><p>（3）担当集成开发环境中的调试器，向文件或控制台打印代码的调试信息。</p><p>　　Apache能用日志包（Commons Logging Package）是Apache的一个开放源代码项目，它提供了一组通用的日志接口，用户可以自由地选择实现日志接口的第三方软件。通用日志包目前支持以下日志实现：</p><ul><li>Log4J日志器（<a href="http://jakarta.apache.org/log4j"><font color="#002c99">http://jakarta.apache.org/log4j</font></a>） 
</li><li>JDK1.4 Logging日志器(JDK1.4自带) 
</li><li>SimpleLog日志器(把日志消息输出到标准系统错误流System.err) 
</li><li>NoOpLog(不输出任何日志信息)</li></ul><p>通用日志包中的两个常用接口：LogFactory和Log，分别介绍如下：</p><ul><li>Log接口</li></ul><p>通用日志包把消息分为6个级别：FATAL、ERROR、WARN、INFO、DEBUG和TRACE。其中FATAL级别最高，TRACE级别最低。Log接口提供输出不同级别消息的方法：</p><p>fatal(Object message)-------输出FATAL级别的消息。</p><p>error(Object message)-------输出ERROR级别的消息。</p><p>warn(Object message)-------输出WARN级别的消息。</p><p>info(Object message)-------输出INFO级别的消息。</p><p>debug(Object message)-------输出DEBUG级别的消息。</p><p>trace(Object message)-------输出TRACE级别的消息。</p><p>注：只有当输出日志的级别大于或等于为日志配置器配置的日志级别时，这个方法才会执行。</p><p>　　如何指定日志器的日志级别，不同的日志器实现会有不同的实现方案。</p><ul><li>LogFactory接口</li></ul><p>LogFactory接口提供了获得日志器实例的两个静态方法：</p><p>public static Log getLog(String name) throws LogConfigurationException;</p><p>public static Log getLog(Class class) throws LogConfigurationException;</p><p>注：name参数作为日志器的名字；class参数指定类名作为日志器名字。</p><p><font size="4">以下介绍最常用的一个<strong>日志实现--------Log4J</strong></font></p><p><strong>　　Log4j</strong>是Apache的一个开放源代码项目，它是一个日志操作包。通过使用Log4j，我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等；我们也可以控制每一条日志的输出格式；通过定义每一条日志信息的级别，我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是，这些可以通过一个配置文件来灵活地进行配置，而不需要修改应用的代码。<br />此外，通过Log4j其他语言接口，您可以在C、C++、.Net、PL/SQL程序中使用Log4j，其语法和用法与在Java程序中一样，使得多语言分布式系统得到一个统一一致的日志组件模块。而且，通过使用各种第三方扩展，您可以很方便地将Log4j集成到J2EE、JINI甚至是SNMP应用中。</p><p>　　Log4J主要由三大组件构成：</p><ul><li>Logger：负责生成日志，并能根据配置的日志级别来决定什么日志消息应该被输出，什么日志消息应该被忽略。 
</li><li>Appender：定义日志消息输出的目的地，指定日志消息应该被输出到什么地方，这些地方可以是控制台、文件和网络设备等。 
</li><li>Layout：指定日志消息的输出格式。</li></ul><p>　　这三个组件协同工作，使得开发者能够依据日志消息类别来输出日志，并能够在程序运行期间，控制日志消息的输出格式以及日志存放地点。</p><p>　　<font size="4"><strong>Log4J的配置</strong></font></p><p><font size="3">　　</font><font size="2">配置Log4J，需要分别配置它的Logger、Appender和Layout属性。配置文件一般为log4j.properties。当然也可以以XML文件来配置，这里介绍以属性文件配置。</font></p><ul><li>配置Logger组件</li></ul><p>Logger组件支持继承关系，所有的Logger组件都直接或间接继承rootLogger。配置rootLogger的语法为：</p><p>　　log4j.rootLogger=[priority]，appenderName，appenderName，......</p><p>priority是如前所述的日志级别；</p><p>appenderName指定Appender组件，用户可以同时指定多个Appender组件，以与逗号分隔。</p><ul><li>配置Appender组件</li></ul><p>配置日志消息输出目的地Appender，语法为：</p><p>　　log4j.appender.appenderName=&lt;appender的完整类名&gt;</p><p>　　log4j.appender.appenderName.option1=value1</p><p>　　log4j.appender.appenderName.option2=value2</p><p>　　...</p><p>Log4J共有以下几种Appender:</p><p>　　org.apache.log4j.ConsoleAppender(控制台)</p><p>　　org.apache.log4j.FileAppender(文件)</p><p>　　org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)</p><p>　　org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)</p><p>　　org.apache.log4j.WriterAppender(将日志消息以流格式发送到任意指定的地方)</p><ul><li>配置Layout组件</li></ul><p>语法：</p><p>　　　log4j.appender.appenderName.layout=&lt;layout的完整类名&gt;</p><p>　　　log4j.appender.appenderName.layout.option1=value1</p><p>　　　log4j.appender.appenderName.layout.option2=value2</p><p>　　　...</p><p>Log4J提供以下几种Layout：</p><p>　　org.apache.log4j.HTMLLayout(以HTML表格形式布局)</p><p>　　org.apache.log4j.PatternLayout(可以灵活地指定布局模式)</p><p>　　org.apache.log4j.SimpleLayout(包含日志消息的级别和信息字符串)</p><p>　　org.apache.log4j.TTCCLayout(包含日志产生的时间、线程和类别等信息)</p><p><font size="2">通过设置PatternLayout的ConversionPattern属性来指定输出格式</font></p><p><font size="2">ConversionPattern</font>的格式如下表所示：</p><p></p><p><font size="2">格式名 　　　　　含义<br />%c 　　　　　 输出日志信息所属的类的全名<br />%d　　　　　 输出日志时间点的日期或时间，默认格式为ISO8601，也可以在其后指定格式，比如：</font></p><p><font size="2">                            %d{yyy-MM-dd HH:mm:ss }，输出类似：2002-10-18- 22：10：28<br />%f 　　　　　 输出日志信息所属的类的类名<br />%l 　　　　　 输出日志事件的发生位置，即输出日志信息的语句处于它所在的类的第几行<br />%m 　　　　   输出代码中指定的信息，如log(message)中的message<br />%n 　　　　　输出一个回车换行符，Windows平台为“\r\n”，Unix平台为“\n”<br />%p 　　　　　输出优先级，即DEBUG，INFO，WARN，ERROR，FATAL。如果是调用debug()输出的，则为DEBUG，依此类推<br />%r 　　　　　输出自应用启动到输出该日志信息所耗费的毫秒数<br />%t 　　　　　输出产生该日志事件的线程名</font></p><p><font size="2"></font><br /><font size="2">示例：log4j.appender.file.layout=org.apache.log4j.PatternLayout</font></p><p><font size="2">　　　log4j.appender.file.layout.ConversionPattern=%t %p- %m%n</font></p><p><font size="2">Log4J对应用性能的影响</font></p><p><font size="2">　　如果在程序运行中输出大量日志，显然会对应用的性能造成一定的影响。Log4J对性能的影响取决于以下因素：</font></p><ul><li><font size="2">日志输出目的地：输出到控制台的速度和输出到文件系统的速度是不一样的。</font></li><li><font size="2">日志输出格式：格式简单，速度也更快。</font></li><li><font size="2">日志级别：日志级别设置的越低，输出的日志内容越多，对性能的影响也越大。</font></li></ul><img src ="http://www.blogjava.net/19851985lili/aggbug/91576.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/19851985lili/" target="_blank">☜♥☞MengChuChen</a> 2007-01-03 16:46 <a href="http://www.blogjava.net/19851985lili/articles/91576.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Log4j进行日志操作续</title><link>http://www.blogjava.net/19851985lili/articles/91572.html</link><dc:creator>☜♥☞MengChuChen</dc:creator><author>☜♥☞MengChuChen</author><pubDate>Wed, 03 Jan 2007 08:38:00 GMT</pubDate><guid>http://www.blogjava.net/19851985lili/articles/91572.html</guid><wfw:comment>http://www.blogjava.net/19851985lili/comments/91572.html</wfw:comment><comments>http://www.blogjava.net/19851985lili/articles/91572.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/19851985lili/comments/commentRss/91572.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/19851985lili/services/trackbacks/91572.html</trackback:ping><description><![CDATA[
		<p>
				<b>2.2.2. 服务器程序</b>
		</p>
		<p>
		</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">package log4j;

import java.util.* ;
import java.io.* ;
import java.net.* ;

// add for log4j: import some package
import org.apache.log4j.PropertyConfigurator ;
import org.apache.log4j.Logger ;
import org.apache.log4j.Level ;

/**
 *
 * &lt;p&gt; Server With Log4j &lt;/p&gt;
 * &lt;p&gt; Description: a sample with log4j&lt;/p&gt;
 * @version 1.0
 */
public class ServerWithLog4j {

    final static int SERVER_PORT = 8001 ; // this server's port

    /*
    add for log4j: class Logger is the central class in the log4j package.
    we can do most logging operations by Logger except configuration.
    getLogger(...): retrieve a logger by name, if not then create for it.
    */
    static Logger logger = Logger.getLogger 
	( ServerWithLog4j.class.getName () ) ;

    /**
     *
     * @param args
     */
    public static void main ( String args[]) {
        String clientRequest = null ;
        BufferedReader reader = null ;
        PrintWriter writer = null ;
        ServerSocket server = null ;
        Socket socket = null ;

        InputStream in = null ;
        OutputStream out = null ;

        /*
        add for log4j: class BasicConfigurator can quickly configure the package.
        print the information to console.
        */
        PropertyConfigurator.configure ( "ServerWithLog4j.properties" ) ;

        // add for log4j: set the level
//        logger.setLevel ( ( Level ) Level.DEBUG ) ;

        try{
            server = new ServerSocket ( SERVER_PORT ) ;

            // add for log4j: log a message with the info level
            logger.info ( "ServerSocket before accept: " + server ) ;

            // add for log4j: log a message with the info level
            logger.info ( "Java server with log4j, on-line!" ) ;

            // wait for client's connection
            socket = server.accept() ;

            // add for log4j: log a message with the info level
            logger.info ( "ServerSocket after accept: " + server ) ;

            in = socket.getInputStream() ;
            out = socket.getOutputStream() ;

        } catch ( IOException e ) {

            // add for log4j: log a message with the error level
            logger.error ( "Server constructor IOException: " + e ) ;
            System.exit ( 0 ) ;
        }
        reader = new BufferedReader ( new InputStreamReader ( in ) ) ;
        writer = new PrintWriter ( new OutputStreamWriter ( out ), true ) ;

        // send welcome string to client
        writer.println ( "Java server with log4j, " + new Date () ) ;

        while ( true ) {
            try {
                // read from client
                clientRequest = reader.readLine () ;

                // add for log4j: log a message with the debug level
                logger.debug ( "Client says: " + clientRequest ) ;

                if ( clientRequest.startsWith ( "HELP" ) ) {

                    // add for log4j: log a message with the debug level
                    logger.debug ( "OK!" ) ;

                    writer.println ( "Vocabulary: HELP QUIT" ) ;
                }
                else {
                    if ( clientRequest.startsWith ( "QUIT" ) ) {

                        // add for log4j: log a message with the debug level
                        logger.debug ( "OK!" ) ;

                        System.exit ( 0 ) ;
                    }
                    else {

                        // add for log4j: log a message with the warn level
                        logger.warn ( "Command '" 
						+ clientRequest + "' not understood." ) ;

                        writer.println ( "Command '"
						+ clientRequest + "' not understood." ) ;
                    }
                }
            } catch ( IOException e ) {

                // add for log4j: log a message with the error level
                logger.error( "IOException in Server " + e ) ;

                System.exit ( 0 ) ;
            }
        }
    }
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<b>2.2.3. 配置文件</b>
		</p>
		<p>2.2.3.1. 客户程序配置文件</p>
		<p>
		</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">log4j.rootLogger=INFO, A1

log4j.appender.A1=org.apache.log4j.ConsoleAppender

log4j.appender.A1.layout=org.apache.log4j.PatternLayout

log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>2.2.3.2. 服务器程序配置文件</p>
		<p>
		</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">log4j.rootLogger=INFO, A1

log4j.appender.A1=org.apache.log4j.ConsoleAppender

log4j.appender.A1.layout=org.apache.log4j.PatternLayout

log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<a name="N100B9">
						<span class="smalltitle">
								<strong>2.3. 比较</strong>
						</span>
				</a>
		</p>
		<p>
				<strong>
				</strong>
		</p>
		<p>比较这两个应用可以看出，采用Log4j进行日志操作的整个过程相当简单明了，与直接使用System.out.println语句进行日志信息输出的方式相比，基本上没有增加代码量，同时能够清楚地理解每一条日志信息的重要程度。通过控制配置文件，我们还可以灵活地修改日志信息的格式，输出目的地等等方面，而单纯依靠System.out.println语句，显然需要做更多的工作。</p>
		<p>下面我们将以前面使用Log4j的应用作为例子，详细讲解使用Log4j的主要步骤。</p>
		<p>
				<br />
		</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/l-log4j/index.html#main">
																				<b>
																						<font face="Verdana" color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="3">
						<span class="atitle">
								<strong>
										<font size="4">Log4j基本使用方法</font>
								</strong>
						</span>
				</a>
		</p>
		<p>
				<strong>
						<font size="4">
						</font>
				</strong>
		</p>
		<p>Log4j由三个重要的组件构成：日志信息的优先级，日志信息的输出目的地，日志信息的输出格式。日志信息的优先级从高到低有ERROR、WARN、INFO、DEBUG，分别用来指定这条日志信息的重要程度；日志信息的输出目的地指定了日志将打印到控制台还是文件中；而输出格式则控制了日志信息的显示内容。</p>
		<p>
				<a name="N100D2">
						<span class="smalltitle">
								<strong>3.1.定义配置文件</strong>
						</span>
				</a>
		</p>
		<p>
				<strong>
				</strong>
		</p>
		<p>其实您也可以完全不使用配置文件，而是在代码中配置Log4j环境。但是，使用配置文件将使您的应用程序更加灵活。</p>
		<p>Log4j支持两种配置文件格式，一种是XML格式的文件，一种是Java特性文件（键=值）。下面我们介绍使用Java特性文件做为配置文件的方法：</p>
		<ol>
				<li>配置根Logger，其语法为： 
<p>log4j.rootLogger = [ level ] , appenderName, appenderName, …</p>其中，level 是日志记录的优先级，分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。Log4j建议只使用四个级别，优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别，您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别，则应用程序中所有DEBUG级别的日志信息将不被打印出来。 <br />appenderName就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。 
</li>
				<li>配置日志信息输出目的地Appender，其语法为 <pre>log4j.appender.appenderName = fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1 = value1
…
log4j.appender.appenderName.option = valueN</pre>其中，Log4j提供的appender有以下几种： <br />org.apache.log4j.ConsoleAppender（控制台）， <br />org.apache.log4j.FileAppender（文件）， <br />org.apache.log4j.DailyRollingFileAppender（每天产生一个日志文件），org.apache.log4j.RollingFileAppender（文件大小到达指定尺寸的时候产生一个新的文件）， <br />org.apache.log4j.WriterAppender（将日志信息以流格式发送到任意指定的地方） 
</li>
				<li>配置日志信息的格式（布局），其语法为： <pre>log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1 = value1
…
log4j.appender.appenderName.layout.option = valueN</pre>其中，Log4j提供的layout有以下几种： <br />org.apache.log4j.HTMLLayout（以HTML表格形式布局）， <br />org.apache.log4j.PatternLayout（可以灵活地指定布局模式）， <br />org.apache.log4j.SimpleLayout（包含日志信息的级别和信息字符串）， <br />org.apache.log4j.TTCCLayout（包含日志产生的时间、线程、类别等等信息） </li>
		</ol>
		<p>
				<a name="N10107">
						<span class="smalltitle">
								<strong>3.2.在代码中使用Log4j</strong>
						</span>
				</a>
		</p>
		<p>
				<strong>
				</strong>
		</p>
		<p>下面将讲述在程序代码中怎样使用Log4j。</p>
		<p>
				<b>3.2.1.得到记录器</b>
		</p>
		<p>使用Log4j，第一步就是获取日志记录器，这个记录器将负责控制日志信息。其语法为：</p>
		<p>public static Logger getLogger( String name)，</p>
		<p>通过指定的名字获得记录器，如果必要的话，则为这个名字创建一个新的记录器。Name一般取本类的名字，比如：</p>
		<p>static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () ) ;</p>
		<p>
				<b>3.2.2.读取配置文件</b>
		</p>
		<p>当获得了日志记录器之后，第二步将配置Log4j环境，其语法为： <br />BasicConfigurator.configure ()： 自动快速地使用缺省Log4j环境。 <br />PropertyConfigurator.configure ( String configFilename) ：读取使用Java的特性文件编写的配置文件。 <br />DOMConfigurator.configure ( String filename ) ：读取XML形式的配置文件。 </p>
		<p>
				<b>3.2.3.插入记录信息（格式化日志信息）</b>
		</p>
		<p>当上两个必要步骤执行完毕，您就可以轻松地使用不同优先级别的日志记录语句插入到您想记录日志的任何地方，其语法如下：</p>
		<p>Logger.debug ( Object message ) ; <br />Logger.info ( Object message ) ; <br />Logger.warn ( Object message ) ; <br />Logger.error ( Object message ) ; </p>
<img src ="http://www.blogjava.net/19851985lili/aggbug/91572.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/19851985lili/" target="_blank">☜♥☞MengChuChen</a> 2007-01-03 16:38 <a href="http://www.blogjava.net/19851985lili/articles/91572.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Log4j进行日志操作1</title><link>http://www.blogjava.net/19851985lili/articles/91571.html</link><dc:creator>☜♥☞MengChuChen</dc:creator><author>☜♥☞MengChuChen</author><pubDate>Wed, 03 Jan 2007 08:36:00 GMT</pubDate><guid>http://www.blogjava.net/19851985lili/articles/91571.html</guid><wfw:comment>http://www.blogjava.net/19851985lili/comments/91571.html</wfw:comment><comments>http://www.blogjava.net/19851985lili/articles/91571.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/19851985lili/comments/commentRss/91571.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/19851985lili/services/trackbacks/91571.html</trackback:ping><description><![CDATA[
		<blockquote> </blockquote>
		<!--START RESERVED FOR FUTURE USE INCLUDE FILES-->
		<!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters -->
		<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->
		<p>
				<a name="1">
						<span class="atitle">
								<font size="4">
										<strong>概述</strong>
								</font>
						</span>
				</a>
		</p>
		<p>
				<font size="4">
						<strong>
						</strong>
				</font>
		</p>
		<p>
				<a name="N10040">
						<span class="smalltitle">
								<strong>1.1. 背景</strong>
						</span>
				</a>
		</p>
		<p>
				<strong>
				</strong>
		</p>
		<p>在应用程序中添加日志记录总的来说基于三个目的：监视代码中变量的变化情况，周期性的记录到文件中供其他应用进行统计分析工作；跟踪代码运行时轨迹，作为日后审计的依据；担当集成开发环境中的调试器的作用，向文件或控制台打印代码的调试信息。</p>
		<p>最普通的做法就是在代码中嵌入许多的打印语句，这些打印语句可以输出到控制台或文件中，比较好的做法就是构造一个日志操作类来封装此类操作，而不是让一系列的打印语句充斥了代码的主体。</p>
		<p>
				<a name="N1004E">
						<span class="smalltitle">
								<strong>1.2. Log4j简介</strong>
						</span>
				</a>
		</p>
		<p>
				<strong>
				</strong>
		</p>
		<p>在强调可重用组件开发的今天，除了自己从头到尾开发一个可重用的日志操作类外，Apache为我们提供了一个强有力的日志操作包-Log4j。</p>
		<p>Log4j是Apache的一个开放源代码项目，通过使用Log4j，我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等；我们也可以控制每一条日志的输出格式；通过定义每一条日志信息的级别，我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是，这些可以通过一个配置文件来灵活地进行配置，而不需要修改应用的代码。</p>
		<p>此外，通过Log4j其他语言接口，您可以在C、C++、.Net、PL/SQL程序中使用Log4j，其语法和用法与在Java程序中一样，使得多语言分布式系统得到一个统一一致的日志组件模块。而且，通过使用各种第三方扩展，您可以很方便地将Log4j集成到J2EE、JINI甚至是SNMP应用中。</p>
		<p>本文介绍的Log4j版本是1.2.3。作者试图通过一个简单的客户/服务器Java程序例子对比使用与不使用Log4j 1.2.3的差别，并详细讲解了在实践中最常使用Log4j的方法和步骤。在强调可重用组件开发的今天，相信Log4j将会给广大的设计开发人员带来方便。加入到Log4j的队伍来吧！</p>
		<p>
				<br />
		</p>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/l-log4j/index.html#main">
																				<b>
																						<font face="Verdana" color="#996699">回页首</font>
																				</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="2">
						<span class="atitle">
								<strong>
										<font size="4">一个简单的例子</font>
								</strong>
						</span>
				</a>
		</p>
		<p>
				<strong>
						<font size="4">
						</font>
				</strong>
		</p>
		<p>我们先来看一个简单的例子，它是一个用Java实现的客户/服务器网络程序。刚开始我们不使用Log4j，而是使用了一系列的打印语句，然后我们将使用Log4j来实现它的日志功能。这样，大家就可以清楚地比较出前后两个代码的差别。</p>
		<p>
				<a name="N1006D">
						<span class="smalltitle">
								<strong>2.1. 不使用Log4j</strong>
						</span>
				</a>
		</p>
		<p>
				<strong>
				</strong>
		</p>
		<p>
				<strong>2.1.1. 客户程序</strong>
		</p>
		<p>
		</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">package log4j ;

import java.io.* ;
import java.net.* ;

/**
 *
 * &lt;p&gt; Client Without Log4j &lt;/p&gt;
 * &lt;p&gt; Description: a sample with log4j&lt;/p&gt;
 * @version 1.0
 */
public class ClientWithoutLog4j {

    /**
     *
     * @param args
     */
    public static void main ( String args [] ) {

        String welcome = null;
        String response = null;
        BufferedReader reader = null;
        PrintWriter writer = null;
        InputStream in = null;
        OutputStream out = null;
        Socket client = null;

        try {
            client = new Socket ( "localhost", 8001 ) ;
            System.out.println ( "info: Client socket: " + client ) ;
            in = client.getInputStream () ;
            out = client.getOutputStream () ;
        } catch ( IOException e ) {
            System.out.println ( "error: IOException : " + e ) ;
            System.exit ( 0 ) ;
        }

        try{
            reader = new BufferedReader( new InputStreamReader ( in ) ) ;
            writer = new PrintWriter ( new OutputStreamWriter ( out ), true ) ;

            welcome = reader.readLine () ;
            System.out.println ( "debug: Server says: '" + welcome + "'" ) ;

            System.out.println ( "debug: HELLO" ) ;
            writer.println ( "HELLO" ) ;
            response = reader.readLine () ;
            System.out.println ( "debug: Server responds: '" + response + "'") ;

            System.out.println ( "debug: HELP" ) ;
            writer.println ( "HELP" ) ;
            response = reader.readLine () ;
            System.out.println ( "debug: Server responds: '" + response + "'" ) ;

            System.out.println ( "debug: QUIT" ) ;
            writer.println ( "QUIT" ) ;
        } catch ( IOException e ) {
            System.out.println ( "warn: IOException in client.in.readln()" ) ;
            System.out.println ( e ) ;
        }
        try{
            Thread.sleep ( 2000 ) ;
        } catch ( Exception ignored ) {}
    }
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<b>2.1.2. 服务器程序</b>
		</p>
		<p>
		</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">package log4j ;

import java.util.* ;
import java.io.* ;
import java.net.* ;

/**
 *
 * &lt;p&gt; Server Without Log4j &lt;/p&gt;
 * &lt;p&gt; Description: a sample with log4j&lt;/p&gt;
 * @version 1.0
 */
public class ServerWithoutLog4j {

    final static int SERVER_PORT = 8001 ; // this server's port

    /**
     *
     * @param args
     */
    public static void main ( String args [] ) {
        String clientRequest = null;
        BufferedReader reader = null;
        PrintWriter writer = null;
        ServerSocket server = null;
        Socket socket = null;
        InputStream in = null;
        OutputStream out = null;

        try {
            server = new ServerSocket ( SERVER_PORT ) ;
            System.out.println ( "info: ServerSocket before accept: " + server ) ;
            System.out.println ( "info: Java server without log4j, on-line!" ) ;

            // wait for client's connection
            socket = server.accept () ;
            System.out.println ( "info: ServerSocket after accept: " + server )  ;

            in = socket.getInputStream () ;
            out = socket.getOutputStream () ;

        } catch ( IOException e ) {
            System.out.println( "error: Server constructor IOException: " + e ) ;
            System.exit ( 0 ) ;
        }
        reader = new BufferedReader ( new InputStreamReader ( in ) ) ;
        writer = new PrintWriter ( new OutputStreamWriter ( out ) , true ) ;

        // send welcome string to client
        writer.println ( "Java server without log4j, " + new Date () ) ;

        while ( true ) {
            try {
                // read from client
                clientRequest = reader.readLine () ;
                System.out.println ( "debug: Client says: " + clientRequest ) ;
                if ( clientRequest.startsWith ( "HELP" ) ) {
                    System.out.println ( "debug: OK!" ) ;
                    writer.println ( "Vocabulary: HELP QUIT" ) ;
                }
                else {
                    if ( clientRequest.startsWith ( "QUIT" ) ) {
                        System.out.println ( "debug: OK!" ) ;
                        System.exit ( 0 ) ;
                    }
                    else{
                        System.out.println ( "warn: Command '" + 
						clientRequest + "' not understood." ) ;
                        writer.println ( "Command '" + clientRequest 
						+ "' not understood." ) ;
                    }
                }
            } catch ( IOException e ) {
                System.out.println ( "error: IOException in Server " + e ) ;
                System.exit ( 0 ) ;
            }
        }
    }
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<a name="N10089">
						<span class="smalltitle">
								<strong>2.2. 迁移到Log4j</strong>
						</span>
				</a>
		</p>
		<p>
				<strong>
				</strong>
		</p>
		<p>
				<strong>2.2.1. 客户程序</strong>
		</p>
		<p>
		</p>
		<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
				<tbody>
						<tr>
								<td>
										<pre>
												<code class="section">
														<font face="Lucida Console">package log4j ;

import java.io.* ;
import java.net.* ;

// add for log4j: import some package
import org.apache.log4j.PropertyConfigurator ;
import org.apache.log4j.Logger ;
import org.apache.log4j.Level ;

/**
 *
 * &lt;p&gt; Client With Log4j &lt;/p&gt;
 * &lt;p&gt; Description: a sample with log4j&lt;/p&gt;
 * @version 1.0
 */
public class ClientWithLog4j {

    /*
    add for log4j: class Logger is the central class in the log4j package.
    we can do most logging operations by Logger except configuration.
    getLogger(...): retrieve a logger by name, if not then create for it.
    */
    static Logger logger = Logger.getLogger 
	( ClientWithLog4j.class.getName () ) ;

    /**
     *
     * @param args : configuration file name
     */
    public static void main ( String args [] ) {

        String welcome = null ;
        String response = null ;
        BufferedReader reader = null ;
        PrintWriter writer = null ;
        InputStream in = null ;
        OutputStream out = null ;
        Socket client = null ;

        /*
        add for log4j: class BasicConfigurator can quickly configure the package.
        print the information to console.
        */
        PropertyConfigurator.configure ( "ClientWithLog4j.properties" ) ;

        // add for log4j: set the level
//        logger.setLevel ( ( Level ) Level.DEBUG ) ;

        try{
            client = new Socket( "localhost" , 8001 ) ;

            // add for log4j: log a message with the info level
            logger.info ( "Client socket: " + client ) ;

            in = client.getInputStream () ;
            out = client.getOutputStream () ;
        } catch ( IOException e ) {

            // add for log4j: log a message with the error level
            logger.error ( "IOException : " + e ) ;

            System.exit ( 0 ) ;
        }

        try{
            reader = new BufferedReader ( new InputStreamReader ( in ) ) ;
            writer = new PrintWriter ( new OutputStreamWriter ( out ), true ) ;

            welcome = reader.readLine () ;

            // add for log4j: log a message with the debug level
            logger.debug ( "Server says: '" + welcome + "'" ) ;

            // add for log4j: log a message with the debug level
            logger.debug ( "HELLO" ) ;

            writer.println ( "HELLO" ) ;
            response = reader.readLine () ;

            // add for log4j: log a message with the debug level
            logger.debug ( "Server responds: '" + response + "'" ) ;

            // add for log4j: log a message with the debug level
            logger.debug ( "HELP" ) ;

            writer.println ( "HELP" ) ;
            response = reader.readLine () ;

            // add for log4j: log a message with the debug level
            logger.debug ( "Server responds: '" + response + "'") ;

            // add for log4j: log a message with the debug level
            logger.debug ( "QUIT" ) ;

            writer.println ( "QUIT" ) ;
        } catch ( IOException e ) {

            // add for log4j: log a message with the warn level
            logger.warn ( "IOException in client.in.readln()" ) ;

            System.out.println ( e ) ;
        }
        try {
            Thread.sleep ( 2000 ) ;
        } catch ( Exception ignored ) {}
    }
}
</font>
												</code>
										</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
<img src ="http://www.blogjava.net/19851985lili/aggbug/91571.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/19851985lili/" target="_blank">☜♥☞MengChuChen</a> 2007-01-03 16:36 <a href="http://www.blogjava.net/19851985lili/articles/91571.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java调试的变迁：从System.out.println到log4j </title><link>http://www.blogjava.net/19851985lili/articles/log4j.html</link><dc:creator>☜♥☞MengChuChen</dc:creator><author>☜♥☞MengChuChen</author><pubDate>Wed, 03 Jan 2007 07:58:00 GMT</pubDate><guid>http://www.blogjava.net/19851985lili/articles/log4j.html</guid><wfw:comment>http://www.blogjava.net/19851985lili/comments/91557.html</wfw:comment><comments>http://www.blogjava.net/19851985lili/articles/log4j.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/19851985lili/comments/commentRss/91557.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/19851985lili/services/trackbacks/91557.html</trackback:ping><description><![CDATA[
		<div class="postText" align="left">
				<font face="Verdana" size="2">
						<strong>
								<u>
										<font color="#cc0000">
												<font size="3">jungleford如是说 <img title="log4j的logo" height="55" alt="o_log4j.jpg" src="http://www.blogjava.net/images/blogjava_net/jungleford/924/o_log4j.jpg" width="82" border="0" /></font>
												<br />
												<br />
										</font>
								</u>
						</strong>    用惯了<a href="http://msdn.microsoft.com/visualc/" target="_blank"><font color="#618b2c">VC</font></a>的人刚接触<a href="http://java.sun.com/" target="_blank"><font color="#618b2c">Java</font></a>大概很不习惯代码的调试，的确，在<a href="http://www.microsoft.com/" target="_blank"><font color="#618b2c">M$</font></a>的大部分IDE都做得相当出色，包括像VJ++这样一直被Java程序员称为是“垃圾”的类库（记得以前在<a href="http://bbs.ustc.edu.cn/" target="_blank"><font color="#618b2c">瀚海星云</font></a>的<a href="http://bbs.ustc.edu.cn/cgi-bin/bbsdoc?board=Java" target="_blank"><font color="#618b2c">Java版</font></a>提有关VJ问题的人是有可能被封的，^_^），它的开发工具在调试上都相当容易。Java也有命令行方式的调试和IDE的调试，但现在的像<a href="http://www.borland.com/jbuilder/" target="_blank"><font color="#618b2c">JB</font></a>这样的玩意又是个庞然大物，低配置的机器可能就是个奢望，不像VC那样。怎么办呢，高手们说，“我的jdb用得贼熟练”，那我会报以景仰的目光，像我这样的菜鸟基本上就没使过jdb，还是老老实实在代码里面System.out.println(...)。直到1996年一个叫做“欧洲安全电子市场”（E.U. <a href="http://www.semper.org/" target="_blank"><font color="#618b2c">SEMPER</font></a>）的项目启动，“调试”不再是一件“体力活”，而是一种软件设计的艺术，这个项目组开发的日志管理接口后来成为<a href="http://www.apache.org/" target="_blank"><font color="#618b2c">Apache</font></a><a href="http://jakarta.apache.org/" target="_blank"><font color="#618b2c">Jakarta</font></a>项目中的一员，它就是现在我们所熟悉的<a href="http://logging.apache.org/" target="_blank"><font color="#618b2c">log4j</font></a>。下面的文字将概要介绍与Java日志记录相关的一些技术，目的不是让您放弃老土的System.out.println(...)，而是说，在Java的世界里可以有许多种选择，你今天觉得掌握了一件高级武器，明天可能就是“过时”的了，呵呵。 
<p class="postText" align="left"><strong><u><font color="#cc0000"><font size="3">始祖：System.out.println(...)</font><br /><br /></font></u></strong>    为什么还是要一再提到它？毕竟我们的习惯不是那么容易改变的，而且<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html" target="_blank"><font color="#618b2c">System</font></a>.<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html#out" target="_blank"><font color="#618b2c">out</font></a>（别忘了还有System.<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html#err" target="_blank"><font color="#618b2c">err</font></a>）是一个直接和控制台打交道的<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/io/PrintStream.html" target="_blank"><font color="#618b2c">PrintStream</font></a>对象，是终端显示的基础，高级的Logger要在终端显示日志内容，就必然会用到这个。一个小规模的程序调试，恰当地使用System.out.<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/io/PrintStream.html#println(java.lang.Object)" target="_blank"><font color="#618b2c">println</font></a>(...)我认为仍然是一种最方便最有效的方法，所以我们仍把它放在最开始，以示不能“数典忘祖” :)</p><p class="postText" align="left"><strong><u><font color="#cc0000"><font size="3">不常用的关键字：assert</font><br /><br /></font></u></strong>    assert对多数人来讲可能还比较陌生，它也是一个调试工具，好像是<a href="http://java.sun.com/j2se/1.4.2/" target="_blank"><font color="#618b2c">J2SE 1.4</font></a>才加进来的东东，一种常见的用法是：</p><p class="postText" align="left"> <font size="-1"><strong><font color="#ff0000">assert</font></strong> (布尔表达式);</font></p><p class="postText" align="left"><font size="-1"><br />    当表达式为true时没有任何反映，如果为false系统将会抛出一个<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/AssertionError.html" target="_blank"><font color="#618b2c">AssertionError</font></a>。如果你要使用assert，在编译时必须加上“<strong>-source 1.4</strong>”的选项，在运行时则要加上“<strong>-ea</strong>”选项。<br /></font></p><p class="postText" align="left"><strong><u><font color="#cc0000"><font size="3">后生可畏：Java Logging API一瞥</font><br /><br /></font></u></strong>    System.out.println(...)对于较高要求的用户是远远不够的，它还不是一个日志系统，一个比较完善的日志系统应当有输出媒介、优先级、格式化、日志过滤、日志管理、参数配置等功能。伴随J2SE 1.4一起发布的Java日志包<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/package-summary.html" target="_blank"><font color="#618b2c">java.util.logging</font></a>适时地满足了我们的初步需求，在程序中按一定格式显示和记录丰富的调试信息已经是一件相当easy的事情。</p><p class="postText" align="left"><strong>1. 日志记录器：Logger</strong><br />    <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Logger.html" target="_blank"><font color="#618b2c">Logger</font></a>是一个直接面向用户的日志功能调用接口，从用户的角度上看，它完成大部分日志记录工作，通常你得到一个Logger对象，只需要使用一些简单方法，譬如info，warning，log，logp，logrb等就能完成任务，简单到和System.out.println(...)一样只用一条语句，但后台可能在向控制台，向文件，向数据库，甚至向网络同时输出该信息，而这个过程对用户是完全透明的。<br />    在使用Logger之前，首先需要通过<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Logger.html#getLogger(java.lang.String)" target="_blank"><font color="#618b2c">getLogger</font></a>()或<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Logger.html#getAnonymousLogger()" target="_blank"><font color="#618b2c">getAnonymousLogger</font></a>()静态方法得到一个Logger对象（想想看，这里是不是设计模式当中的“工厂方法”的一个实实在在的应用？可以参考一下Logger的源代码，你就明白<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/LogManager.html" target="_blank"><font color="#618b2c">LogManager</font></a>是“工厂类”而Logger是“产品类”，凡事都要学以致用嘛，呵呵）。这里我们需要了解的是Logger的“名字空间”（<strong>namespace</strong>）的概念：通常我们调试时需要清楚地知道某个变量是出现在什么位置，精确到哪个类的哪个方法，namespace就是这么个用处。我们用getLogger()得到Logger时需要指定这个Logger的名字空间，通常是一个包名，譬如“com.jungleford.test”等，如果是指定了namespace，那么将在一个全局对象LogManager中注册这个namespace，Logger会基于namespace形成层次关系，譬如namespace为“com.jungleford”的Logger就是namespace为“com.jungleford.test”的Logger的父，后者调用<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Logger.html#getParent()" target="_blank"><font color="#618b2c">getParent</font></a>()方法将返回前者，如果当前没有namespace为“com.jungleford”的Logger，则查找namespace为“com”的Logger，要是按照这个链找不到就返回根Logger，其namespace为""，根Logger的父是null。从理论上说，这个namespace可以是任意的，通常我们是按所调试的对象来定，但如果你是使用getAnonymousLogger()方法产生的Logger，那它就没有namespace，这个“匿名Logger”的父是根Logger。<br />    得到一个Logger对象后就可以记录日志了，下面是一些常用的方法： </p><p class="postText" align="left"><br /><font size="-1"><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Logger.html#finest(java.lang.String)" target="_blank"><font color="#618b2c">finest</font></a>、<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Logger.html#finer(java.lang.String)" target="_blank"><font color="#618b2c">finer</font></a>、<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Logger.html#fine(java.lang.String)" target="_blank"><font color="#618b2c">fine</font></a>、<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Logger.html#info(java.lang.String)" target="_blank"><font color="#618b2c">info</font></a>、<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Logger.html#config(java.lang.String)" target="_blank"><font color="#618b2c">config</font></a>、<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Logger.html#warning(java.lang.String)" target="_blank"><font color="#618b2c">warning</font></a>、<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Logger.html#severe(java.lang.String)" target="_blank"><font color="#618b2c">severe</font></a>：简洁的方法，输出的日志为指定的级别。关于日志级别我们在后面将会详细谈到。<br /><br /><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Logger.html#log(java.util.logging.Level, java.lang.String)" target="_blank"><font color="#618b2c">log</font></a>：不仅可以指定消息和级别，还可以带一些参数，甚至可以直接是一个LogRecord对象（这些参数是LogRecord对象的重要组成部分）。<br /><br /><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Logger.html#logp(java.util.logging.Level, java.lang.String, java.lang.String, java.lang.String)" target="_blank"><font color="#618b2c">logp</font></a>：更加精细了，不但具有log方法的功能，还可以不使用当前的namespace，定义新的类名和方法名。<br /><br /><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Logger.html#entering(java.lang.String, java.lang.String)" target="_blank"><font color="#618b2c">entering</font></a>、<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"><font color="#618b2c">exiting</font></a>：这两个方法在调试的时候特别管用，用来观察一个变量变化的情况，就如同我们在VC的调试状态下watch一个变量，然后按F10，呵呵。</font><br /></p><p class="postText" align="left"><strong>2. 输出媒介控制：Handler</strong><br />    日志的意义在于它可以以多种形式输出，尤其是像文件这样可以长久保存的媒介，这是System.out.println(...)所无法办到的。Logging API的<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Handler.html" target="_blank"><font color="#618b2c">Handler</font></a>类提供了一个处理日志记录（<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/LogRecord.html" target="_blank"><font color="#618b2c">LogRecord</font></a>，它是对一条日志消息的封装对象）的接口，包括几个已实现的API：</p><p class="postText" align="left"><br /><font size="-1"></font><font size="-1"><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/ConsoleHandler.html" target="_blank"><font color="#618b2c">ConsoleHandler</font></a>：向控制台输出。<br /><br /><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/FileHandler.html" target="_blank"><font color="#618b2c">FileHandler</font></a>：向文件输出。<br /><br /><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/SocketHandler.html" target="_blank"><font color="#618b2c">SocketHandler</font></a>：向网络输出。</font></p><font size="-1"><p class="postText" align="left"><br />    这三个输出控制器都是<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/StreamHandler.html" target="_blank"><font color="#618b2c">StreamHandler</font></a>的子类，另外Handler还有一个MemoryHandler的子类，它有特殊的用处，我们在后面将会看到。在程序启动时默认的Handler是ConsoleHandler，不过这个是可以配置的，下面会谈到logging配置文件的问题。<br />    此外用户还可以定制自己输出控制器，继承Handler即可，通常只需要实现Handler中三个未定义的抽象方法： </p><p class="postText" align="left"><font size="-1"><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Handler.html#publish(java.util.logging.LogRecord)" target="_blank"><font color="#618b2c">publish</font></a>：主要方法，把日志记录写入你需要的媒介。<br /><br /><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Handler.html#flush()" target="_blank"><font color="#618b2c">flush</font></a>：清除缓冲区并保存数据。<br /><br /><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Handler.html#close()" target="_blank"><font color="#618b2c">close</font></a>：关闭控制器。</font></p></font><font size="-1"><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Handler.html#publish(java.util.logging.LogRecord)" target="_blank"><font color="#618b2c">publish</font></a>：主要方法，把日志记录写入你需要的媒介。<br /><br /><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Handler.html#flush()" target="_blank"><font color="#618b2c">flush</font></a>：清除缓冲区并保存数据。<br /><br /><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Handler.html#close()" target="_blank"><font color="#618b2c">close</font></a>：关闭控制器。</font><p class="postText" align="left"><font size="-1"><br />    通过重写以上三个方法我们可以很容易就实现一个把日志写入数据库的控制器。<br /></font></p><p class="postText" align="left"><strong>3. 自定义输出格式：Formatter</strong><br />    除了可以指定输出媒介之外，我们可能还希望有多种输出格式，譬如可以是普通文本、HTML表格、XML等等，以满足不同的查看需求。Logging API中的<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Formatter.html" target="_blank"><font color="#618b2c">Formatter</font></a>就是这样一个提供日志记录格式化方法接口的类。默认提供了两种Formatter：<br /><br /><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/SimpleFormatter.html" target="_blank"><font color="#618b2c">SimpleFormatter</font></a>：标准日志格式，就是我们通常在启动一些诸如<a href="http://jakarta.apache.org/tomcat/" target="_blank"><font color="#618b2c">Tomcat</font></a>、<a href="http://www.jboss.org/" target="_blank"><font color="#618b2c">JBoss</font></a>之类的服务器的时候经常能在控制台下看到的那种形式，就像这样： </p><p class="postText" align="left"><br /><font size="-1">2004-12-20 23:08:52 org.apache.coyote.http11.Http11Protocol init<br />信息: Initializing Coyote HTTP/1.1 on http-8080<br /><br />2004-12-20 23:08:56 org.apache.coyote.http11.Http11Protocol init<br />信息: Initializing Coyote HTTP/1.1 on http-8443 </font></p><font size="-1"><p class="postText" align="left"><br /><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/XMLFormatter.html" target="_blank"><font color="#618b2c">XMLFormatter</font></a>：XML形式的日志格式，你的Logger如果add了一个new XMLFormatter()，那么在控制台下就会看到下面这样的形式，不过更常用的是使用上面介绍的FileHandler输出到XML文件中： </p><p class="postText" align="left"><font size="-1">&lt;?xml version="1.0" encoding="GBK" standalone="no"?&gt;<br />&lt;!DOCTYPE log SYSTEM "logger.dtd"&gt;<br />&lt;log&gt;<br />&lt;record&gt;<br />  &lt;date&gt;2004-12-20T23:47:56&lt;/date&gt;<br />  &lt;millis&gt;1103557676224&lt;/millis&gt;<br />  &lt;sequence&gt;0&lt;/sequence&gt;<br />  &lt;logger&gt;Test&lt;/logger&gt;<br />  &lt;level&gt;WARNING&lt;/level&gt;<br />  &lt;class&gt;Test&lt;/class&gt;<br />  &lt;method&gt;main&lt;/method&gt;<br />  &lt;thread&gt;10&lt;/thread&gt;<br />  &lt;message&gt;warning message&lt;/message&gt;<br />&lt;/record&gt;</font></p></font><font size="-1">&lt;?xml version="1.0" encoding="GBK" standalone="no"?&gt;<br />&lt;!DOCTYPE log SYSTEM "logger.dtd"&gt;<br />&lt;log&gt;<br />&lt;record&gt;<br />  &lt;date&gt;2004-12-20T23:47:56&lt;/date&gt;<br />  &lt;millis&gt;1103557676224&lt;/millis&gt;<br />  &lt;sequence&gt;0&lt;/sequence&gt;<br />  &lt;logger&gt;Test&lt;/logger&gt;<br />  &lt;level&gt;WARNING&lt;/level&gt;<br />  &lt;class&gt;Test&lt;/class&gt;<br />  &lt;method&gt;main&lt;/method&gt;<br />  &lt;thread&gt;10&lt;/thread&gt;<br />  &lt;message&gt;warning message&lt;/message&gt;<br />&lt;/record&gt;</font><font size="-1"><p class="postText" align="left"><br />    与Handler类似，我们也可以编写自己的格式化处理器，譬如API里没有将日志输出为我们可通过浏览器查看的HTML表格形式的Formatter，我们只需要重写3个方法： </p><p class="postText" align="left"><font size="-1"><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Formatter.html#format(java.util.logging.LogRecord)" target="_blank"><font color="#618b2c">format</font></a>：格式化LogRecord中包含的信息。<br /><br /><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Formatter.html#getHead(java.util.logging.Handler)" target="_blank"><font color="#618b2c">getHead</font></a>：输出信息的头部。<br /><br /><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Formatter.html#getTail(java.util.logging.Handler)" target="_blank"><font color="#618b2c">getTail</font></a>：输出信息的尾部。</font><font size="-1"></font><br /></p></font><font size="-1"><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Formatter.html#format(java.util.logging.LogRecord)" target="_blank"><font color="#618b2c">format</font></a>：格式化LogRecord中包含的信息。<br /><br /><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Formatter.html#getHead(java.util.logging.Handler)" target="_blank"><font color="#618b2c">getHead</font></a>：输出信息的头部。<br /><br /><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Formatter.html#getTail(java.util.logging.Handler)" target="_blank"><font color="#618b2c">getTail</font></a>：输出信息的尾部。</font><font size="-1"></font><br /><p class="postText" align="left"><font size="-1"><strong>4. 定义日志级别：Level</strong><br />    大家可能都知道Windows的“事件查看器”，里面有三种事件类型：“信息”、“警告”、“错误”。这其实就是日志级别的一种描述。Java日志级别用<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Level.html" target="_blank"><font color="#618b2c">Level</font></a>类表示，一个日志级别对应的是一个整数值，范围和整型值的范围是一致的，该整数值愈大，说明警戒级别愈高。Level有9个内置的级别，分别是： </font></p><p class="postText" align="left"><font size="-1"><strong>类型</strong>         </font> <font size="-1"><strong>对应的整数</strong><br /></font><font color="#000080" size="-1"><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Level.html#OFF" target="_blank">OFF</a></font>          <font size="-1">最大整数（<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Integer.html" target="_blank"><font color="#618b2c">Integer</font></a>.<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Integer.html#MAX_VALUE" target="_blank"><font color="#618b2c">MAX_VALUE</font></a>）<br /></font><font color="#000080" size="-1"><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Level.html#SEVERE" target="_blank">SEVERE</a></font>     <font size="-1">1000<br /></font><font color="#000080" size="-1"><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Level.html#WARNING" target="_blank">WARNING</a></font>   <font size="-1">900<br /></font><font color="#000080" size="-1"><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Level.html#INFO" target="_blank">INFO</a></font>         <font size="-1">800<br /></font><font color="#000080" size="-1"><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Level.html#CONFIG" target="_blank">CONFIG</a></font>      <font size="-1">700<br /></font><font color="#000080" size="-1"><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Level.html#FINE" target="_blank">FINE</a></font>          <font size="-1">500<br /></font><font color="#000080" size="-1"><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Level.html#FINER" target="_blank">FINER</a></font>        <font size="-1">400<br /></font><font color="#000080" size="-1"><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Level.html#FINEST" target="_blank">FINEST</a></font>      <font size="-1">300<br /></font><font color="#000080" size="-1"><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Level.html#ALL" target="_blank">ALL</a></font>           <font size="-1">最小整数（Integer.<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Integer.html#MIN_VALUE" target="_blank"><font color="#618b2c">MIN_VALUE</font></a>）</font></p><font size="-1"><p class="postText" align="left"><br />    你也可以定义自己的日志级别，但要注意的是，不是直接创建Level的对象（因为它的构造函数是protected的），而是通过继承Level的方式，譬如： </p><p class="postText" align="left"><font color="#ff0000" size="-1"><strong>class</strong></font><font size="-1"> AlertLevel <strong><font color="#ff0000">extends</font></strong> java.util.logging.Level<br />{<br />  <strong><font color="#ff0000">public</font></strong> AlertLevel()<br />  {<br />    super(<font color="#ff00ff">"ALERT"</font>, <font color="#0000ff">950</font>);<br />  }<br />}<br />...<br /><strong><font color="#990000">Logger</font></strong> logger = <strong><font color="#990000">Logger</font></strong>.getAnonymousLogger();<br />logger.log(<strong><font color="#ff0000">new</font></strong> AlertLevel(), <font color="#ff00ff">"A dangerous action!"</font>);</font></p></font><font color="#ff0000" size="-1"><strong>class</strong></font><font size="-1"> AlertLevel <strong><font color="#ff0000">extends</font></strong> java.util.logging.Level<br />{<br />  <strong><font color="#ff0000">public</font></strong> AlertLevel()<br />  {<br />    super(<font color="#ff00ff">"ALERT"</font>, <font color="#0000ff">950</font>);<br />  }<br />}<br />...<br /><strong><font color="#990000">Logger</font></strong> logger = <strong><font color="#990000">Logger</font></strong>.getAnonymousLogger();<br />logger.log(<strong><font color="#ff0000">new</font></strong> AlertLevel(), <font color="#ff00ff">"A dangerous action!"</font>);</font><font size="-1"><p class="postText" align="left"><br />    上面定义了一个高于WARNING但低于SEVERE的日志级别。<br />    于是可能有朋友会兴冲冲地用以下的语句来记录一个事件： </p><p class="postText" align="left"><font color="#990000" size="-1"><strong>Logger</strong></font><font size="-1"> logger = <strong><font color="#990000">Logger</font></strong>.getAnonymousLogger();<br />logger.fine(<font color="#ff00ff">"Everything seems ok."</font>);<br /><font color="#006600">//或者是<br />//logger.log(Level.FINE, "Everything seems ok.");</font></font></p></font><font color="#990000" size="-1"><strong>Logger</strong></font><font size="-1"> logger = <strong><font color="#990000">Logger</font></strong>.getAnonymousLogger();<br />logger.fine(<font color="#ff00ff">"Everything seems ok."</font>);<br /><font color="#006600">//或者是<br />//logger.log(Level.FINE, "Everything seems ok.");</font></font><p class="postText" align="left"><font color="#006600"></font><font size="-1"><br />    但是一程序运行，奇怪了，怎么没有打印出任何消息呢？下一小节我们就来谈这个问题。</font></p><p class="postText" align="left"><font size="-1"><strong>5. 日志过滤器：Filter</strong><br />    所谓过滤器是控制哪些日志该输出哪些不该输出的一种组件。上面你写的那条日志没有能在控制台显示出来，是因为logging API预先设定的缺省级别是INFO，也就是说只有级别不低于INFO（即其整数值不小于800）的日志才会被输出，这个就是Filter的功能。所以我们可以看到SEVERE、WARNING、INFO以及上面我们定义的ALERT消息，但看不到FINE、FINER和FINEST消息。当然，你尽可以用Logger的<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Logger.html#setLevel(java.util.logging.Level)" target="_blank"><font color="#618b2c">setLevel</font></a>方法或者修改配置文件的方法（什么是配置文件，我们后面将会看到）来重新定义Logger输出的最低级别。<br />    <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Filter.html" target="_blank"><font color="#618b2c">Filter</font></a>不仅仅可以按日志级别过滤，你也可以定义自己的Filter，实现其中的<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Filter.html#isLoggable(java.util.logging.LogRecord)" target="_blank"><font color="#618b2c">isLoggable</font></a>方法，随便按照LogRecord携带的任何信息进行过滤，譬如（顺便复习一下匿名类，呵呵）： </font></p><p class="postText" align="left"><font color="#990000" size="-1"><strong>Logger</strong></font><font size="-1"> logger = <strong><font color="#990000">Logger</font></strong>.getAnonymousLogger();<br />logger.setFilter(<strong><font color="#ff0000">new</font></strong><strong><font color="#990000">Filter</font></strong>()<br />{<br />  <strong><font color="#ff0000">public</font></strong><strong><font color="#ff0000">boolean</font></strong> isLoggable(<strong><font color="#990000">LogRecord</font></strong> rec)<br />  {<br />    <font color="#006600">//从LogRecord里得到过滤信息<br /></font>  }<br />});</font></p><p class="postText" align="left"><strong><br />6. 预定义参数<br /></strong>    LogManager是一个实现了Singleton模式的全局对象（由于是一个唯一的对象，LogManager需要是线程安全的），它管理着程序启动以后所有已注册（包层次）或匿名的Logger，以及相关配置信息。这里的配置信息通常是从<strong>&lt;JAVA_HOME&gt;\jre\lib\logging.properties</strong>文件得到的。logging.properties对于logging API来说是一个很重要的文件，它的内容一般是：<br /></p><font size="-1"></font><font size="-1"><p class="postText" align="left">############################################################<br /># Default Logging Configuration File<br />#<br /># You can use a different file by specifying a filename<br /># with the java.util.logging.config.file system property. <br /># For example java -Djava.util.logging.config.file=myfile<br />############################################################</p><p class="postText" align="left">############################################################<br /># Global properties<br />############################################################</p><p class="postText" align="left"># "handlers" specifies a comma separated list of log Handler <br /># classes. These handlers will be installed during VM startup.<br /># Note that these classes must be on the system classpath.<br /># By default we only configure a ConsoleHandler, which will only<br /># show messages at the INFO and above levels.<br />handlers= java.util.logging.ConsoleHandler</p><p class="postText" align="left"># To also add the FileHandler, use the following line instead.<br />#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler</p><p class="postText" align="left"># Default global logging level.<br /># This specifies which kinds of events are logged across<br /># all loggers. For any given facility this global level<br /># can be overriden by a facility specific level<br /># Note that the ConsoleHandler also has a separate level<br /># setting to limit messages printed to the console.<br />.level= INFO</p><p class="postText" align="left">############################################################<br /># Handler specific properties.<br /># Describes specific configuration info for Handlers.<br />############################################################</p><p class="postText" align="left"># default file output is in user's home directory.<br />java.util.logging.FileHandler.pattern = %h/java%u.log<br />java.util.logging.FileHandler.limit = 50000<br />java.util.logging.FileHandler.count = 1<br />java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter</p><p class="postText" align="left"># Limit the message that are printed on the console to INFO and above.<br />java.util.logging.ConsoleHandler.level = INFO<br />java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter<br /></p><p class="postText" align="left">############################################################<br /># Facility specific properties.<br /># Provides extra control for each logger.<br />############################################################</p><p class="postText" align="left"># For example, set the com.xyz.foo logger to only log SEVERE<br /># messages:<br />com.xyz.foo.level = SEVERE</p></font><font size="-1"><div class="postText" align="left"><br />    你可以通过修改这个配置文件来改变运行时Logger的行为，譬如：.level定义的是上面所说的默认输出的最低日志级别；XXXHandler相关属性定义了各种输出媒介等等。<br />    这里比较有意思的是关于日志文件，也就是FileHandler，当然，你可以在程序中创建一个FileHandler，然后添加到logger中： </div><div class="postText" align="left"> </div><div class="postText" align="left"><font color="#990000" size="-1"><strong>FileHandler</strong></font><font size="-1"> fhd = <strong><font color="#ff0000">new</font></strong><strong><font color="#990000">FileHandler</font></strong>(<font color="#ff00ff">"%h/java%u.log"</font>, <font color="#0000ff">5000</font>, <font color="#0000ff">1</font>, <strong><font color="#ff0000">true</font></strong>);<br />fhd.setLevel(<strong><font color="#990000">Level</font></strong>.ALL);<br />fhd.setFormatter(<strong><font color="#ff0000">new</font></strong><strong><font color="#990000">XMLFormatter</font></strong>());<br />logger.addHandler(fhd);</font></div></font><font color="#990000" size="-1"><strong>FileHandler</strong></font><font size="-1"> fhd = <strong><font color="#ff0000">new</font></strong><strong><font color="#990000">FileHandler</font></strong>(<font color="#ff00ff">"%h/java%u.log"</font>, <font color="#0000ff">5000</font>, <font color="#0000ff">1</font>, <strong><font color="#ff0000">true</font></strong>);<br />fhd.setLevel(<strong><font color="#990000">Level</font></strong>.ALL);<br />fhd.setFormatter(<strong><font color="#ff0000">new</font></strong><strong><font color="#990000">XMLFormatter</font></strong>());<br />logger.addHandler(fhd);</font><font size="-1"><div class="postText" align="left"><br />    这段代码等价于上面logging.properties中的文字段： </div><div class="postText" align="left"> </div><div class="postText" align="left"><font size="-1">java.util.logging.FileHandler.pattern = %h/java%u.log<br />java.util.logging.FileHandler.limit = 50000<br />java.util.logging.FileHandler.count = 1<br />java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter</font></div></font><font size="-1">java.util.logging.FileHandler.pattern = %h/java%u.log<br />java.util.logging.FileHandler.limit = 50000<br />java.util.logging.FileHandler.count = 1<br />java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter</font><font size="-1"><div class="postText" align="left"><br />    这里的pattern代表用转义字符定义的一个日志文件名： <font size="-1">转义字符串</font><font size="-1">含义</font><font size="-1">%t</font><font size="-1">临时目录</font><font size="-1">%h</font><font size="-1">用户目录，即系统属性“user.home”对应的值</font><font size="-1">%g</font><font size="-1">一个随机生成的数字，可以重复</font><font size="-1">%u</font><font size="-1">一个随机生成的非重复数字</font><font size="-1"><br />    以上面的“%h/java%u.log”为例，在Windows 2000下代表日志文件可能就是：C:\Documents and Settings\Administrator\java<strong>x</strong>.log。这里x代表一个不重复的数字，如果是第一次，那么就是java0.log；如果在该目录下已经存在了一个java0.log的文件，那么logger就产生一个java1.log的新的日志文件。<br />    当然，你可以在别的地方使用自己写的配置文件，不过在启动程序时候需要指定<strong>java.logging.config.file</strong>属性： </font></div></font><font size="-1">转义字符串</font><font size="-1">含义</font><font size="-1">%t</font><font size="-1">临时目录</font><font size="-1">%h</font><font size="-1">用户目录，即系统属性“user.home”对应的值</font><font size="-1">%g</font><font size="-1">一个随机生成的数字，可以重复</font><font size="-1">%u</font><font size="-1">一个随机生成的非重复数字</font><font size="-1"><br />    以上面的“%h/java%u.log”为例，在Windows 2000下代表日志文件可能就是：C:\Documents and Settings\Administrator\java<strong>x</strong>.log。这里x代表一个不重复的数字，如果是第一次，那么就是java0.log；如果在该目录下已经存在了一个java0.log的文件，那么logger就产生一个java1.log的新的日志文件。<br />    当然，你可以在别的地方使用自己写的配置文件，不过在启动程序时候需要指定<strong>java.logging.config.file</strong>属性： </font><div class="postText" align="left"> </div><div class="postText" align="left"><font size="-1">java -Djava.logging.config.file=...</font></div><div class="postText" align="left"><br /><strong>7. 资源与本地化</strong><br />    Logger里还有个方法叫<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"><font color="#618b2c">logrb</font></a>，可能初学者不太会用到。如果你安装的JDK是国际版的，那么你将会看到在中文Windows平台下日志输出的INFO、WARNING显示的是“信息”、“警告”等中文字样。因为logrb是一个和Java i18n/l10n相关的方法，你可以定义自己的“资源包”（Resource Bundle），然后在logrb方法中指定相应的资源名称，那么在输出日志中你就能看到用自己定义的本地语言、时间等显示的信息。如果你对i18n/l10n感兴趣，可以参考<a href="http://java.sun.com/j2se/1.4.2/docs/guide/intl/index.html" target="_blank"><font color="#618b2c">Java Localization文档</font></a>。<br /><br /><br />    了解以上组件后，我们回顾一个完整的日志处理的工作过程：<br />    程序启动日志服务，创建Logger对象，LogManager按照namespace的层次结构组织Logger，在同一个namespace里子Logger将继承父Logger的属性；同时，LogManager从logging.properties中读取相应的属性对Logger进行初始化，如果在程序中设置了属性则使用新的配置。当应用程序产生一条日志，Logger将创建一个LogRecord对象，该对象封装了一条日志的全部信息。Logger需要根据当前设置的Filter来判断这条日志是否需要输出，并将有用的日志传给相应的Handler处理，而Handler根据当前设置的Formatter和Resource Bundle将日志消息转换成一定的显示格式，然后输出到预定的媒介（控制台、文件等）中去。整个过程大致如图1所示： <br /></div><p class="postText" align="center"></p><p class="postText" align="center"><img title="日志处理流程" height="151" alt="o_logging1.gif" src="http://www.blogjava.net/images/blogjava_net/jungleford/924/o_logging1.gif" width="632" border="0" /></p><p class="postText" align="left">                                                  图1<br /><br />    前面我们在介绍Handler的时候提到过一个特殊的类叫<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/MemoryHandler.html" target="_blank"><font color="#618b2c">MemoryHandler</font></a>，这里我们要了解一下“Handler链”的概念，日志在输出之前可能经过多个Handler的处理，MemoryHandler在这种情况下就是一个中间角色，它维持一个内存中的日志缓冲区，当日志没有填满缓冲区时就将全部日志送到下一个Handler，否则新进来的日志将会覆盖最老的那些日志，因此，使用MemoryHandler可以维护一定容量的日志，另外，MemoryHandler也可以不需要使用Formatter来进行格式化，从而具有较高的效率。一个使用Handler链的例子如图2所示： </p><p class="postText" align="left"></p><div class="postText" align="center"><img title="一个 Handler 链" height="149" alt="o_logging2.gif" src="http://www.blogjava.net/images/blogjava_net/jungleford/924/o_logging2.gif" width="700" border="0" /><br />图2 </div><p class="postText" align="center"></p><p class="postText" align="left"><strong><u><font color="#cc0000"><font size="3">青出于蓝：Apache Jakarta log4j日志工具包</font><br /><br /></font></u></strong>    应付日常的日志需求，J2SE的Logging API可以说已经做得相当出色了，但追求完美的开发人员可能需要可扩展性更好的专业日志处理工具，log4j正是当前比较流行的一个工具包，它提供更多的输出媒介、输出格式和配置选择，你会发现原来在J2SE里一些仍需要自己手工构建的功能在log4j当中都已经为你实现了。关于log4j我可能谈得不会太多，可以看看文后所附的“<a href="http:///#ref"><font color="#618b2c">参考资料</font></a>”，网上也有很详细的介绍，我在这里做的是一个对比，因为log4j和J2SE 1.4 Logging API的用法是很相似的，一些名称不同的组件你会发现他们所处的地位其实是一样的： <br /><br />                 <font size="-1"><strong>J2SE 1.4中的类</strong></font>       <font size="-1"><strong>log4j中的类</strong><br /></font><strong><font size="-1">日志记录器</font></strong>    <font size="-1">Logger                  </font><font size="-1"><a href="http://logging.apache.org/log4j/docs/api/org/apache/log4j/Logger.html" target="_blank"><font color="#618b2c">Logger</font></a><br /></font><font size="-1"><strong>日志管理器</strong>    </font><font size="-1">LogManager           </font><font color="#000080" size="-1"><a href="http://logging.apache.org/log4j/docs/api/org/apache/log4j/LogManager.html" target="_blank">LogManager</a></font><br /><strong></strong><font size="-1"><strong>日志对象</strong>      </font> <font size="-1">LogRecord             </font><font color="#000080" size="-1"><a href="http://logging.apache.org/log4j/docs/api/org/apache/log4j/spi/LoggingEvent.html" target="_blank">LoggingEvent</a></font><br /><font size="-1"><strong>输出媒介控制</strong></font><font size="-1">Handler                </font> <font size="-1"><a href="http://logging.apache.org/log4j/docs/api/org/apache/log4j/Appender.html" target="_blank"><font color="#618b2c">Appender</font></a><br /></font><font size="-1"><strong>格式化</strong>        </font>  <font size="-1">Formatter             </font> <font size="-1"><a href="http://logging.apache.org/log4j/docs/api/org/apache/log4j/Layout.html" target="_blank"><font color="#618b2c">Layout</font></a><br /></font><font size="-1"><strong>级别</strong>           </font>  <font size="-1">Level                   </font> <font color="#000080" size="-1"><a href="http://logging.apache.org/log4j/docs/api/org/apache/log4j/Layout.html" target="_blank">Level</a></font><br /><font size="-1"><strong>过滤器</strong>          </font><font size="-1">Filter                    </font> <font size="-1"><a href="http://logging.apache.org/log4j/docs/api/org/apache/log4j/spi/Filter.html" target="_blank"><font color="#618b2c">Filter</font></a><br /></font><font size="-1"><br />    log4j可以做到更精细更完善的控制，譬如J2SE里没有现成向数据库里写日志的方法，但log4j却有<a href="http://logging.apache.org/log4j/docs/api/org/apache/log4j/jdbc/JDBCAppender.html" target="_blank"><font color="#618b2c">JDBCAppender</font></a>，它甚至还能向GUI图形界面（<a href="http://logging.apache.org/log4j/docs/api/org/apache/log4j/lf5/LF5Appender.html" target="_blank"><font color="#618b2c">LF5Appender</font></a>，一种以JTree方式显示的层次结构）、Windows NT事件查看器（<a href="http://logging.apache.org/log4j/docs/api/org/apache/log4j/nt/NTEventLogAppender.html" target="_blank"><font color="#618b2c">NTEventLogAppender</font></a>）、UNIX的syslogd服务（<a href="http://logging.apache.org/log4j/docs/api/org/apache/log4j/net/SyslogAppender.html" target="_blank"><font color="#618b2c">SyslogAppender</font></a>）、电子邮箱（<a href="http://logging.apache.org/log4j/docs/api/org/apache/log4j/net/SMTPAppender.html" target="_blank"><font color="#618b2c">SMTPAppender</font></a>）、Telnet终端（<a href="http://logging.apache.org/log4j/docs/api/org/apache/log4j/net/TelnetAppender.html" target="_blank"><font color="#618b2c">TelnetAppender</font></a>）、JMS消息（<a href="http://logging.apache.org/log4j/docs/api/org/apache/log4j/net/JMSAppender.html" target="_blank"><font color="#618b2c">JMSAppender</font></a>）输出日志，牛吧；J2SE里默认只能用%JAVA_HOME%\jre\lib\logging.properties做配置文件，但log4j却可以在代码中设置其它路径下的properties文件或XML格式的配置文件。log4j的其它方面同样很丰富，总之，log4j的最大的特点就是“灵活”，无论是Appender、Layout还是Configurator，你可以把日志轻松地弄成几乎任何你想要的形式。</font></p><p class="postText" align="left"><strong><u><font color="#cc0000"><font size="3">框架与标准：JSR议案</font><br /><br /></font></u></strong>    从时间顺序上讲，log4j要比J2SE Logging API来得早，很多概念都是log4j先有的，但成为一个标准，则是在<a href="http://www.jcp.org/en/jsr/detail?id=47" target="_blank"><font color="#618b2c">JSR 47</font></a>的形成。可能有人还不太了解<a href="http://www.jcp.org/en/jsr/overview" target="_blank"><font color="#618b2c">JSR</font></a>，这还要谈到<a href="http://www.jcp.org/en/home/index" target="_blank"><font color="#618b2c">JCP</font></a>，即“Java Community Process”，它是一个于1998年成立的旨在为Java技术制定民间标准的开放组织，你可以通过<a href="http://www.jcp.org/en/participation/membership" target="_blank"><font color="#618b2c">http://www.jcp.org/en/participation/membership</font></a>申请成为它的付费或免费会员，JCP的主要工作就是制定和发布JSR（Java Specification Requests），JSR对于Java的意义就相当于RFC对于网络技术的意义，由于JCP会员们的集思广益，使得JSR成为Java界的一个重要标准。JSR 47即“Logging API Specification”，制定了调试和日志框架，J2SE Logging API正是该框架的一个实现。由于种种原因，在JSR 47出来以前，log4j就已经成为一项成熟的技术，使得log4j在选择上占据了一定的优势，但不能因此就说JSR 47是过时的规范，标准总是在发展的嘛！</p><p class="postText" align="left"><strong><u><font color="#cc0000"><font size="3">并不是全部：其它日志处理工具</font><br /><br /></font></u></strong>    除了J2SE Logging API和log4j，日志处理方面还有别的技术：Jakarta的<a href="http://jakarta.apache.org/commons/" target="_blank"><font color="#618b2c">commons</font></a>组件项目中的<a href="http://jakarta.apache.org/commons/logging/" target="_blank"><font color="#618b2c">JCL</font></a>（Jakarta Commons Logging）是一个不错的选择，它有点类似于GSS-API（通用安全服务接口）中的思想，其日志服务机制是可以替换的，也就是说既可以用J2SE Logging API也可以用log4j，但JCL对开发人员提供一致的接口，这一点相当重要，组件可重用正是Jakarta Commons项目追求的一个目标；<a href="http://www.ibm.com/" target="_blank"><font color="#618b2c">IBM</font></a>的<a href="http://www.alphaworks.ibm.com/tech/loggingtoolkit4j" target="_blank"><font color="#618b2c">JLog</font></a>也是在J2SE Logging API之前推出的一个工具包，但JLog是一个商业产品。<br />    至于日志API的应用那可就多了，现在哪个大一点的工具或平台不用到日志模块呢？Tomcat、JBoss……<br /></p><p class="postText" align="left">    说了这么多，我们无非需要知道的一件事就是，“调试”也是一门学问。在我们一个劲地用System.out.println(...)而且用得很爽的时候，也应该想想看，如何让这样一条菜鸟语句也能变得人性化和丰富多彩。</p><p class="postText" align="left"><a name="ref"></a><strong><u><font color="#cc0000" size="3">参考资料</font></u></strong></p><div class="postText" align="left"><ul><li><font color="#000080" size="-1"><a href="http://java.sun.com/j2se/1.4.2/docs/guide/util/logging/index.html" target="_blank">Java Logging Documentation</a></font></li><li><font color="#000080" size="-1"><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/package-summary.html" target="_blank">Java Logging APIs</a></font></li><li><font size="-1">J2SE进阶, by <a href="http://www.javaresearch.org/" target="_blank"><em><font color="#618b2c">www.javaresearch.org</font></em></a></font></li><li><font size="-1"><a href="http://logging.apache.org/log4j/docs/manual.html" target="_blank"><font color="#618b2c">Short introduction to log4j</font></a>, by <em>Ceki Gülcü</em></font></li><li><font color="#000080" size="-1"><a href="http://logging.apache.org/log4j/docs/api/index.html" target="_blank">log4j APIs</a></font></li><li><font color="#000080" size="-1"><a href="http://logging.apache.org/log4j/docs/faq.html" target="_blank">FAQ about log4j</a></font></li></ul></div></font>
		</div>
<img src ="http://www.blogjava.net/19851985lili/aggbug/91557.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/19851985lili/" target="_blank">☜♥☞MengChuChen</a> 2007-01-03 15:58 <a href="http://www.blogjava.net/19851985lili/articles/log4j.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>