??xml version="1.0" encoding="utf-8" standalone="yes"?>相泽南亚洲一区二区在线播放,亚洲日韩精品无码专区网站,久久亚洲一区二区 http://m.tkk7.com/19851985lili/category/18934.html☜GivE mE HapPy ?
zh-cn Wed, 28 Feb 2007 03:42:57 GMT Wed, 28 Feb 2007 03:42:57 GMT 60 单的说log4j是帮助开发h员进行日志输出管理的APIcd。它最重要的特点就 http://m.tkk7.com/19851985lili/articles/97641.html☜♥☞MengChuChen ☜♥☞MengChuChen Fri, 02 Feb 2007 12:30:00 GMT http://m.tkk7.com/19851985lili/articles/97641.html http://m.tkk7.com/19851985lili/comments/97641.html http://m.tkk7.com/19851985lili/articles/97641.html#Feedback 0 http://m.tkk7.com/19851985lili/comments/commentRss/97641.html http://m.tkk7.com/19851985lili/services/trackbacks/97641.html
可以
配置文g灉|的设|?/span>
日志信息的优先、日志信息的输出目的C及日志信息的输出格式?span lang="EN-US">
Log4j除了可以记录E序q行日志信息外还有一重要的功能就是用?/span>
昄调试信息。程序员l常会遇到脱?span lang="EN-US">java ide环境调试E序的情况,q时大多Ch会选择使用System.out.println语句输出某个变量值的Ҏq行调试。这样会带来一个非帔R烦的问题Q一旦哪天程序员军_不要昄q些System.out.println的东西了只能一行行的把q些垃圾语句注释掉。若哪天又需调试变量|则只能再一行行Lq些注释恢复System.out.println语句。用log4j可以很好的处理类似情c?o:p>
log4j使用Ҏ
下面介绍的是log4j一些理论方面的知识Q读者觉得枯燥的话可以蟩q本节直接阅ȝ三节实例部分?o:p>
1、定义配|文?o:p>
首先使用配置文g我们的应用程序更加灵z配|log日志输出方式包括输出优先U、输出目的地、输出格式。Log4j支持两种配置文g格式Q一U是XML格式的文Ӟ一U是JavaҎ文件log4j.propertiesQ键=|。下面将介绍使用log4j.properties文g作ؓ配置文g的方法:
?/span>
配置根LoggerQ其语法为:0
log4j.rootLogger = [ level ] , appenderName, appenderName, ?
其中Q?span lang="EN-US">level 是日志记录的优先U,分ؓOFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定义的别。Log4j只用四个别,优先U从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的U别Q您可以控制到应用程序中相应U别的日志信息的开兟뀂比如在q里定义了INFOU别Q则应用E序中所有DEBUGU别的日志信息将不被打印出来?appenderName是指定日志信息输出到哪个地斏V可同时指定多个输出目的地?
?/span>
配置日志信息输出目的地AppenderQ其语法为:
log4j.appender.appenderName = fully.qualified.name.of.appender.class log4j.appender.appenderName.option1 = value1 ? log4j.appender.appenderName.option = valueN
其中Q?/font>
Log4j提供的appender有以下几U: org.apache.log4j.ConsoleAppenderQ控制台Q, org.apache.log4j.FileAppenderQ文ӞQ? org.apache.log4j.DailyRollingFileAppenderQ每天生一个日志文ӞQ?br /> org.apache.log4j.RollingFileAppenderQ文件大到达指定尺寸的时候生一个新的文ӞQ? org.apache.log4j.WriterAppenderQ将日志信息以流格式发送到L指定的地方)
?/span>
配置日志信息的格式(布局Q,其语法ؓQ?o:p>
log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class log4j.appender.appenderName.layout.option1 = value1 ? log4j.appender.appenderName.layout.option = valueN
其中Q?/font>
Log4j提供的layout有以下几U: org.apache.log4j.HTMLLayoutQ以HTML表格形式布局Q, org.apache.log4j.PatternLayoutQ可以灵zd指定布局模式Q, org.apache.log4j.SimpleLayoutQ包含日志信息的U别和信息字W串Q, org.apache.log4j.TTCCLayoutQ包含日志生的旉、线E、类别等{信息)
Log4J采用cMC语言中的printf函数的打印格式格式化日志信息Q打印参数如下: %m 输出代码中指定的消息
%p 输出优先U,即DEBUGQINFOQWARNQERRORQFATAL %r 输出自应用启动到输出该log信息耗费的毫U数 %c 输出所属的cȝQ通常是所在类的全? %t 输出产生该日志事件的U程? %n 输出一个回车换行符QWindowsq_为“\r\n”,Unixq_为“\n? %d 输出日志旉点的日期或时_默认格式为ISO8601Q也可以在其后指定格式,比如Q?d{yyy MMM dd HH:mm:ss,SSS}Q输出类|
2002q?0?8?/font>
22Q?0Q?8Q?21 %l 输出日志事g的发生位|,包括cȝ名、发生的U程Q以及在代码中的行数。D例:Testlog4.main(TestLog4.java:10)
2、在代码中用Log4j
?/span>
得到记录?o:p>
使用Log4jQ第一步就是获取日志记录器Q这个记录器负责控制日志信息。其语法为:
public static Logger getLogger( String name)
通过指定的名字获得记录器Q如果必要的话,则ؓq个名字创徏一个新的记录器?span lang="EN-US">Name一般取本类的名字,比如Q?
static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () )
?/span>
d配置文g
当获得了日志记录器之后,W二步将配置Log4j环境Q其语法为:
BasicConfigurator.configure ()Q?自动快速地使用~省Log4j环境?br /> PropertyConfigurator.configure ( String configFilename) Q读取用Java的特性文件编写的配置文g?o:p>
例:PropertyConfigurator.configure
(".\\src\\log4j.properties")
DOMConfigurator.configure ( String filename ) Q读取XML形式的配|文件?o:p>
?/span>
插入记录信息Q格式化日志信息Q?o:p>
当上两个必要步骤执行完毕Q就可轻村֜使用不同优先U别的日志记录语句插入到您想记录日志的Q何地方,其语法如下:
Logger.debug ( Object message ) ; Logger.info ( Object message ) ; Logger.warn ( Object message ) ; Logger.error ( Object message ) ;
log4j范例E序
下面用一个最单的范例E序来进一步说?span lang="EN-US">log4j的用方法。程序代码如下:
import org.apache.log4j.*;
public class
LogTest
{
static
Logger logger = Logger.getLogger(LogTest.class.getName());
public
static
void
main(String[] args)
{
PropertyConfigurator.configure ( ?\\src\
log4j.properties
?
Q?/span>
logger.debug(
"Debug ..."
);
logger.info(
"Info ..."
);
logger.warn(
"Warn ..."
);
logger.error(
"Error ..."
);
}
}
E序说明Q?span lang="EN-US">
?/span>
static Logger logger = Logger.getLogger(LogTest.class.getName());
是创徏一个属?/span>
LogTest
cȝ
Logger
对象Q创建时要告?/span>
Logger
你当前的
Class
是什么?/span>
?/span>
PropertyConfigurator.configure ( ?/span>
log4j.properties
?
是说用当前工E目录下?/span>
src
文g夹中?/span>
log4j.properties
文g作ؓ配置文g。若?/span>
log4j.properties
攑֜工程根目录下也可不写此句Q程序会自动扑ֈ配置文g?/span>
?/span>
logger.debug
是输出
debug
的信息,
logger.info
是输出提示信息Q?/span>
logger.warn
是昄警告信息Q?/span>
logger.error
是昄错误信息?/span>
下面是配|文?/span>
log4j.properties
的内容:
log4j.rootCategory=DEBUG, stdout
Q?/span>
R
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p (%F:%L) - %m%n
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=log.txt
log4j.appender.R.MaxFileSize=100KB
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d
{
yyyy MMM dd HH:mm:ss
}
%-5p %c - %m%n
E序说明Q?span lang="EN-US">
?/span>
log4j.rootCategory=DEBUG, stdout
Q?/span>
R
是说我要显C所有优先权{於和高?/span>
Debug的信息?br />"stdout"Q?/span>
”R?/span>
表示我定义了两个输出?/span>
(
随便什么名字都?/span>
)
?/span>
?/span>
下面的三行说
stdout
输出端其实是标准输出
Console
Q也是屏幕。输出的格式?/span>
Pattern
Layout
。{换方式是
%5p (%F:%L) - %m%n
Q即前五格用来显CZ先权Q再昄当前的文件名Q加当前的行数。最后是
logger.debug()
?/span>
logger.info()
?/span>
logger.warn()
?/span>
logger.error()
里的信息?/span>
%n
表示回RI?/span>
?/span>
再加上下面六行则
log
信息不光昄在屏q上Q而且被保存在一个叫
"log.txt"
的文仉Q文件最大ؓ
100KB
。如果文件大超q?/span>
100KB
Q文件会被备份成
"log.txt.1"
Q新?/span>
"log.txt"
l箋记录
log
信息?/span>
接下来我们可以改?/span>
log4j.properties
Q而不需重新~译可以控?/span>
log
信息是否昄?/span>
log
信息的输出端cd、输出方式、输出格式,{等。D例如下:
?/span>
?/span>
log4j.properties
文g里把
"log4j.rootCategory=DEBUG,stdout,R"
改写?/span>
"log4j.rootCategory=OFF, stdout,R"
Q这h有的
log信息都不会显CZQ解决了本文开始提出的问题?br />?/span>
?/span>
log4j.properties
文g里把
"log4j.rootCategory=DEBUG,stdout,R"
改写?/span>
"log4j.rootCategory=INFO, stdout,R"
Q这样只昄
INFO, WARN, ERROR
?/span>
log
信息Q?/span>
DEBUG
信息不会被显C;
?span lang="EN-US">webE序中用log4j注意问题
1?span style="FONT: 7pt 'Times New Roman'">
׃jsp或servlet在执行状态时没有当前路径概念Q所有?/span>
PropertyConfigurator.configure
Q?/span>
String
Q语句找
log4j.properties
文g时要l出相对于当?/span>
jsp
?/span>
servlet
的\径{化成Z个绝对的文gpȝ路径。方法是使用
servletcontext.getrealpath(string)
语句。例Q?/span>
//得到当前jsp路径
String prefix = getServletContext().getRealPath(
"/");
//d
log4j.properties
PropertyConfigurator.configure(prefix+
"\\WEB-INF\\log4j.properties");
2、相应的log4j.properties讄某个属性时也要在程序中讄l对路径。例Q?o:p>
log4j.appender.R.File属性设|日志文件存放位|。我们可以用d.properties配置文g的方法进行灵z设|?span style="COLOR: black">
]]> Log4j明手册(3/3Q? http://m.tkk7.com/19851985lili/articles/91587.html☜♥☞MengChuChen ☜♥☞MengChuChen Wed, 03 Jan 2007 09:04:00 GMT http://m.tkk7.com/19851985lili/articles/91587.html http://m.tkk7.com/19851985lili/comments/91587.html http://m.tkk7.com/19851985lili/articles/91587.html#Feedback 0 http://m.tkk7.com/19851985lili/comments/commentRss/91587.html http://m.tkk7.com/19851985lili/services/trackbacks/91587.html
Log4j明手册(3/3Q?/font>
7. Nested Diagnostic Contexts 在现实世界中的系l经怸得不同时处理多个客户端请求。在q样的一个典型的多线E的pȝ中,不同的线E将处理不同的客L。Logging特别能够适应q种复杂的分布式的应用程序的调试和跟t。一个常见的区分每个客户端所输出的Logging的方法是为每个客L实例化一个新的独立的Logger。这DLogger的大量生,理的成本也过了logging本n? 唯一标识每个logh是一个轻量的技术。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). Z唯一标识每个hQ用h上下文信息推入NDC(Nested Diagnostic Context)中?br /> NDCcȝ例如下: public class NDC { // Used when printing the diagnostic public static String get(); // Remove the top of the context from the NDC. public static String pop(); // Add diagnostic context for the current thread. public static void push(String message); // Remove the diagnostic context for this thread. public static void remove(); } NDC如同一个堆栈样理每个U程。注意所有the org.apache.log4j.NDC cȝҎ都是静态的。假设NDC输出被开启,每次一个log h被生成时Q适当的log4jlg为将要输出log的线E包含完整的NDC堆栈。这是在没有用户的干预的情况下做到的Q用户只负责在NDC中定位正的信息Q通过在代码中正确位置插入很少的push和popҎp了。相反的Q在代码中per-client实现Ҏ有着很大变化?br /> Z演示q个点,让我们以一个发送内容到匿名客户端的servletZ。这个servlet可以在开始执行每个其他代码前的初始化时徏立NDC。上下文信息可以是客户主机的名字和其他的h中固有的信息?br /> 典型的信息包括cookies。因此,即servlet同时为多个客户同时提供服务,log 被同L代码初始化,例如属于同一个loggerQ依然可以被区别Q因为每个客戯求将有不同的NDC堆栈。与之相比,Contrast this with the complexity of passing a freshly instantiated logger to all code exercised during the client's request?br /> 不过Q一些诡异的E序Q例如虚拟主机的web server记录日志Q不是一般的依靠虚拟L的上下文Q还要依靠Y件的lg发出h。近来log4j的发布版本支持多层的树Şl构。这个增强允许每个虚拟主机可以处理在树型l构中属于它自己的logger?br /> 8. 优化 一个经常引用的依靠于logging的参数是可以计算的花贏V这是一个合理的概念Q一个适度的应用程序可能生成千上万个日志h。许多努力花在测量和调试logging的优化上。Log4j要求快速和Ҏ:速度最重要Q弹性是其次?br /> 用户应该注意随后的优化徏议?br /> 1.日志为禁用时Q日志的优化?br /> 当日志被d的关闭,一个日志请求的p{于一个方法的调用加上整数的比较时间?br /> ?33mhz的Pentium II 机器上这个花贚w常?-50U秒之间?br /> 然而,Ҏ调用包括参数构徏的隐藏花贏V?br /> 例如Q对于logger catQ?br /> logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i])); 引v了构Z息参数的pQ例如,转化整数i和entry[i]C个stringQƈ且连接中间字W串Q不信息是否被输出。这个参数的构徏p可能是很高,它主要决定于被调用的参数的大?br /> 避免参数构徏的花费应如下Q?br /> if(logger 如果logger的debug被关闭这不会招致参数构建的p。另一斚wQ如果logger是debug的话Q它生两ơ判?logger是否能用的花贏V一ơ是在debugenabledQ一ơ是debug。这是无关紧要的Q因为判断日志的能用 只占日志实际p旉的约1%?br /> 在Log4j里,日志h在Logger cȝ实例里。Logger 是一个类Q而不是一个接口。这大量的减了在方法调用上的弹性化的花贏V?br /> 当然用户采用预处理或~译旉技术去~译出所有的日志声明。这导致完的执行成效。然而因Zq制应用E序不包括Q何的日志声明的结果,日志不可能对那个二进制程序开启。以我的观点Q以q种较大的代h换取较小的性能优化是不值得的?br /> 2。当日志状态ؓ启用Ӟ日志的优化?br /> q是本质上的优化logger的层ơ。当日志状态ؓ开QLog4j依然需要比较请求的U别与logger的别。然而, logger可能没有被安排一个别;它们从它们的fatherl承。这P在承之前,logger可能需要搜索它的ancestor?br /> q里有一个认真的努力使层ơ的搜烦可能的快。例如,子logger仅仅q接到它的存在的father logger?br /> 在先前展C的BasicConfigurator 例子中,名ؓcom.foo.bar 的logger是连接到跟根loggerQ因此绕q?了不存在的logger com和com.foo。这显著的改善执行的速度Q特别是解析logger的层l构时?br /> 典型的层ơ结构的解析的花Ҏloggerd关闭时的三倍?br /> 3.日志信息的输出时Q日志的优化?br /> q是主要p在日志输出的格式化和发送它到它的输出源上。这里我们再一ơ的付出努力以格式化执行的可能快。同appender一栗实际上典型的花费大U是100-300毫秒?br /> 详情看org.apache.log4.performance.Logging?br /> 虽然Log4j有许多特点,但是它的W一个设计目标还是速度。一些Log4j的组件已l被重写q很多次以改善性能。不q,投稿者经常提Z新的优化。你应该满意的知道,以SimpleLayout的配|执行测试已l展CZLog4j的输出同System.out.println一样快?br /> 9. ȝ Log4j是一个用java写成的流行的日志包。一个它与众不同的特Ҏ在logger中的l承的概c用logger的承可以以L的间隔控制日志的状态输出。这个减了体积和最化日志的代仗?br /> 易管理性是Log4j API的优点之一。只要日志定义被加入C码中Q它们就可以用配|文件来控制。它们可以有选择的被用Qƈ且发送到不同的多个输出源上,以用户选择好的格式?br /> Log4j的包被设计成Q不需p沉重的执行代价就可以保留它们在品中?/font>
]]> g4j明手册(2/3Q? http://m.tkk7.com/19851985lili/articles/91585.html☜♥☞MengChuChen ☜♥☞MengChuChen Wed, 03 Jan 2007 09:03:00 GMT http://m.tkk7.com/19851985lili/articles/91585.html http://m.tkk7.com/19851985lili/comments/91585.html http://m.tkk7.com/19851985lili/articles/91585.html#Feedback 0 http://m.tkk7.com/19851985lili/comments/commentRss/91585.html http://m.tkk7.com/19851985lili/services/trackbacks/91585.html 4. 配置 插入日志h到应用程序的代码中需要大量的预先计划和最l努力。观察显C大U?%的代码是用来输出的?br /> 因此Q大适度的程序都被嵌入有成千个日志输句。ؓ了以无需手工的方式管理这些日志的输出状态,l日志输Z~号和规范变得势在必行? Log4j在程序中有充分的可配|性。然而,用配|文仉|Log4jh更大的弹性。目前,它的配置文g支持xml和java propertiesQkey=valueQ文件两U格式?br /> 让我们以一个例子来演示它是如何做的。假定有一个用了Log4j的程序MyApp?br /> import com.foo.Bar; // Import Log4j classes. import org.apache.Log4j.Logger; import org.apache.Log4j.BasicConfigurator; public class MyApp { // Define a static logger variable so that it references the // Logger instance named "MyApp". static Logger logger = Logger.getLogger(MyApp.class); public static void main(String[] args) { // Set up a simple configuration that logs on the console. BasicConfigurator.configure(); logger.info("Entering application."); Bar bar = new Bar(); bar.doIt(); logger.info("Exiting application."); } } MyApp以引入Log4j的相关类开始,接着它定义了一个静态logger变量Qƈl予gؓ"MyApp"cȝ全\径名U?br /> MYApp用了定义在包com.foo中的cBar. package com.foo; import org.apache.Log4j.Logger; public class Bar { static Logger logger = Logger.getLogger(Bar.class); public void doIt() { logger.debug("Did it again!"); } } 调用BasicConfigurator.configure()Ҏ创徏了一个相当简单的Log4j的设|。它加入一 个ConsoleAppender到根logger。输出将被采用了"%-4r [%t] %-5p %c %x - %m%n"模式 的PatternLayout所格式化?br /> 注意Q根logger默认被分配了Level.DEBUG的别?br /> MyApp的输ZؓQ?br /> 0 [main] INFO MyApp - Entering application. 36 [main] DEBUG com.foo.Bar - Did it again! 51 [main] INFO MyApp - Exiting application. 随后的图形描qC在调用BasicConfigurator.configure()Ҏ后MyApp的对象图?br /> 一边要提醒的是QLog4j的子logger只连接到已经存在的它们的父代。特别的是,名ؓ com.foo.bar的logger是直接连接到根loggerQ而不是围l着没用的com或com.foo logger。这显著的提高了E序性能q且减少的内存占用?br /> MyAppc配|Log4j是通过调用BasicConfigurator.configure Ҏ。其它的cM?br /> 需要引入org.apache.Log4j.Logger c,扑ֈ它们希望用的loggerQƈ且用它就行?br /> 以前的例子通常输出同样的日志信息。幸q的是,修改MyApp是容易的Q以便日志输 出可以在q行时刻被控制。这里是一个小修改的版本?br /> import com.foo.Bar; import org.apache.Log4j.Logger; import org.apache.Log4j.PropertyConfigurator; public class MyApp { static Logger logger = Logger.getLogger(MyApp.class.getName()); public static void main(String[] args) { // BasicConfigurator replaced with PropertyConfigurator. PropertyConfigurator.configure(args[0]); logger.info("Entering application."); Bar bar = new Bar(); bar.doIt(); logger.info("Exiting application."); } } 修改后的 MyApp通知E序调用PropertyConfigurator()Ҏ解析一个配|文Ӟq且?br /> 据这个配|文件来讄日志?br /> q里是一个配|文件的例子Q它生同以前BasicConfigurator 基本例子一?br /> 的输出结果?br /> # Set root logger level to DEBUG and its only appender to A1. Log4j.rootLogger=DEBUG, A1 # A1 is set to be a ConsoleAppender. Log4j.appender.A1=org.apache.Log4j.ConsoleAppender # A1 uses PatternLayout. Log4j.appender.A1.layout=org.apache.Log4j.PatternLayout Log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n 假设我们不在对com.foo包的Mcȝ输出感兴的话,随后的配|文件向我们展示 了实现这个目的的Ҏ之一?br /> Log4j.rootLogger=DEBUG, A1 Log4j.appender.A1=org.apache.Log4j.ConsoleAppender Log4j.appender.A1.layout=org.apache.Log4j.PatternLayout # Print the date in ISO 8601 format Log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n # Print only messages of level WARN or above in the package com.foo. Log4j.logger.com.foo=WARN 以这个配|文仉|好的MyApp输出如下: 2000-09-07 14:07:41,508 [main] INFO MyApp - Entering application. 2000-09-07 14:07:41,529 [main] INFO MyApp - Exiting application. 当logger com.foo.bar没有被分配一个别,它将从com.fool承Q在配置文g?br /> 它被讄了WARN的别。在Bar.doItҎ中定义的log为DEBUGU别Q低于WARNQ?br /> 因此doIt() Ҏ的日志请求被用?br /> q里是另外一个配|文Ӟ它用了多个appenders. Log4j.rootLogger=debug, stdout, R Log4j.appender.stdout=org.apache.Log4j.ConsoleAppender Log4j.appender.stdout.layout=org.apache.Log4j.PatternLayout # Pattern to output the caller's file name and line number. Log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n Log4j.appender.R=org.apache.Log4j.RollingFileAppender Log4j.appender.R.File=example.log Log4j.appender.R.MaxFileSize=100KB # Keep one backup file Log4j.appender.R.MaxBackupIndex=1 Log4j.appender.R.layout=org.apache.Log4j.PatternLayout Log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n 以这个配|文件调用加Z的MyAppcd输出如下信息. INFO [main] (MyApp2.java:12) - Entering application. DEBUG [main] (Bar.java:8) - Doing it again! INFO [main] (MyApp2.java:15) - Exiting application. 另外,因ؓ根logger有被分配W二个appender,所以输Z被定向到example.log文g?br /> q个文g大小辑ֈ100kb时将自动备䆾。备份时老版本的example.log文g自动被移?br /> 文gexample.log.1中?br /> 注意我们不需要重新编译代码就可以获得q些不同的日志行为。我们一样可以容?br /> 的日志输出到UNIX Syslog daemon, 重定向所有的com.foo到NT Event logger, 或者{发日志到一个远E的Log4j服务?它根据本地server的策略来q行日志输出。例 如{发日志事件到W二个Log4j服务? 5. 默认的初始化q程 Log4jcd不对它的环境做Q何假设。特别是没有默认的Log4j appender。在一些特?br /> 的有着良好定义的环境下Qlogger的静态inializer尝试自动的配置Log4j?br /> java语言的特性保证类的静态initializer当且仅当装蝲cd内存之时只会被调用一ơ?br /> 要记住的重要一ҎQ不同的c装载器可能装蝲同一个类的完全不同的拯?br /> q些同样cȝ拯被虚拟机认ؓ是完全不相干的?br /> 默认的initialization是非常有用的Q特别是在一些应用程序所依靠的运行环境被准确?br /> 定位的情况下。例如,同一L应用E序可以被用做一个标准的应用E序Q或一?br /> appletQ或一个在web-server控制下的servlet?br /> 准确的默认的initialization原理被定义如下: 1.讄pȝ属性Log4j.defaultInitOverride?false"以外的其它|那么Log4j?br /> 跌默认的initializationq程?br /> 2.讄资源变量字符串给pȝ属性Log4j.configuration。定义默认initialization 文g的最好的Ҏ是通过pȝ属性Log4j.configuration。万一pȝ属?br /> Log4j.configuration没有被定义,那么讄字符串变量resource l它的默认?br /> Log4j.properties?br /> 3.试转换resource 变量Z个URL?br /> 4.如果变量resource的g能被转换Z个URLQ例如由于MalformedURLExceptionq?br /> 例,那么通过调用 org.apache.Log4j.helpers.Loader.getResource(resource, Logger.class) Ҏ?br /> classpath中搜索resourceQ它返回一个URLQƈ通知"Log4j.properties"的值是一个错 误的URL?br /> 看See Loader.getResource(java.lang.String) 查看搜烦位置的列表?br /> 5.如果没有URL被发玎ͼ那么攑ּ默认的initialization。否则用URL配置Log4j?br /> PropertyConfigurator用来解析URLQ配|Log4jQ除非URL?.xml"为结?br /> 在这U情况下的话DOMConfigurator被调用。你可以有机会定义一个自定义?br /> configurator?br /> pȝ属性Log4j.configuratorClass 的值取自你的自定义的类名的全\径?br /> 你自定义的configurator必须实现configurator接口?br /> 6. 配置范例 6.1 Tomcat下的初始?br />默认的Log4j initialization典型的应用是在web-server 环境下。在tomcat3.x和tomcat4.x 下,你应该将配置文gLog4j.properties攑֜你的web应用E序的WEB-INF/classes 目录 下?br /> Log4j发现属性文Ӟq且以此初始化。这是它工作的最Ҏ的方法?br /> 你也可以选择在运行tomcat前设|系l属性Log4j.configuration 。对于tomcat 3.xQ?br /> TOMCAT_OPTS pȝ变量是用来设|命令行的选项。对于tomcat4.0Q用pȝ环境?br /> 量CATALINA_OPTS 代替了TOMCAT_OPTS?br /> Example 1 UNIX 命o?br /> export TOMCAT_OPTS="-DLog4j.configuration=foobar.txt" 告诉Log4j用文件foobar.txt作ؓ默认的配|文件。这个文件应该放在WEB-INF/classes 目录下。这个文件将被PropertyConfigurator所诅R每个web-application用不同的默?br /> 配置文gQ因为每个文件是和它的web-application 相关的?br /> Example 2 UNIX 命o?br /> export TOMCAT_OPTS="-DLog4j.debug -DLog4j.configuration=foobar.xml" 告诉Log4j输出Log4j-internal的调试信息,q且用foobar.xml作ؓ默认的配|文件?br /> q个文g应该攑֜你的web-application的WEB-INF/classes 目录下。因为有.xml?br /> 扩展名,它将被DOMConfigurator所诅R每个web-application用不同的默?br /> 配置文g。因为每个文仉和它所在的web-application 相关的?br /> Example 3 UNIX 命o?br /> set TOMCAT_OPTS=-DLog4j.configuration=foobar.lcf -DLog4j.configuratorClass=com.foo.BarConfigurator 告诉Log4j用文件foobar.lcf作ؓ默认的配|文件。这个文件应该放在你?br /> web-application的WEB-INF/classes 目录下。因为定义了Log4j.configuratorClass pȝ?br /> 性,文g用自定义的com.foo.barconfiguratorcL解析。每个web-application用?br /> 同的默认配置文g。因为每个文仉和它所在的web-application 相关的?br /> Example 4 UNIX 命o?br /> set TOMCAT_OPTS=-DLog4j.configuration=file:/c:/foobar.lcf 告诉Log4j用文件foobar.lcf作ؓ默认的配|文件。这个配|文件用URL file:/c:/foobar.lcf 定义了全路径名。这样同L配置文g被所有的web-application所用?br /> 不同的web-application通过它们自己的类装蝲器来装蝲Log4j。这P每个Log4j的环 境将独立的运作,而没有Q何的怺同步。例如:在多个web-application中定义了 完全相同的输出源的FileAppenders尝试写同样的文件。结果好象是~Z安全性的?br /> 你必ȝ保每个不同的web-application的Log4j配置没有用到同样的系l资源?br /> 6.2 Servlet 的初始化 用一个特别的servlet来做Log4j的初始化也是可以的。如下是一个例子: package com.foo; import org.apache.Log4j.PropertyConfigurator; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.PrintWriter; import java.io.IOException; public class Log4jInit extends HttpServlet { public void init() { String prefix = getServletContext().getRealPath("/"); String file = getInitParameter("Log4j-init-file"); // if the Log4j-init-file is not set, then no point in trying if(file != null) { PropertyConfigurator.configure(prefix+file); } } public void doGet(HttpServletRequest req, HttpServletResponse res) { } } 在web.xml中定义随后的servletZ的web-application?br />Log4j-init com.foo.Log4jInit Log4j-init-file WEB-INF/classes/Log4j.lcf 1 写一个初始化的servlet是最有弹性的初始化Log4j的方法。代码中没有M限制Q你?br /> 以在servlet的initҎ中定义它?/font>
]]> Log4j明手? http://m.tkk7.com/19851985lili/articles/91583.html☜♥☞MengChuChen ☜♥☞MengChuChen Wed, 03 Jan 2007 09:00:00 GMT http://m.tkk7.com/19851985lili/articles/91583.html http://m.tkk7.com/19851985lili/comments/91583.html http://m.tkk7.com/19851985lili/articles/91583.html#Feedback 0 http://m.tkk7.com/19851985lili/comments/commentRss/91583.html http://m.tkk7.com/19851985lili/services/trackbacks/91583.html Log4j明手?br /> 1. 概述 本文主要描述Log4j的API的唯一Ҏ和它的设计原理。Log4j是一个基于许多作者的开放源码的目。它允许开发员以Q意的间隔来控制日志的输出。它通过讑֜外部的配|文件而达到运行时灉|的设|。最重要的是QLog4j有一个^E的学习曲线。注意:Ҏ来自用户的反馈判断,它很Ҏ使h上瘾?br /> 2. D 几乎所有的大型应用E序都包括它的自q日志和跟tAPI。顺应这个规则,E.U. SEMPER 目军_写它自己的跟tPAI。这?996q初。在无数ơ加强,几次变Ş和许多工作后Q那个API变成了如今的Log4jQ一个流行的java日志包。这个包以Apache Software License协议发布Q一个成熟的开放源吗协议。最新的Log4j版本Q包括全部的源码Qclass文g和文,你可以在http://jakarta.apache.org/Log4j/上找到。顺便,Log4j已经lC, C++, C#, Python, Ruby, and Eiffel 语言都提供了接口?br /> Z调试而插入日志输出到代码里是一个低技术成分的ҎQ但它可能也是唯一的方法,因ؓ调试器ƈ不是一直可用或者可以适应的,其对于多线E的分布使式的大型程序而言?br /> l验指出调试是Y件开发周期中一个重要的l成部分?br /> Log4j拥有几个优点Q?br /> 首先Q它提供关于q行E序的准的环境。一旦代码被插入Q不需要h工干预就可以产生调试信息?br /> 其次Q日志输出可以被有计划的保存在永久媒体中以便日后研究?br /> 另外Q除了在开发周期中Q一个充分详的日志包可以被用来作ؓ以后的统计工兗?br /> Log4j当然q有它的~点Q它可能减慢E序。如果太详细Q它可能D屏幕盲目滚动。排除这些情况,Log4j是可靠的Q快速的Q可以扩展的。因为日志很是一个应用程序的主要目的, 设计者们正努力得Log4j API学习和用简单化?br /> 3. 日志cd、输出源和布局 Log4j有三个主要的lgQ日志类别(LoggersQ、输出源Q?AppendersQ和布局QLayoutsQ。这三种cd的组件一起工作得开发员可以Ҏ信息的类型和U别记录它们Qƈ且在q行时控制这些信息的输出格式和位|?br /> 3.1 日志cd的层ơ结?Loggers) Log4j首要的相对于单的使用System.out.println()Ҏ的优ҎZ它的在禁止一些特定的信息输出的同时不妨碍其它信息的输出的能力。这个能力源自于日志命名I间Q也是_所有日志声明的I间Q它Ҏ一些开发员选择的公式而分cR以前的观察引导我们选择cd作ؓ包的中心概念。然而,自从Log4j?.2版本QLoggerc被CatalogcL取代Q对于那些熟悉Log4j以前版本的h来说QLoggercd以被惌成仅仅是Category cȝ别名?br /> Loggers 被指定ؓ实体QLogger的名字是大小写敏感的Q它们遵循以下的命名 规则Q?br /> 2 命名l承 如果cd的名Uͼ后面加一个点Q是其子cd名称的前~Q则它就是另一个类别的辈?br /> 如果一个类?Logger)和它的子cd之间没有其它的承关p,我们q之ؓparent与child的关pR?br /> 例如Q类?com.foo"是类?com.foo.Bar"的parent。相似的Q?java"?java.util"的parentQ是"java.util.Vector"的父辈?q个命名规则应该被大多数的开发员所熟悉?br /> ?root) cd位于loggerl承l构的最上层。它有两U例外: 1.它一直存?br /> 2.它不能根据名U而获得? 调用cȝ静态方法Logger.getRootLogger可以得到它。其它所有的Logger可以通过静态方法Logger.getLogger而得到它们自q实例。这个方法取希望的Logger名作为参数。Logger的一些基本的ҎCZ如下Q?br /> package org.apache.Log4j; public Logger class { // Creation & retrieval methods: public static Logger getRootLogger(); public static Logger getLogger(String name); // printing methods: public void debug(Object message); public void info(Object message); public void warn(Object message); public void error(Object message); // generic printing method: public void log(Level l, Object message); } Loggers可以被分配的U别。所有别的集合包括Q?br /> DEBUG INFO WARN ERROR FATAL 它们被定义于org.apache.Log4j.Level cR虽然我们不鼓励Q但是你们可以通过l承LevelcL定义你们自己的别。我们随后将介绍一个比较好的方法?br /> 如果一个Logger没有被分配一个别,那么它将从一个被分配了别的最接近它的ancestor哪里l承?br /> 正规的说Q?br /> 2 U别l承 对于一个给定的Logger CQ它的承的U别{于从C开始上溯到的第一个拥有非I别的Logger的别?br /> Z保证所有的Logger最l能够承到一个别,根Logger通常有一个已l定义了的别?br /> 以下四个表中的数据演CZҎ以上规则得到的结果?br /> cd?br />分配的?br />l承的?br /> root Proot Proot X none Proot X.Y none Proot X.Y.Z none Proot Example 1 在例?中,只有根Logger定义了一个别,它的U别的?-"Proot"被所有其它的Loggers X, X.Y, 和X.Y.Z所l承?br /> cd?br />分配的?br />l承的?br /> root Proot Proot X Px Px X.Y Pxy Pxy X.Y.Z Pxyz Pxyz Example 2 在例?中,所有的Logger都有一个被分配的别|所以它们不需要别ѝ?br /> cd?br />分配的?br />l承的?br /> root Proot Proot X Px Px X.Y none Px X.Y.Z Pxyz Pxyz Example 3 在例?中,根LoggerQ以及X和X.Y.Z被分别分配了U别ProotQPx和Pxyz。Logger X.Y从它的parent Xl承了别值Px?br /> cd?br />分配的?br />l承的?br /> root Proot Proot X Px Px X.Y none Px X.Y.Z none Px Example 4 在例?中,根Logger和X被分别分配了U别"Proot"?Px"QLogger X.Y ?X.Y.Z从被分配了别的最接近它们的ancestor X那里得到l承?br /> 我们需要通过调用Logger的输出的实例Ҏ之一来实现日志请求。这些输出的Ҏ是debug, info, warn, error, fatal ?log. 通过定义输出Ҏ来区分日志的h的别。例如,如果c是一个Logger的实例,那么声明 c.info 是一个INFOU别的日志请求?br /> 如果一个日志的h的别高于或{于日志的别那么它p被启用。反之,被用。一个没有被安排U别的Logger从它的父辈中得到ѝ这个规则ȝ如下?br /> 2 基本的选择规则 假如在一个别ؓq的Logger中发生一个别ؓp的日志请求,如果p>=q,那么h被启用?br /> q是Log4j的核心原则。它假设U别是有序的。对于标准别,我们定义DEBUG < INFO < WARN < ERROR < FATAL. 以下是关于这条规则的一个例子?br /> // get a logger instance named "com.foo" Logger logger = Logger.getLogger("com.foo"); // Now set its level. Normally you do not need to set the // level of a logger progamitcally. This is usually done // in configuration files. cat.setLevel(Level.INFO); Logger barlogger = Logger.getLogger("com.foo.Bar"); // This request is enabled, because WARN >= INFO. logger.warn("Low fuel level."); // This request is disabled, because DEBUG < INFO. logger.debug("Starting search for nearest gas station."); // The logger instance barlogger, named "com.foo.Bar", // will inherit its level from the logger named // "com.foo" Thus, the following request is enabled // because INFO >= INFO. barlogger.info("Located nearest gas station."); // This request is disabled, because DEBUG < INFO. barlogger.debug("Exiting gas station search"); 调用getLoggerҎ返回一个同名的Logger对象的实例?br /> 例如Q?br /> Categoty x = Logger.getLogger("wombat"); Categoty y = Logger.getLogger("wombat"); x和y参照的是同一个Logger对象?br /> q样我们可以先定义一个LoggerQ然后在代码的其它地方不需传参可以重新得到我们已l定义了的Logger的实? 同基本的生物学理?-父先于子相反QLog4j 的loggers可以以Q何顺序创造和配置。特别是Q一个后实例化的"parent"logger能够扑ֈq且q接它的子logger?br /> 配置Log4j的环境通常在一个应用程序被初始化的时候进行,最好的Ҏ是通过M个配|文件。这个方法我们将短介l?br /> Log4j使得通过软glg命名logger很容易。我们可以通过Logger的静态的初始化方法在每一个类里定义一个loggerQologger的名字等于类名的全局名,而实现logger的命名。这是一个实效的单的定义一个logger的方法。因为日志输出带有生日志的cȝ名字Q这个命名策略得我们更Ҏ定位C个日志信息的来源。虽然普通,但却是命名logger的常用策略之一。Log4j没有限制定义logger的可能。开发员可以自由的按照它们的意愿定义logger的名U?br /> 然而,以类的所在位|来命名Logger好象是目前已知的最好方法?br /> 3.2 输出源(AppendersQ和布局QLayoutsQ?br /> 有选择的能用或者禁用日志请求仅仅是Log4j的一部分功能。Log4j允许日志h被输出到多个输出源。用Log4j的话_一个输出源被称做一个Appender. 。Appender包括consoleQ控制台Q? filesQ文Ӟ, GUI componentsQ图形的lgQ? remote socket serversQsocket 服务Q? JMSQjava信息服务Q? NT Event LoggersQNT的事件日志), and remote UNIX Syslog daemonsQ远EUNIX的后台日志服务)。它也可以做到异步记录?br /> 一个logger可以讄过一个的appender?br /> 用addAppender Ҏd一个appenderC个给定的logger。对于一个给定的logger它每个生效的日志h都被转发到该logger所有的appender上和该logger的父辈logger的appender上。换句话_appender自动从它的父辈获得ѝD例来_如果一个根logger拥有一个console appenderQ那么所有生效的日志h臛_会被输出到console上。如果一个名为C的logger有一个filecd的appenderQ那么它׃对它自己以及所有它的子logger生效。我们也可以通过讄appender的additivity flag 为falseQ来重蝲appender的默认行为,以便l承的属性不在生效?br /> 调节输出源(appenderQ添加性的规则如下?br /> 输出源的可添加性(Appender Additivity Q?br /> 一个名为C的logger的日志定义的输出gl到它自w以及它的ancestor logger的appenders。这是术语"appender additivity"的含义? 然而,logger C的一个ancestor logger PQ它的附加标志被设ؓfalseQ那么C的输出将被定位到所有C的appenderQ以及从它开始上溯到P的所有ancestor logger的appender?br /> Loggers的附加标讎ͼadditivity flagQ默认ؓtrue?br /> 下表是一个例子?br /> Logger Name Added Appenders Additivity Flag Output Targets Comment root A1 not applicable A1 The root logger is anonymous but can be accessed with the Logger.getRootLogger() method. There is no default appender attached to root. x A-x1, A-x2 true A1, A-x1, A-x2 Appenders of "x" and root. x.y none true A1, A-x1, A-x2 Appenders of "x" and root. x.y.z A-xyz1 true A1, A-x1, A-x2, A-xyz1 Appenders in "x.y.z", "x" and root. security A-sec false A-sec No appender accumulation since the additivity flag is set to false. security.access none true A-sec Only appenders of "security" because the additivity flag in "security" is set to false. l常Q用户希望自定义不但输出源,而且定义输出格式。这个是通过在一个appender上附加一个layout来完成的。layout是负责根据用L希望来格式化日志h。而appender是负责发送格式化的输出到它的目的地。PatternLayoutQ作为Log4j标准版中的一部分Q让用户指以cMC语言的printfҎ的格式来指定日志的输出格式?br /> 例如Q{化模式ؓ"%r [%t] %-5p %c - %m%n" 的PatternLayout 输出类似如下的信息Q?br /> 176 [main] INFO org.foo.Bar - Located nearest gas station. W一个栏位是自从E序开始后消逝的毫秒数?br /> W二个栏位是做出日志的线E?br /> W三个栏位是log的别?br /> W四个栏位是日志h相关的logger的名字。?-"后的文字是信息的表述?br /> Log4j根据用户定义的公式来修饰日志信息的内容。例如,如果你经帔R要记录OrangesQ一个在你当前的目被用到的对象cdQ那么你可以注册一个OrangeRenderer Q它在一个orange需要被记录时被调用?br /> 对象渲染cM的类的结构ѝ例如,假设oranges是fruitsQ如果你注册了一个FruitRendererQ所有的水果包括oranges被FruitRenderer所渲染。除非你注册了一个orange?br /> 对象渲染必须实现ObjectRenderer接口?/font>
]]> java中的日志操作Ҏ---Log4J http://m.tkk7.com/19851985lili/articles/91576.html☜♥☞MengChuChen ☜♥☞MengChuChen Wed, 03 Jan 2007 08:46:00 GMT http://m.tkk7.com/19851985lili/articles/91576.html http://m.tkk7.com/19851985lili/comments/91576.html http://m.tkk7.com/19851985lili/articles/91576.html#Feedback 0 http://m.tkk7.com/19851985lili/comments/commentRss/91576.html http://m.tkk7.com/19851985lili/services/trackbacks/91576.html Q?Q监视代码中变量的变化情况,把数据周期性地记录到文件中供其他应用进行统计分析工作?/p>Q?Q跟t代码运行进轨迹Q作为日后审计的依据?/p>
Q?Q担当集成开发环境中的调试器Q向文g或控制台打印代码的调试信息?/p>
Apache能用日志包(Commons Logging PackageQ是Apache的一个开放源代码目Q它提供了一l通用的日志接口,用户可以自由地选择实现日志接口的第三方软g。通用日志包目前支持以下日志实玎ͼ
通用日志包中的两个常用接口:LogFactory和LogQ分别介l如下:
通用日志包把消息分ؓ6个别:FATAL、ERROR、WARN、INFO、DEBUG和TRACE。其中FATALU别最高,TRACEU别最低。Log接口提供输出不同U别消息的方法:
fatal(Object message)-------输出FATALU别的消息?/p>
error(Object message)-------输出ERRORU别的消息?/p>
warn(Object message)-------输出WARNU别的消息?/p>
info(Object message)-------输出INFOU别的消息?/p>
debug(Object message)-------输出DEBUGU别的消息?/p>
trace(Object message)-------输出TRACEU别的消息?/p>
注:只有当输出日志的U别大于或等于ؓ日志配置器配|的日志U别Ӟq个Ҏ才会执行?/p>
如何指定日志器的日志U别Q不同的日志器实C有不同的实现Ҏ?/p>
LogFactory接口提供了获得日志器实例的两个静态方法:
public static Log getLog(String name) throws LogConfigurationException;
public static Log getLog(Class class) throws LogConfigurationException;
注:name参数作ؓ日志器的名字Qclass参数指定cd作ؓ日志器名字?/p>
以下介绍最常用的一?strong>日志实现--------Log4J
Log4j 是Apache的一个开放源代码目Q它是一个日志操作包。通过使用Log4jQ我们可以控制日志信息输送的目的地是控制台、文件、GUIlg、甚x套接口服务器、NT的事件记录器、UNIX Syslog守护q程{;我们也可以控制每一条日志的输出格式Q通过定义每一条日志信息的U别Q我们能够更加细致地控制日志的生成过E。最令h感兴的是Q这些可以通过一个配|文件来灉|地进行配|,而不需要修改应用的代码?br />此外Q通过Log4j其他语言接口Q您可以在C、C++?Net、PL/SQLE序中用Log4jQ其语法和用法与在JavaE序中一P使得多语a分布式系l得C个统一一致的日志lg模块。而且Q通过使用各种W三Ҏ展,您可以很方便地将Log4j集成到J2EE、JINI甚至是SNMP应用中?/p>
Log4J主要׃大组件构成:
LoggerQ负责生成日志,q能Ҏ配置的日志别来军_什么日志消息应该被输出Q什么日志消息应该被忽略?
AppenderQ定义日志消息输出的目的圎ͼ指定日志消息应该被输出到什么地方,q些地方可以是控制台、文件和|络讑֤{?
LayoutQ指定日志消息的输出格式?/li> q三个组件协同工作,使得开发者能够依据日志消息类别来输出日志Qƈ能够在程序运行期_控制日志消息的输出格式以及日志存攑֜炏V?/p>
Log4J的配|?/strong>
配置Log4JQ需要分别配|它的Logger、Appender和Layout属性。配|文件一般ؓlog4j.properties。当然也可以以XML文g来配|,q里介绍以属性文仉|?/font>
Loggerlg支持l承关系Q所有的Loggerlg都直接或间接l承rootLogger。配|rootLogger的语法ؓQ?/p>
log4j.rootLogger=[priority]QappenderNameQappenderNameQ?.....
priority是如前所q的日志U别Q?/p>
appenderName指定AppenderlgQ用户可以同时指定多个AppenderlgQ以与逗号分隔?/p>
配置日志消息输出目的地AppenderQ语法ؓQ?/p>
log4j.appender.appenderName=<appender的完整类?gt;
log4j.appender.appenderName.option1=value1
log4j.appender.appenderName.option2=value2
...
Log4J共有以下几种Appender:
org.apache.log4j.ConsoleAppender(控制?
org.apache.log4j.FileAppender(文g)
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文?
org.apache.log4j.RollingFileAppender(文g大小到达指定寸的时候生一个新的文?
org.apache.log4j.WriterAppender(日志消息以格式发送到L指定的地?
语法Q?/p>
log4j.appender.appenderName.layout=<layout的完整类?gt;
log4j.appender.appenderName.layout.option1=value1
log4j.appender.appenderName.layout.option2=value2
...
Log4J提供以下几种LayoutQ?/p>
org.apache.log4j.HTMLLayout(以HTML表格形式布局)
org.apache.log4j.PatternLayout(可以灉|地指定布局模式)
org.apache.log4j.SimpleLayout(包含日志消息的别和信息字符?
org.apache.log4j.TTCCLayout(包含日志产生的时间、线E和cd{信?
通过讄PatternLayout的ConversionPattern属性来指定输出格式
ConversionPattern 的格式如下表所C:
格式? 含义 %c 输出日志信息所属的cȝ全名 %d 输出日志旉点的日期或时_默认格式为ISO8601Q也可以在其后指定格式,比如Q?/font>
%d{yyy-MM-dd HH:mm:ss }Q输出类|2002-10-18- 22Q?0Q?8 %f 输出日志信息所属的cȝcd %l 输出日志事g的发生位|,卌出日志信息的语句处于它所在的cȝW几?br />%m 输出代码中指定的信息Q如log(message)中的message %n 输出一个回车换行符QWindowsq_为“\r\n”,Unixq_为“\n?br />%p 输出优先U,即DEBUGQINFOQWARNQERRORQFATAL。如果是调用debug()输出的,则ؓDEBUGQ依此类?br />%r 输出自应用启动到输出该日志信息所耗费的毫U数 %t 输出产生该日志事件的U程?/font>
CZQlog4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%t %p- %m%n
Log4J对应用性能的媄?/font>
如果在程序运行中输出大量日志Q显然会对应用的性能造成一定的影响。Log4JҎ能的媄响取决于以下因素Q?/font>
日志输出目的圎ͼ输出到控制台的速度和输出到文gpȝ的速度是不一L?/font> 日志输出格式Q格式简单,速度也更快?/font> 日志U别Q日志别设|的低Q输出的日志内容多Q对性能的媄响也大?/font> ]]> 使用Log4jq行日志操作l?/title> http://m.tkk7.com/19851985lili/articles/91572.html☜♥☞MengChuChen ☜♥☞MengChuChen Wed, 03 Jan 2007 08:38:00 GMT http://m.tkk7.com/19851985lili/articles/91572.html http://m.tkk7.com/19851985lili/comments/91572.html http://m.tkk7.com/19851985lili/articles/91572.html#Feedback 0 http://m.tkk7.com/19851985lili/comments/commentRss/91572.html http://m.tkk7.com/19851985lili/services/trackbacks/91572.html
2.2.2. 服务器程?/b>
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 ;
/**
*
* <p> Server With Log4j </p>
* <p> Description: a sample with log4j</p>
* @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 ) ;
}
}
}
}
2.2.3. 配置文g
2.2.3.1. 客户E序配置文g
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
2.2.3.2. 服务器程序配|文?/p>
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
2.3. 比较
比较q两个应用可以看出,采用Log4jq行日志操作的整个过E相当简单明了,与直接用System.out.println语句q行日志信息输出的方式相比,基本上没有增加代码量Q同时能够清楚地理解每一条日志信息的重要E度。通过控制配置文gQ我们还可以灉|CҎ志信息的格式Q输出目的地{等斚wQ而单U依靠System.out.println语句Q显焉要做更多的工作?/p>
下面我们以前面使用Log4j的应用作Z子,详细讲解使用Log4j的主要步骤?/p>
Log4j基本使用Ҏ
Log4j׃个重要的lg构成Q日志信息的优先U,日志信息的输出目的地Q日志信息的输出格式。日志信息的优先U从高到低有ERROR、WARN、INFO、DEBUGQ分别用来指定这条日志信息的重要E度Q日志信息的输出目的地指定了日志打印到控制台还是文件中Q而输出格式则控制了日志信息的昄内容?/p>
3.1.定义配置文g
其实您也可以完全不用配|文Ӟ而是在代码中配置Log4j环境。但是,使用配置文g您的应用E序更加灉|?/p>
Log4j支持两种配置文g格式Q一U是XML格式的文Ӟ一U是JavaҎ文Ӟ?|。下面我们介l用JavaҎ文件做为配|文件的ҎQ?/p>
配置根LoggerQ其语法为:
log4j.rootLogger = [ level ] , appenderName, appenderName, ?/p>其中Qlevel 是日志记录的优先U,分ؓOFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的别。Log4j只用四个别,优先U从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的U别Q您可以控制到应用程序中相应U别的日志信息的开兟뀂比如在q里定义了INFOU别Q则应用E序中所有DEBUGU别的日志信息将不被打印出来? appenderName是指定日志信息输出到哪个地斏V您可以同时指定多个输出目的地?
配置日志信息输出目的地AppenderQ其语法?log4j.appender.appenderName = fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1 = value1
?
log4j.appender.appenderName.option = valueN 其中QLog4j提供的appender有以下几U: org.apache.log4j.ConsoleAppenderQ控制台Q, org.apache.log4j.FileAppenderQ文ӞQ? org.apache.log4j.DailyRollingFileAppenderQ每天生一个日志文ӞQorg.apache.log4j.RollingFileAppenderQ文件大到达指定尺寸的时候生一个新的文ӞQ? org.apache.log4j.WriterAppenderQ将日志信息以流格式发送到L指定的地方)
配置日志信息的格式(布局Q,其语法ؓQ?log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1 = value1
?
log4j.appender.appenderName.layout.option = valueN 其中QLog4j提供的layout有以下几U: org.apache.log4j.HTMLLayoutQ以HTML表格形式布局Q, org.apache.log4j.PatternLayoutQ可以灵zd指定布局模式Q, org.apache.log4j.SimpleLayoutQ包含日志信息的U别和信息字W串Q, org.apache.log4j.TTCCLayoutQ包含日志生的旉、线E、类别等{信息)
3.2.在代码中使用Log4j
下面讲q在E序代码中怎样使用Log4j?/p>
3.2.1.得到记录?/b>
使用Log4jQ第一步就是获取日志记录器Q这个记录器负责控制日志信息。其语法为:
public static Logger getLogger( String name)Q?/p>
通过指定的名字获得记录器Q如果必要的话,则ؓq个名字创徏一个新的记录器。Name一般取本类的名字,比如Q?/p>
static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () ) ;
3.2.2.d配置文g
当获得了日志记录器之后,W二步将配置Log4j环境Q其语法为: BasicConfigurator.configure ()Q?自动快速地使用~省Log4j环境? PropertyConfigurator.configure ( String configFilename) Q读取用Java的特性文件编写的配置文g? DOMConfigurator.configure ( String filename ) Q读取XML形式的配|文件?
3.2.3.插入记录信息Q格式化日志信息Q?/b>
当上两个必要步骤执行完毕Q您可以轻村֜使用不同优先U别的日志记录语句插入到您想记录日志的Q何地方,其语法如下:
Logger.debug ( Object message ) ; Logger.info ( Object message ) ; Logger.warn ( Object message ) ; Logger.error ( Object message ) ;
]]> 使用Log4jq行日志操作1 http://m.tkk7.com/19851985lili/articles/91571.html☜♥☞MengChuChen ☜♥☞MengChuChen Wed, 03 Jan 2007 08:36:00 GMT http://m.tkk7.com/19851985lili/articles/91571.html http://m.tkk7.com/19851985lili/comments/91571.html http://m.tkk7.com/19851985lili/articles/91571.html#Feedback 0 http://m.tkk7.com/19851985lili/comments/commentRss/91571.html http://m.tkk7.com/19851985lili/services/trackbacks/91571.html
概述
1.1. 背景
在应用程序中d日志记录ȝ来说Z三个目的Q监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工作;跟踪代码q行时轨q,作ؓ日后审计的依据;担当集成开发环境中的调试器的作用,向文件或控制台打C码的调试信息?/p>
最普通的做法是在代码中嵌入许多的打印语句,q些打印语句可以输出到控制台或文件中Q比较好的做法就是构造一个日志操作类来封装此cL作,而不是让一pd的打印语句充斥了代码的主体?/p>
1.2. Log4j?/strong>
在强调可重用lg开发的今天Q除了自׃头到ּ发一个可重用的日志操作类外,Apache为我们提供了一个强有力的日志操作包-Log4j?/p>
Log4j是Apache的一个开放源代码目Q通过使用Log4jQ我们可以控制日志信息输送的目的地是控制台、文件、GUIlg、甚x套接口服务器、NT的事件记录器、UNIX Syslog守护q程{;我们也可以控制每一条日志的输出格式Q通过定义每一条日志信息的U别Q我们能够更加细致地控制日志的生成过E。最令h感兴的是Q这些可以通过一个配|文件来灉|地进行配|,而不需要修改应用的代码?/p>
此外Q通过Log4j其他语言接口Q您可以在C、C++?Net、PL/SQLE序中用Log4jQ其语法和用法与在JavaE序中一P使得多语a分布式系l得C个统一一致的日志lg模块。而且Q通过使用各种W三Ҏ展,您可以很方便地将Log4j集成到J2EE、JINI甚至是SNMP应用中?/p>
本文介绍的Log4j版本?.2.3。作者试N过一个简单的客户/服务器JavaE序例子Ҏ使用与不使用Log4j 1.2.3的差别,q详l讲解了在实践中最怋用Log4j的方法和步骤。在可重用组件开发的今天Q相信Log4j会l广大的设计开发h员带来方ѝ加入到Log4j的队伍来吧!
一个简单的例子
我们先来看一个简单的例子Q它是一个用Java实现的客?服务器网l程序。刚开始我们不使用Log4jQ而是使用了一pd的打印语句,然后我们用Log4j来实现它的日志功能。这P大家可以清楚地比较出前后两个代码的差别?/p>
2.1. 不用Log4j
2.1.1. 客户E序
package log4j ;
import java.io.* ;
import java.net.* ;
/**
*
* <p> Client Without Log4j </p>
* <p> Description: a sample with log4j</p>
* @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 ) {}
}
}
2.1.2. 服务器程?/b>
package log4j ;
import java.util.* ;
import java.io.* ;
import java.net.* ;
/**
*
* <p> Server Without Log4j </p>
* <p> Description: a sample with log4j</p>
* @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 ) ;
}
}
}
}
2.2. q移到Log4j
2.2.1. 客户E序
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 ;
/**
*
* <p> Client With Log4j </p>
* <p> Description: a sample with log4j</p>
* @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 ) {}
}
}
]]> Java调试的变q:从System.out.println到log4j http://m.tkk7.com/19851985lili/articles/log4j.html☜♥☞MengChuChen ☜♥☞MengChuChen Wed, 03 Jan 2007 07:58:00 GMT http://m.tkk7.com/19851985lili/articles/log4j.html http://m.tkk7.com/19851985lili/comments/91557.html http://m.tkk7.com/19851985lili/articles/log4j.html#Feedback 0 http://m.tkk7.com/19851985lili/comments/commentRss/91557.html http://m.tkk7.com/19851985lili/services/trackbacks/91557.html
jungleford如是?
用惯?a target="_blank">VC 的h刚接?a target="_blank">Java 大概很不习惯代码的调试,的确Q在M$ 的大部分IDE都做得相当出Ԍ包括像VJ++q样一直被JavaE序员称为是“垃䏀的cdQ记得以前在瀚v星云 ?a target="_blank">Java?/font>提有关VJ问题的h是有可能被封的,^_^Q,它的开发工具在调试上都相当Ҏ。Java也有命o行方式的调试和IDE的调试,但现在的?a target="_blank">JB q样的玩意又是个庞然大物Q低配置的机器可能就是个奢望Q不像VC那样。怎么办呢Q高手们_“我的jdb用得贼熟l”,那我会报以景仰的目光Q像我这L菜鸟基本上就没ɘqjdbQ还是老老实实在代码里面System.out.println(...)。直?996q一个叫做“欧z安全电子市场”(E.U. SEMPER Q的目启动Q“调试”不再是一件“体力活”,而是一UY件设计的艺术Q这个项目组开发的日志理接口后来成ؓApache Jakarta 目中的一员,它就是现在我们所熟悉?a target="_blank">log4j 。下面的文字概要介l与Java日志记录相关的一些技术,目的不是让您攑ּ老土的System.out.println(...)Q而是_在Java的世界里可以有许多种选择Q你今天觉得掌握了一仉U武器,明天可能是“过时”的了,呵呵?
始祖QSystem.out.println(...) Z么还是要一再提到它Q毕竟我们的习惯不是那么Ҏ改变的,而且System .out Q别忘了q有System.err Q是一个直接和控制台打交道?a target="_blank">PrintStream 对象Q是l端昄的基Q高U的Logger要在l端昄日志内容Q就必然会用到这个。一个小规模的程序调试,恰当C用System.out.println (...)我认Z然是一U最方便最有效的方法,所以我们仍把它攑֜最开始,以示不能“数典忘?:)
不常用的关键字:assert assert对多Ch来讲可能q比较陌生,它也是一个调试工P好像?a target="_blank">J2SE 1.4 才加q来的东东,一U常见的用法是:
assert (布尔表达?;
当表辑ּ为true时没有Q何反映,如果为falsepȝ会抛出一?a target="_blank">AssertionError 。如果你要用assertQ在~译时必d上?strong>-source 1.4”的选项Q在q行时则要加上?strong>-ea”选项?br />
后生可畏QJava Logging API一?/font> System.out.println(...)对于较高要求的用hq远不够的,它还不是一个日志系l,一个比较完善的日志pȝ应当有输出媒介、优先、格式化、日志过滤、日志管理、参数配|等功能。伴随J2SE 1.4一起发布的Java日志?a target="_blank">java.util.logging 适时地满了我们的初步需求,在程序中按一定格式显C和记录丰富的调试信息已l是一件相当easy的事情?/p>
1. 日志记录器:Logger Logger 是一个直接面向用L日志功能调用接口Q从用户的角度上看,它完成大部分日志记录工作Q通常你得C个Logger对象Q只需要用一些简单方法,譬如infoQwarningQlogQlogpQlogrb{就能完成Q务,单到和System.out.println(...)一样只用一条语句,但后台可能在向控制台Q向文gQ向数据库,甚至向网l同时输信息Q而这个过E对用户是完全透明的?br /> 在用Logger之前Q首先需要通过getLogger ()?a target="_blank">getAnonymousLogger ()静态方法得C个Logger对象Q想想看Q这里是不是设计模式当中的“工厂方法”的一个实实在在的应用Q可以参考一下Logger的源代码Q你明?a target="_blank">LogManager 是“工厂类”而Logger是“品类”,凡事都要学以致用嘛,呵呵Q。这里我们需要了解的是Logger的“名字空间”(namespace Q的概念Q通常我们调试旉要清楚地知道某个变量是出现在什么位|,_到哪个类的哪个方法,namespace是q么个用处。我们用getLogger()得到Logger旉要指定这个Logger的名字空_通常是一个包名,譬如“com.jungleford.test”等Q如果是指定了namespaceQ那么将在一个全局对象LogManager中注册这个namespaceQLogger会基于namespace形成层次关系Q譬如namespace为“com.jungleford”的Logger是namespace为“com.jungleford.test”的Logger的父Q后者调?a target="_blank">getParent ()Ҏ返回前者,如果当前没有namespace为“com.jungleford”的LoggerQ则查找namespace为“com”的LoggerQ要是按照这个链找不到就q回根LoggerQ其namespace?"Q根Logger的父是null。从理论上说Q这个namespace可以是Q意的Q通常我们是按所调试的对象来定,但如果你是用getAnonymousLogger()Ҏ产生的LoggerQ那它就没有namespaceQ这个“匿名Logger”的父是根Logger?br /> 得到一个Logger对象后就可以记录日志了,下面是一些常用的ҎQ?
finest ?a target="_blank">finer ?a target="_blank">fine ?a target="_blank">info ?a target="_blank">config ?a target="_blank">warning ?a target="_blank">severe Q简z的ҎQ输出的日志为指定的U别。关于日志别我们在后面会详细谈到?br />log Q不仅可以指定消息和U别Q还可以带一些参敎ͼ甚至可以直接是一个LogRecord对象Q这些参数是LogRecord对象的重要组成部分)?br />logp Q更加精l了Q不但具有logҎ的功能,q可以不使用当前的namespaceQ定义新的类名和Ҏ名?br />entering ?a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/logging/Logger.html#exiting(java.lang.String, java.lang.String)" target="_blank">exiting Q这两个Ҏ在调试的时候特别管用,用来观察一个变量变化的情况Q就如同我们在VC的调试状态下watch一个变量,然后按F10Q呵c?/font>
2. 输出媒介控制QHandler 日志的意义在于它可以以多UŞ式输出,其是像文gq样可以长久保存的媒介,q是System.out.println(...)所无法办到的。Logging API?a target="_blank">Handler cL供了一个处理日志记录(LogRecord Q它是对一条日志消息的装对象Q的接口Q包括几个已实现的APIQ?/p>
ConsoleHandler Q向控制台输出?br />FileHandler Q向文g输出?br />SocketHandler Q向|络输出?/font>
q三个输出控制器都是StreamHandler 的子c,另外Handlerq有一个MemoryHandler的子c,它有Ҏ的用处,我们在后面将会看到。在E序启动旉认的Handler是ConsoleHandlerQ不q这个是可以配置的,下面会谈到logging配置文g的问题?br /> 此外用户q可以定制自p出控制器Q承Handler卛_Q通常只需要实现Handler中三个未定义的抽象方法:
publish Q主要方法,把日志记录写入你需要的媒介?br />flush Q清除缓冲区q保存数据?br />close Q关闭控制器?/font>
publish Q主要方法,把日志记录写入你需要的媒介?br />flush Q清除缓冲区q保存数据?br />close Q关闭控制器?/font> 通过重写以上三个Ҏ我们可以很容易就实现一个把日志写入数据库的控制器?br />
3. 自定义输出格式:Formatter 除了可以指定输出媒介之外Q我们可能还希望有多U输出格式,譬如可以是普通文本、HTML表格、XML{等Q以满不同的查看需求。Logging API中的Formatter 是q样一个提供日志记录格式化Ҏ接口的类。默认提供了两种FormatterQ?br />SimpleFormatter Q标准日志格式,是我们通常在启动一些诸?a target="_blank">Tomcat ?a target="_blank">JBoss 之类的服务器的时候经常能在控制台下看到的那种形式Q就像这P
2004-12-20 23:08:52 org.apache.coyote.http11.Http11Protocol init 信息: Initializing Coyote HTTP/1.1 on http-8080 2004-12-20 23:08:56 org.apache.coyote.http11.Http11Protocol init 信息: Initializing Coyote HTTP/1.1 on http-8443
XMLFormatter QXML形式的日志格式,你的Logger如果add了一个new XMLFormatter()Q那么在控制C׃看到下面q样的Ş式,不过更常用的是用上面介l的FileHandler输出到XML文g中:
<?xml version="1.0" encoding="GBK" standalone="no"?> <!DOCTYPE log SYSTEM "logger.dtd"> <log> <record> <date>2004-12-20T23:47:56</date> <millis>1103557676224</millis> <sequence>0</sequence> <logger>Test</logger> <level>WARNING</level> <class>Test</class> <method>main</method> <thread>10</thread> <message>warning message</message> </record>
<?xml version="1.0" encoding="GBK" standalone="no"?> <!DOCTYPE log SYSTEM "logger.dtd"> <log> <record> <date>2004-12-20T23:47:56</date> <millis>1103557676224</millis> <sequence>0</sequence> <logger>Test</logger> <level>WARNING</level> <class>Test</class> <method>main</method> <thread>10</thread> <message>warning message</message> </record> 与HandlercMQ我们也可以~写自己的格式化处理器,譬如API里没有将日志输出为我们可通过览器查看的HTML表格形式的FormatterQ我们只需要重?个方法:
format Q格式化LogRecord中包含的信息?br />getHead Q输Z息的头部?br />getTail Q输Z息的N?/font>
format Q格式化LogRecord中包含的信息?br />getHead Q输Z息的头部?br />getTail Q输Z息的N?/font>4. 定义日志U别QLevel 大家可能都知道Windows的“事件查看器”,里面有三U事件类型:“信息”、“警告”、“错误”。这其实是日志U别的一U描q。Java日志U别?a target="_blank">Level c表C,一个日志别对应的是一个整数|范围和整型值的范围是一致的Q该整数值愈大,说明警戒U别愈高。Level?个内|的U别Q分别是Q?
cd 对应的整?/strong> OFF 最大整敎ͼInteger .MAX_VALUE Q?br /> SEVERE 1000 WARNING 900 INFO 800 CONFIG 700 FINE 500 FINER 400 FINEST 300 ALL 最整敎ͼInteger.MIN_VALUE Q?/font>
你也可以定义自己的日志别,但要注意的是Q不是直接创建Level的对象(因ؓ它的构造函数是protected的)Q而是通过l承Level的方式,譬如Q?
class AlertLevel extends java.util.logging.Level { public AlertLevel() { super("ALERT" , 950 ); } } ...Logger logger = Logger .getAnonymousLogger(); logger.log(new AlertLevel(), "A dangerous action!" );
class AlertLevel extends java.util.logging.Level { public AlertLevel() { super("ALERT" , 950 ); } } ...Logger logger = Logger .getAnonymousLogger(); logger.log(new AlertLevel(), "A dangerous action!" ); 上面定义了一个高于WARNING但低于SEVERE的日志别?br /> 于是可能有朋友会兴冲冲地用以下的语句来记录一个事Ӟ
Logger logger = Logger .getAnonymousLogger(); logger.fine("Everything seems ok." );//或者是 //logger.log(Level.FINE, "Everything seems ok.");
Logger logger = Logger .getAnonymousLogger(); logger.fine("Everything seems ok." );//或者是 //logger.log(Level.FINE, "Everything seems ok."); 但是一E序q行Q奇怪了Q怎么没有打印ZQ何消息呢Q下一节我们来谈这个问题?/font>
5. 日志qo器:Filter 所谓过滤器是控制哪些日志该输出哪些不该输出的一U组件。上面你写的那条日志没有能在控制台显C出来,是因为logging API预先讑֮的缺省别是INFOQ也是说只有别不低于INFOQ即其整数g于800Q的日志才会被输出,q个是Filter的功能。所以我们可以看到SEVERE、WARNING、INFO以及上面我们定义的ALERT消息Q但看不到FINE、FINER和FINEST消息。当Ӟ你尽可以用Logger?a target="_blank">setLevel Ҏ或者修攚w|文件的ҎQ什么是配置文gQ我们后面将会看刎ͼ来重新定义Logger输出的最低别?br /> Filter 不仅仅可以按日志U别qoQ你也可以定义自qFilterQ实现其中的isLoggable ҎQ随便按照LogRecord携带的Q何信息进行过滤,譬如Q顺便复习一下匿名类Q呵呵)Q?
Logger logger = Logger .getAnonymousLogger(); logger.setFilter(new Filter () { public boolean isLoggable(LogRecord rec) { //从LogRecord里得到过滤信?br /> } });
6. 预定义参?br /> LogManager是一个实CSingleton模式的全局对象Q由于是一个唯一的对象,LogManager需要是U程安全的)Q它理着E序启动以后所有已注册Q包层次Q或匿名的LoggerQ以及相关配|信息。这里的配置信息通常是从<JAVA_HOME>\jre\lib\logging.properties 文g得到的。logging.properties对于logging API来说是一个很重要的文Ӟ它的内容一般是Q?br />
############################################################ # Default Logging Configuration File # # You can use a different file by specifying a filename # with the java.util.logging.config.file system property. # For example java -Djava.util.logging.config.file=myfile ############################################################
############################################################ # Global properties ############################################################
# "handlers" specifies a comma separated list of log Handler # classes. These handlers will be installed during VM startup. # Note that these classes must be on the system classpath. # By default we only configure a ConsoleHandler, which will only # show messages at the INFO and above levels. handlers= java.util.logging.ConsoleHandler
# To also add the FileHandler, use the following line instead. #handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
# Default global logging level. # This specifies which kinds of events are logged across # all loggers. For any given facility this global level # can be overriden by a facility specific level # Note that the ConsoleHandler also has a separate level # setting to limit messages printed to the console. .level= INFO
############################################################ # Handler specific properties. # Describes specific configuration info for Handlers. ############################################################
# default file output is in user's home directory. java.util.logging.FileHandler.pattern = %h/java%u.log java.util.logging.FileHandler.limit = 50000 java.util.logging.FileHandler.count = 1 java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
# Limit the message that are printed on the console to INFO and above. java.util.logging.ConsoleHandler.level = INFO java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
############################################################ # Facility specific properties. # Provides extra control for each logger. ############################################################
# For example, set the com.xyz.foo logger to only log SEVERE # messages: com.xyz.foo.level = SEVERE
你可以通过修改q个配置文g来改变运行时Logger的行为,譬如Q?level定义的是上面所说的默认输出的最低日志别;XXXHandler相关属性定义了各种输出媒介{等?br /> q里比较有意思的是关于日志文Ӟ也就是FileHandlerQ当Ӟ你可以在E序中创Z个FileHandlerQ然后添加到logger中:
FileHandler fhd = new FileHandler ("%h/java%u.log" , 5000 , 1 , true ); fhd.setLevel(Level .ALL); fhd.setFormatter(new XMLFormatter ()); logger.addHandler(fhd);
FileHandler fhd = new FileHandler ("%h/java%u.log" , 5000 , 1 , true ); fhd.setLevel(Level .ALL); fhd.setFormatter(new XMLFormatter ()); logger.addHandler(fhd); q段代码{h于上面logging.properties中的文字D:
java.util.logging.FileHandler.pattern = %h/java%u.log java.util.logging.FileHandler.limit = 50000 java.util.logging.FileHandler.count = 1 java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
java.util.logging.FileHandler.pattern = %h/java%u.log java.util.logging.FileHandler.limit = 50000 java.util.logging.FileHandler.count = 1 java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter q里的pattern代表用{义字W定义的一个日志文件名Q?转义字符?/font>含义 %t 临时目录 %h 用户目录Q即pȝ属性“user.home”对应的?/font>%g 一个随机生成的数字Q可以重?/font>%u 一个随机生成的非重复数?/font> 以上面的?h/java%u.log”ؓ例,在Windows 2000下代表日志文件可能就是:C:\Documents and Settings\Administrator\javax .log。这里x代表一个不重复的数字,如果是第一ơ,那么是java0.logQ如果在该目录下已经存在了一个java0.log的文Ӟ那么logger׃生一个java1.log的新的日志文件?br /> 当然Q你可以在别的地方用自己写的配|文Ӟ不过在启动程序时候需要指?strong>java.logging.config.file属性:
转义字符?/font>含义 %t 临时目录 %h 用户目录Q即pȝ属性“user.home”对应的?/font>%g 一个随机生成的数字Q可以重?/font>%u 一个随机生成的非重复数?/font> 以上面的?h/java%u.log”ؓ例,在Windows 2000下代表日志文件可能就是:C:\Documents and Settings\Administrator\javax .log。这里x代表一个不重复的数字,如果是第一ơ,那么是java0.logQ如果在该目录下已经存在了一个java0.log的文Ӟ那么logger׃生一个java1.log的新的日志文件?br /> 当然Q你可以在别的地方用自己写的配|文Ӟ不过在启动程序时候需要指?strong>java.logging.config.file属性:
java -Djava.logging.config.file=...
7. 资源与本地化 Logger里还有个Ҏ?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">logrb Q可能初学者不太会用到。如果你安装的JDK是国际版的,那么你将会看到在中文Windowsq_下日志输出的INFO、WARNING昄的是“信息”、“警告”等中文字样。因为logrb是一个和Java i18n/l10n相关的方法,你可以定义自q“资源包”(Resource BundleQ,然后在logrbҎ中指定相应的资源名称Q那么在输出日志中你p看到用自己定义的本地语言、时间等昄的信息。如果你对i18n/l10n感兴,可以参?a target="_blank">Java Localization文 ?br /> 了解以上lg后,我们回顾一个完整的日志处理的工作过E: E序启动日志服务Q创建Logger对象QLogManager按照namespace的层ơ结构组lLoggerQ在同一个namespace里子Logger承父Logger的属性;同时QLogManager从logging.properties中读取相应的属性对Loggerq行初始化,如果在程序中讄了属性则使用新的配置。当应用E序产生一条日志,Logger创Z个LogRecord对象Q该对象装了一条日志的全部信息。Logger需要根据当前设|的Filter来判断这条日志是否需要输出,q将有用的日志传l相应的Handler处理Q而HandlerҎ当前讄的Formatter和Resource Bundle日志消息{换成一定的昄格式Q然后输出到预定的媒介(控制台、文件等Q中厅R整个过E大致如?所C:
? 前面我们在介lHandler的时候提到过一个特D的cdMemoryHandler Q这里我们要了解一下“Handler䏀的概念Q日志在输出之前可能l过多个Handler的处理,MemoryHandler在这U情况下是一个中间角Ԍ它维持一个内存中的日志缓冲区Q当日志没有填满~冲区时将全部日志送到下一个HandlerQ否则新q来的日志将会覆盖最老的那些日志Q因此,使用MemoryHandler可以l护一定容量的日志Q另外,MemoryHandler也可以不需要用Formatter来进行格式化Q从而具有较高的效率。一个用Handler铄例子如图2所C:
?
青出于蓝QApache Jakarta log4j日志工具?/font> 应付日常的日志需求,J2SE的Logging API可以说已l做得相当出色了Q但q求完美的开发h员可能需要可扩展性更好的专业日志处理工具Qlog4j正是当前比较行的一个工具包Q它提供更多的输出媒介、输出格式和配置选择Q你会发现原来在J2SE里一些仍需要自己手工构建的功能在log4j当中都已lؓ你实C。关于log4j我可能谈得不会太多,可以看看文后所附的?a href="http:///#ref">参考资?/font>”,|上也有很详l的介绍Q我在这里做的是一个对比,因ؓlog4j和J2SE 1.4 Logging API的用法是很相似的Q一些名UC同的lg你会发现他们所处的C其实是一LQ? J2SE 1.4中的c?/strong> log4j中的c?/strong> 日志记录?/font> Logger Logger 日志理?/strong> LogManager LogManager 日志对象 LogRecord LoggingEvent 输出媒介控制 Handler Appender 格式?/strong> Formatter Layout U别 Level Level qo?/strong> Filter Filter log4j可以做到更精l更完善的控Ӟ譬如J2SE里没有现成向数据库里写日志的ҎQ但log4j却有JDBCAppender Q它甚至q能向GUI囑Ş界面Q?a target="_blank">LF5Appender Q一U以JTree方式昄的层ơ结构)、Windows NT事g查看器(NTEventLogAppender Q、UNIX的syslogd服务Q?a target="_blank">SyslogAppender Q、电子邮(SMTPAppender Q、Telnetl端Q?a target="_blank">TelnetAppender Q、JMS消息Q?a target="_blank">JMSAppender Q输出日志,牛吧QJ2SE里默认只能用%JAVA_HOME%\jre\lib\logging.properties做配|文Ӟ但log4j却可以在代码中设|其它\径下的properties文g或XML格式的配|文件。log4j的其它方面同样很丰富QMQlog4j的最大的特点是“灵zZ,无论是Appender、Layoutq是ConfiguratorQ你可以把日志轻村֜弄成几乎M你想要的形式?/font>
框架与标准:JSR议案 从时间顺序上Ԍlog4j要比J2SE Logging API来得早,很多概念都是log4j先有的,但成Z个标准,则是?a target="_blank">JSR 47 的Ş成。可能有不太了解JSR Q这q要谈到JCP Q即“Java Community Process”,它是一个于1998q成立的旨在为Java技术制定民间标准的开攄l,你可以通过http://www.jcp.org/en/participation/membership 甌成ؓ它的付费或免费会员,JCP的主要工作就是制定和发布JSRQJava Specification RequestsQ,JSR对于Java的意义就相当于RFC对于|络技术的意义Q由于JCP会员们的集思广益,使得JSR成ؓJava界的一个重要标准。JSR 47即“Logging API Specification”,制定了调试和日志框架QJ2SE Logging API正是该框架的一个实现。由于种U原因,在JSR 47出来以前Qlog4j已l成ZҎ熟的技术,使得log4j在选择上占据了一定的优势Q但不能因此pJSR 47是过时的规范Q标准L在发展的嘛!
q不是全部:其它日志处理工具 除了J2SE Logging API和log4jQ日志处理方面还有别的技术:Jakarta?a target="_blank">commons lg目中的JCL QJakarta Commons LoggingQ是一个不错的选择Q它有点cM于GSS-APIQ通用安全服务接口Q中的思想Q其日志服务机制是可以替换的Q也是说既可以用J2SE Logging API也可以用log4jQ但JCL对开发h员提供一致的接口Q这一点相当重要,lg可重用正是Jakarta Commons目q求的一个目标;IBM ?a target="_blank">JLog 也是在J2SE Logging API之前推出的一个工具包Q但JLog是一个商业品?br /> 至于日志API的应用那可就多了Q现在哪个大一点的工具或^C用到日志模块呢?Tomcat、JBoss…?br />
说了q么多,我们无非需要知道的一件事是Q“调试”也是一门学问。在我们一个劲地用System.out.println(...)而且用得很爽的时候,也应该想想看Q如何让q样一条菜鸟语句也能变得h性化和丰富多彩?/p>
参考资?/font>
]]>
վ֩ģ壺
ާѡþþþƷ9966 |
ɫ |
aëƬѹۿƵ |
һ24˾ |
þþƷaһվ |
ëƬһƵѲ
|
һëƬѹۿշ |
þaƬ |
Ʒ鶹վ |
һƬɫ |
avһ߲ |
պ |
ŮvƬ |
һ |
avһ
|
ӰԺһҳ |
AV˳ۺ |
ִӲˬִֿƵ |
ɫëƬƵ |
Ʒþ˰ |
ҹƷҹ³˿Ƭ |
ٸ̫߳ˬ߹ۿ |
ձһҹ |
ҹӰ |
av벻þ |
av乾 |
߲ |
ŮˬˬˬˬˬƵ |
2019Ļ |
Ʒþþþ |
һ234 |
AVվþþƷ
|
99reƵѹۿ |
һ**ƬƵ |
˳ɫ99999߹ۿ |
Ƶ߹ۿ |
ۺһʵ |
AV˾Ʒպһ18p |
һһëƬa |
߿Ƭ˳Ƶ |
Ƶ߹ۿ |