java log4j日志详解
log4j文件切分规则

log4j文件切分规则一、引言log4j是一个Java日志框架,方便开发者记录应用程序的运行日志并进行管理。
在使用log4j时,我们可以通过配置文件来定义日志的输出方式和切分规则。
本文将重点讨论log4j文件切分规则。
二、按文件大小切分在日志文件的切分规则中,按文件大小切分是最常见的一种方式。
通过配置log4j,我们可以设置一个文件的最大大小,当该文件达到最大大小时,log4j会自动将其备份,并创建一个新的日志文件来记录日志。
这种方式可以确保每个日志文件不会过大,方便查阅和管理。
三、按日期切分除了按文件大小切分,log4j还支持按日期切分日志文件。
通过设置切分的时间间隔,log4j会在指定的时间点自动将当前日志文件备份,并创建一个新的日志文件来记录后续的日志信息。
这种方式可以按照日期来管理日志文件,方便按照时间段进行查阅。
四、按文件数量切分除了按文件大小和日期切分,log4j还支持按文件数量切分日志文件。
通过设置切分的文件数量,当日志文件数量达到指定值时,log4j会自动将最早的日志文件备份,并创建一个新的日志文件来记录新的日志信息。
这种方式可以保持日志文件数量的稳定,避免文件过多导致管理困难。
五、动态切分规则在log4j中,我们可以通过配置动态切分规则来灵活地管理日志文件。
例如,我们可以根据业务需求,定义不同的切分规则,如按照不同的模块或日志级别进行切分。
这样可以根据具体的需求来管理日志文件,使日志信息更加有意义和可读性。
六、配置示例下面是一个示例的log4j配置文件,展示了如何设置文件切分规则:```log4j.rootLogger=INFO, filelog4j.appender.file=org.apache.log4j.RollingFileAppenderlog4j.appender.file.File=/path/to/log/file.loglog4j.appender.file.MaxFileSize=10MBlog4j.appender.file.MaxBackupIndex=10yout=org.apache.log4j.PatternLayoutyout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n```在上述配置中,我们定义了一个名为file的appender,它是一个RollingFileAppender。
log4j日志脱敏处理+javaproperties文件加载

log4j⽇志脱敏处理+javaproperties⽂件加载Java 加载Properties 配置⽂件:ResourceBundle bundle = ResourceBundle.getBundle("log4j_filter"); // 不要写扩展名 .propertiesLOG_FILTER_SWITH = bundle.getString("log4j.filter.swith");LOG_FILTER_KEYS = bundle.getString("log4j.filter.keys"); // 直接在本类中使⽤main调⽤时⽤ Properties.class.getResourceAsStream("/log4j_filter.properties"); //Properties p = new Properties(); //p.load(in); //LOG_FILTER_SWITH = p.getProperty("log4j.filter.swith"); //LOG_FILTER_KEYS = p.getProperty("log4j.filter.keys");⽇志脱敏实现:因为只修改了⼀个log4j类的调⽤,故⽇志必须是private final static Logger logger = LogManager.getLogger(SeqConfControl.class);1 , 配置⽂件 log4j_filter.properties (⼀个参数是脱敏⽇志开关,⼀个参数是要脱敏的关键字)2,⾃定义类: org.apache.logging.log4j.spi.Log4jFilter.java 是解析处理⽇志字符串中的敏感信息;log4j原⽣类: org.apache.logging.log4j.spi.AbstractLogger.java 负责调⽤⾃⼰写的类的⽅法.3,规则⽀持k:v 和 k=v 两种形式的数据处理脱敏时v的长度如果⼤于8,采⽤ XXX****XXX的形式脱敏;如果⼩于等于8采⽤ ******* 形式脱敏效果:20:25:02,0197 [INFO ][ ][connect to SFTP . ip:10.0.26.36; port:22;uppath:null;downpath:home/selfftp/selffile/20161209/;username:selfftp;password:********][ :][hulk.frame.sftp.SFtpTools]21:06:16,0907 [INFO ][ ][接收到⼀个纯⽂本消息并开始传⼊数据库:{"data":"{\"state\":\"0\",\"hostName\":\"termfrontapp\",\"policyName\":\"check_SSPM_101\",\"stateName\":null,\"program\":null,\"entryId\":null,\"agentId\":null,\"msg\":\"{\\\21:06:16,0907 [INFO ][ ][the message to decode: {"account_num":"62294785200****0034","amount":"2.00","channel_id":"01I","p_trans_code":"1017006","card_type":"","start_time":"1481634017288","end_time":"1481634017526","term_id":"01159log4j_filter.properties:# log4j 过滤器配置⽂件,主要⽤于系统中敏感字段的脱敏# true表⽰打开 false表⽰关闭log4j.filter.swith=true# 要脱敏的关键字log4j.filter.keys=password,passwd,password1,password2,account_num⾃定义解析类:org.apache.logging.log4j.spi.Log4jFilter.javapackage org.apache.logging.log4j.spi;import java.util.ResourceBundle;import java.util.regex.Matcher;import java.util.regex.Pattern;/*** ⾃定义处理⽇志中的敏感信息* @author yangw1006@**/public class Log4jFilter {/*** ⽇志脱敏开关*/private static String LOG_FILTER_SWITH = "false";/*** ⽇志脱敏关键字*/private static String LOG_FILTER_KEYS = null;static{// 加载配置⽂件try {// 直接在本类中使⽤main调⽤时⽤ Properties.class.getResourceAsStream("/log4j_filter.properties");//InputStream in =Properties.class.getClassLoader().getResourceAsStream("log4j_filter.properties");//Properties p = new Properties();//p.load(in);//LOG_FILTER_SWITH = p.getProperty("log4j.filter.swith");//LOG_FILTER_KEYS = p.getProperty("log4j.filter.keys");ResourceBundle bundle = ResourceBundle.getBundle("log4j_filter");LOG_FILTER_SWITH = bundle.getString("log4j.filter.swith");LOG_FILTER_KEYS = bundle.getString("log4j.filter.keys");} catch (Exception e) {e.printStackTrace();}}/*** 处理⽇志字符串,返回脱敏后的字符串* @param msg* @return*/public static String invokeMsg(final String message){String msg = new String(message);if("true".equals(LOG_FILTER_SWITH)){//处理字符串if(LOG_FILTER_KEYS!=null && LOG_FILTER_KEYS.length()>0){String[] keyArr = LOG_FILTER_KEYS.split(",");for(String key: keyArr){// 找keyint index= -1;do{index = msg.indexOf(key, index+1);if(index!=-1){// 判断key是否为单词字符if(isWordChar(msg,key,index)){continue;}// 确定是单词⽆疑....................................// 寻找值的开始位置.................................int valueStart = getValueStartIndex(msg,index + key.length());//查找值的结束位置(逗号,分号)........................int valueEnd = getValuEndEIndex(msg,valueStart);// 对获取的值进⾏脱敏String subStr = msg.substring(valueStart, valueEnd);subStr = tuomin(subStr);///////////////////////////msg = msg.substring(0,valueStart) + subStr + msg.substring(valueEnd); }}while(index!=-1);}}}return msg;}private static Pattern pattern = pile("[0-9a-zA-Z]");/*** 判断从字符串msg获取的key值是否为单词, index为key在msg中的索引值* @return*/private static boolean isWordChar(String msg,String key, int index){// 必须确定key是⼀个单词............................if(index!=0){ //判断key前⾯⼀个字符char preCh = msg.charAt(index-1);Matcher match = pattern.matcher(preCh+"");if(match.matches()){return true;}}//判断key后⾯⼀个字符char nextCh = msg.charAt(index+key.length());Matcher match = pattern.matcher(nextCh+"");if(match.matches()){return true;}return false;}/*** 获取value值的开始位置* @param msg 要查找的字符串* @param valueStart 查找的开始位置* @return*/private static int getValueStartIndex(String msg, int valueStart ){// 寻找值的开始位置.................................do{char ch = msg.charAt(valueStart);if(ch == ':' || ch == '='){ // key 与 value的分隔符valueStart ++;ch = msg.charAt(valueStart);if(ch == '"'){valueStart ++;}break; //找到值的开始位置}else{valueStart ++;}}while(true);return valueStart;}/*** 获取value值的结束位置* @return*/private static int getValuEndEIndex(String msg,int valueEnd){do{if(valueEnd == msg.length()){break;}char ch = msg.charAt(valueEnd);if(ch == '"'){ // 引号时,判断下⼀个值是结束,分号还是逗号决定是否为值的结束if(valueEnd+1 == msg.length()){break;}char nextCh = msg.charAt(valueEnd+1);if(nextCh ==';' || nextCh == ','){// 去掉前⾯的 \ 处理这种形式的数据 "account_num\\\":\\\"6230958600001008\\\"while(valueEnd>0 ){char preCh = msg.charAt(valueEnd-1);if(preCh != '\\'){break;}valueEnd--;}break;}else{valueEnd ++;}}else if (ch ==';' || ch == ','){break;}else{valueEnd ++;}}while(true);return valueEnd;}private static String tuomin(String submsg){StringBuffer sbResult = new StringBuffer();if(submsg!=null && submsg.length()>0){int len = submsg.length();if(len > 8){ //8位以上的隐掉中间4位for(int i = len-1;i>=0;i--){if(len-i<5 || len-i>8){sbResult.insert(0, submsg.charAt(i));}else{sbResult.insert(0, '*');}}}else{ //8位以下的全部使⽤ *for(int i =0;i<len;i++){sbResult.append('*');}}}return sbResult.toString();}public static void main (String[] args) {//{\\\"account_num\\\":\\\"6230958600001008\\\",\\\"amount\\\":\\\"\\\"String msg = "\\\"account_num\\\":\\\"6230958600001008\\\",\\\"amount\\\":\\\"\\\"";System.out.println(invokeMsg(msg));}}log4j原⽣类 org.apache.logging.log4j.spi.AbstractLogger.java 修改的地⽅# 代码 725⾏左右的⽅法protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message, final Throwable t) { // by yangwString invokeMsg = Log4jFilter.invokeMsg(message);logMessage(fqcn, level, marker, messageFactory.newMessage(invokeMsg), t);}。
log4j2异步日志原理

log4j2异步日志原理
log4j2 是一个流行的 Java 日志框架,它支持异步日志记录。
log4j2 的异步日志原理主要涉及以下几个方面:
1. 异步日志队列,log4j2 使用 Disruptor(一种高性能的并发框架)作为异步日志队列,它能够高效地处理大量的日志事件。
当日志事件产生时,它会被放入 Disruptor 的环形队列中,而不会阻塞当前线程。
2. 异步日志 Appender,log4j2 的 Appender 是用来指定日志输出目的地的组件,异步日志 Appender 会从 Disruptor 队列中获取日志事件,并将其输出到指定的目的地,比如文件、数据库或控制台。
3. 异步日志配置,通过 log4j2 的配置文件,可以指定日志记录器(Logger)使用异步日志方式,这样日志事件会被放入Disruptor 队列中,而不会阻塞当前线程。
总的来说,log4j2 的异步日志原理是通过 Disruptor 队列实
现日志事件的异步处理,从而提高日志记录的性能和吞吐量。
这种机制能够在高并发环境下有效地降低日志记录对系统性能的影响。
java日志级别

java⽇志级别log4j定义了8个级别的log(除去OFF和ALL,可以说分为6个级别),优先级从⾼到低依次为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL。
ALL 最低等级的,⽤于打开所有⽇志记录。
TRACE designates finer-grained informational events than the DEBUG.Since:1.2.12,很低的⽇志级别,⼀般不会使⽤。
DEBUG 指出细粒度信息事件对调试应⽤程序是⾮常有帮助的,主要⽤于开发过程中打印⼀些运⾏信息。
INFO 消息在粗粒度级别上突出强调应⽤程序的运⾏过程。
打印⼀些你感兴趣的或者重要的信息,这个可以⽤于⽣产环境中输出程序运⾏的⼀些重要信息,但是不能滥⽤,避免打印过多的⽇志。
WARN 表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员的⼀些提⽰。
ERROR 指出虽然发⽣错误事件,但仍然不影响系统的继续运⾏。
打印错误和异常信息,如果不想输出太多的⽇志,可以使⽤这个级别。
FATAL 指出每个严重的错误事件将会导致应⽤程序的退出。
这个级别⽐较⾼了。
重⼤错误,这种级别你可以直接停⽌程序了。
OFF 最⾼等级的,⽤于关闭所有⽇志记录。
如果将log level设置在某⼀个级别上,那么⽐此级别优先级⾼的log都能打印出来。
例如,如果设置优先级为WARN,那么OFF、FATAL、ERROR、WARN 4个级别的log能正常输出,⽽INFO、DEBUG、TRACE、 ALL级别的log则会被忽略。
Log4j建议只使⽤四个级别,优先级从⾼到低分别是ERROR、WARN、INFO、DEBUG。
从我们实验的结果可以看出,log4j默认的优先级为ERROR或者WARN(实际上是ERROR)。
java中使用日志

java中使用日志在Java中,日志是一种用于记录应用程序运行时信息的重要工具。
它可以帮助开发人员在应用程序中定位问题、调试代码以及监控系统运行情况。
Java提供了多种日志框架和API,最常用的是Java自带的java.util.logging和第三方库Log4j和Logback。
1. 使用java.util.logging:Java自带的日志框架是java.util.logging(JUL),它是在JDK中内置的一个简单的日志系统。
使用JUL,你需要创建一个Logger对象,然后使用不同级别的日志方法(如info、warning、severe)记录日志信息。
可以通过设置日志级别、输出格式和日志处理器来配置JUL。
优点,不需要引入额外的依赖,简单易用。
缺点,功能相对较弱,配置相对繁琐。
2. 使用Log4j:Log4j是一个功能强大且广泛使用的日志框架。
它提供了丰富的配置选项和灵活的日志级别控制。
使用Log4j,你需要在项目中引入Log4j的依赖,然后配置一个log4j.properties或log4j.xml文件,指定日志输出的格式、位置和级别。
在代码中,你可以通过获取Logger对象并调用不同级别的日志方法来记录日志信息。
优点,功能强大、配置灵活、性能较好。
缺点,需要引入额外的依赖。
3. 使用Logback:Logback是Log4j框架的改进版本,也是目前广泛使用的日志框架之一。
它提供了与Log4j类似的功能,但性能更好。
使用Logback,你需要在项目中引入Logback的依赖,然后配置一个logback.xml文件,指定日志输出的格式、位置和级别。
在代码中,你可以通过获取Logger对象并调用不同级别的日志方法来记录日志信息。
优点,性能较好、配置灵活、与Log4j兼容。
缺点,需要引入额外的依赖。
总结:以上是Java中使用日志的常见方式。
选择合适的日志框架取决于你的需求和偏好。
无论你选择哪种方式,良好的日志记录可以帮助你更好地理解应用程序的运行情况,快速定位问题并进行调试。
log4j 删除日志原理

log4j删除日志原理详解1. 什么是log4jlog4j是一个Java日志框架,用于记录应用程序的日志信息。
它是Apache软件基金会的一个开源项目,被广泛用于Java应用程序中。
log4j提供了灵活的配置选项,可以将日志输出到不同的目标(如控制台、文件、数据库等),并且可以根据日志级别过滤不同类型的日志信息。
2. log4j的基本原理log4j的基本原理可以归纳为以下几个步骤:步骤1:配置log4j在使用log4j之前,需要先进行配置。
log4j的配置文件通常为log4j.properties或log4j.xml,其中定义了日志输出的目标、格式、级别等信息。
步骤2:引入log4j库在Java应用程序中引入log4j库,以便在代码中使用log4j提供的API进行日志记录。
步骤3:获取Logger对象在代码中通过调用Logger.getLogger()方法获取Logger对象。
每个Logger对象与一个特定的类关联,用于记录该类产生的日志信息。
步骤4:设置日志级别通过调用Logger对象的setLevel()方法设置该Logger对象所记录的日志级别。
只有达到指定级别及以上的日志信息才会被记录。
步骤5:编写日志记录语句在代码中通过调用Logger对象的不同方法(如debug()、info()、warn()、error()等)编写日志记录语句。
根据不同的日志级别,选择合适的方法进行日志记录。
步骤6:输出日志当代码中执行了Logger对象的日志记录方法后,log4j会根据配置文件中的设置,将相应级别的日志信息输出到指定目标(如控制台、文件、数据库等)。
3. log4j删除日志原理在实际应用中,由于业务需求或存储空间限制,我们可能需要定期删除过时的日志信息。
log4j提供了一些机制来实现删除日志的功能。
基于时间戳删除log4j允许我们在配置文件中设置一个时间戳(或日期),当达到这个时间戳后,自动删除该时间之前的所有日志信息。
java 日志收集的方式

java 日志收集的方式在Java应用程序中,日志收集是一项重要的任务,以便于监测、故障排除和性能分析。
以下是一些Java日志收集的常见方式:Java Util Logging(JUL):JUL是Java平台的官方日志框架,通过java.util.logging包提供。
可以配置日志记录器、处理程序和格式化程序,将日志输出到不同的目标。
配置通常通过logging.properties文件进行。
Log4j:Log4j是一个流行的开源日志框架,提供了更灵活的配置和更丰富的功能。
通过使用log4j.properties或log4j.xml配置文件,你可以定义日志记录器、布局和输出目标。
Logback:Logback是由Log4j的创始人开发的日志框架,它是Log4j的后继者。
Logback提供了与Log4j类似的功能,但在一些方面更为先进。
配置文件通常是logback.xml。
Slf4j(Simple Logging Facade for Java):Slf4j是一个日志接口,允许你使用不同的底层日志实现,如Log4j、Logback等。
Slf4j并不是具体的日志实现,而是为应用提供一个统一的接口。
ELK Stack(Elasticsearch, Logstash, Kibana):ELK Stack是一组用于日志分析和可视化的开源工具。
Elasticsearch 用于存储和搜索日志数据,Logstash用于收集和处理日志,Kibana用于创建仪表板和可视化。
Application Performance Monitoring(APM)工具:APM工具如New Relic、AppDynamics、Dynatrace等提供了不仅仅是日志收集,还包括性能监控、错误追踪等功能。
它们可以帮助你更全面地了解应用程序的运行状况。
Syslog:Java应用程序可以通过Syslog协议将日志消息发送到远程Syslog 服务器。
使用log4j2打印Log,log4j不能打印日志信息,log4j2不能打印日志信息,lo。。。

使⽤log4j2打印Log,log4j不能打印⽇志信息,log4j2不能打印⽇志信息,lo。
说来惭愧,今天就写了个"hello world",了解了⼀下log4j的⽇志。
本来是想在控制台打印个log信息,也是遇到坎坷重重,开始也没去了解log4j就来使⽤,log4j配置⽂件开始⽤的log4j.properties,结果控制台⼀直打印ERROR StatusLogger No log4j2 configuration file found.也就是Log4j2配置⽂件没找到的意思。
我就把log4j.properties⽂件名改成log4j2.properties,结果不报错了,但是就是不打印⽇志,直接就结束运⾏了(Process finished with exit code 0),现在想想好愚蠢啊。
后来经过百般折腾,发现log4j是log4j,log4j2是log4j2,不能混⽤啊,但它们都是出⾃同⼀个公司,log4j2顾名思义是第⼆代,是log4j的优化升级版。
log4j的配置⽂件是log4j.properties,是以.properties后缀名结尾的⽂件命名,⽽log4j2的配置⽂件⼀般是xml⽂件或json,以.xml或.json 后缀格式的命名,log4j更新到1.2.17版就停⽌了更新,发布了Log4j2; 我加⼊的jar包⼀直是log4j2的jar包,开始使⽤了log4j的配置⽂件(log4j.properties),所以⼀直打印不出来。
后来重新加⼊配置⽂件log4j2.xml后,就可以打印了。
maven的pom.xml⽂件中加⼊的依赖:加⼊log4j的实现和log4j核⼼包,如果版本号(version)在2.0以下,配置⽂件就是.properties了哦<!-- https:///artifact/org.apache.logging.log4j/log4j-slf4j-impl --><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-slf4j-impl</artifactId><version>2.6.2</version></dependency><!-- https:///artifact/org.apache.logging.log4j/log4j-core --><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.6.2</version></dependency> 如果是springboot项⽬:需要排除⼀个logback的jar包,以免冲突: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><!--log4j-slf4j-impl与 logback-classic包不兼容,删除这个包 --><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId></exclusion></exclusions></dependency> log4j2.xml⽂件:⽹上复制的⼀个,写的挺全,由于我只⽤到在控制台打印输出,所以我把没⽤到的都注释了。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
浅谈JAVA中的日志文件log4的使用方法:log4是具有日志记录功能,主要通过一个配置文件来对程序进行监测有两种配置方式:一种程序配置,一种文件配置有三个主要单元要了解,Logger,appender,layout.logger是进行记录的主要类,appender是记录的方式,layout是记录的格式logger七种日志级别:debug,info,warn,error,fatal,all,off最常用的应该是debug()和info();而warn()、error()、fatal()仅在相应事件发生后才使用appender主要分三类,终端输出,文件输出,流输出ConsoleAppenderFileAppenderWriterAppenderlayout也分三类:简单格式,html格式,匹配格式SimpleLayoutHTMLLayoutPatternLayout输出简写:(用在PatternLayout)%m 输出代码中指定的消息%p 输出优先级%r 输出自应用启动到输出该log信息耗费的毫秒数%c 输出所属的类目,通常就是所在类的全名%t 输出产生该日志事件的线程名%n 输出一个回车换行符,Windows平台为“\r\n”,Unix平台为“\n”%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。
一般使用了它就不需使用%c了[按照下面步骤来写吧!就可以得到我们所想要的日志文件哦!][按照顺序就可以将日志文件读出来了!]作用实例:程序配置一般过程:1.得到特定名称的logger2.得到其中一个layout3.根据layout得到appender4.logger添加appender5.logger设置级别6.logger输出有级别的日志信息程序:Logger logger = Logger.getLogger(Test.class.getName()) //取得loggerSimpleLayout simpleLayut = new SimpleLayout() //取得layoutFileAppender fa = new FileAppender(simpleLayout,"test.log") //取得ppenderlogger.addAppender(fa) //添加appenderlogger.set((Level)Level.DEBUG) //设置级别logger.debug("hihihihih") //记录信息文件配置过程:1.得到特定名称的logger2.加载配置文件 (配置文件做了2-5的工作)3.logger输出有级别的日志信息文件配置程序:1.Logger logger = Logger.getLogger(Test.class.getName()) //取得logger2.使用下面的配置加载3.输出信息文件配置分properties,xml读取properties:PropertyConfigurator.configure("logTest.properties");读取xml:DOMConfigurator.configure("src/logTest.xml");告别System.out.print()—J2SDK1.4新增Java日志框架(一)作为一名Java程序员,最熟悉的、使用最多的调用恐怕莫过于System.out.print(“…”)。
当你没有调试工具而要跟踪一个变量的值得时候;当你需要显示捕获的Exception、Error的时候;当你想知道程序在运行的时候究竟发生了什么的时候,通常的做法就是调用System.out.print把他们在终端、控制台上打印出来。
这种方式对于输出信息的分类、格式化及永久保存带来诸多不便。
虽然我们可以把它写入一个文件然后进行分析,但是这要需要编写额外的程序代码,其成本不可忽视!而由此给目标系统本身增加的复杂程度不可避免的使开发、调试陷入一个深深的迷潭。
[要知道一点:如果说能不写的代码最好不要写!]JDK1.4的推出,使得这一切即将成为历史。
让我们向System.out.print()告别吧,使用Java Logging API为自己的程序构建一个完整的日志记录系统!一、第一个实例先看一个简单的实例:1 import java.util.logging.*;2 public class SimpleLoggingTest {3 public static void main(String args[]) {4 //程序的其它处理5 //使用Logger的静态方法获得一个匿名 //Logger6 Logger logger1 = Logger.getAnonymousLogger();7 //记录消息8 logger1.log(,"第一条日志记录");9 //程序的其它处理10 }11 }实例1注意:编译、执行该程序需要JDK1.4及以上版本的支持。
运行该程序,可以在控制台看到程序运行结果:2003-1-14 15:09:40 SimpleLoggingTest main信息:第一条日志记录首先,程序引用java.util.Logging包(第1行)。
接着,在适当的时候获得一个Logger(记录器)类的实例(第6行,获取一个匿名的Logger)。
最后,在程序需要记录信息的地方调用Logger类的log方法进行记录(第8行,记录一个INFO级别的消息)。
二、Java Logging APIJava Logging API封装在JDK1.4.0的java.util.Logging 包中。
它通过产生便于最终用户、系统管理员、故障维护工程师以及软件开发团队(工程师)进行分析的日志记录为软件的开发调试和维护提供便利的手段。
它捕获操作系统平台和执行程序的安全故障、配置错误、执行瓶颈和(或)Bug等数据信息,以纯文本、XML或程序员自定的某种方式将其格式化成日志记录,然后传递给内存、系统输出流、控制台、文件、Sockets等多种系统资源进行缓存和输出。
(一)、该软件包中的关键类。
n Logger:应用程序进行日志记录调用的主要实体。
Logger对象用于记录特定系统或应用程序的消息。
n LogRecord:用于在日志框架和单个记录处理程序之间传递记录请求。
n Handler:日志数据的最终输出处理器。
它将LogRecord对象导出到各种目标,包括内存、输出流、控制台、文件和套接字。
多种Handler子类可供用于这种用途。
图一n Level:定义一组标准的记录级别,可用于控制记录的输出。
可以把程序配置为只输出某些级别的记录,而忽略其他级别的输出。
n Filter:精细过滤、控制记录的内容,比记录级别所提供的控制准确得多。
记录API支持通用的过滤器机制,这种机制允许应用程序代码添加任意过滤器以便控制记录的输出。
n Formatter:为LogRecord对象的格式化提供支持。
图二n LogManager: Java Logging框架中唯一的、全局的对象,用于维护与Logger记录器及日志服务的一系列共享的数据结构及状态。
它负责整个日志框架的初始化、维护一组全局性的Handle对象、维护一个树形结构的Logger的名字空间、诊测日志框架配置文件的改变从而重新读入并应用相关的参数以及负责程序停止运行时整个日志框架的清理工作。
(二)Logger1、Logger的命名空间在SimpleLoggingTest.java实例中,我们使用了一个匿名的(没有命名的)Logger对象。
在Java Logging 框架中,Logger是可以命名的。
Logger的名字空间与java类的名字空间相同的结构相同:使用“。
”间隔的字符串。
Logger 的名字空间体现了Logger的层次结构。
例如:命名为“a.b”的Logger是命名为“a.b.c”的“父”(上一级)Logger记录器。
Logger的命名可以是任意的字符串,一般情况下,使用包或类的名字为Logger 进行命名。
Logger的名字空间由全局单列类LogManager的实例进行创建、维护。
[貌似在处理数据库的时候的DriverManage来管理数据库驱动一样了!]匿名Logger不被存储在命名空间中。
2、创建Logger实例Logger对象可以通过调用工厂方法getLogger或getAnonymousLogger获取。
//获取一个名为“A”的Logger对象Logger loggerA= Logger.getLogger(“A”);// 获取一个名为“A.B”的Logger对象,其上级记录器为loggerA.Logger loggerAB= Logger.getLogger(“A.B”);//获取一个匿名Logger对象Logger loggerTmp = Logger.getAnonymousLogger();对非匿名Logger,getLogger先在命名空间中查找同名的Logger对象,如果有,则返回该Logger对象;如果不存在,则在命名空间中创建注册一个新的Logger对象,并与其上级Logger对象相关联。
匿名Logger对象属于创建它的对象的私有对象,只能由创建它的对象使用,记录一些临时性的日志信息。
而命名Logger对象使全局性的,在日志框架的生存期内,除了创建它的对象外还,可由其它对象用于记录日志信息。
匿名的Logger对象由一个全局的的root Logger “” 对象(root Logger 的名字为空)。
这意味着所有匿名Logger对象将从root Logger “”中继承行为。
匿名Logger对象通常用于java Applet应用中。
它去掉了在运行过程中的一班性的安全检查,允许其创建类对象对Logger的控制、状态信息进行修改,如:setLevel设置Logger的日志消息记录级别;addHandle增加Logger的Handle (处理器)对象等。
一个Logger对象可以拥有有零个到多个Handler实例。
当没有Handler时,如不禁止日志记录沿名字空间向上传递,那该Logger对象的日志消息记录将有其拥有Handler实例的上级Logger进行处理。
当一个Logger对象拥有多个Handler实例对象时,其记录的日志数据将被所有的Handler逐一进行处理。