摘要:所有低于级别的消息记录将会被忽略。构造函数,创建一个与有关的构造函数,创建一个,记录消息到指定文件。这个构造函数用来创建一个对象这个方法来自类,通过它设置。该对象是全局的,用来维护一组共享状态和日志服务。
Jdk Logging 解析原文链接
原作者:Rohit Joshi
译者:smallclover
个人翻译,水平有限,如有错误欢迎指出,谢谢!
在本文中,我们将讨论关于Java的日志(logging)功能。日志,用简单的话来说就是记录应用程序的活动。日志通常被用于存储异常(exceptions)、信息(information)、警告(warnings)的消息,这些消息可能会出现在程序的整个执行过程。日志在程序员调式(debug)程序的过程中会有所帮助。
Java 包(package)java.util.logging与日志记录的功能有关。这个包由一些用于日志功能的类(class)和接口(interface)组成。系统使用Logger对象(object)来记录消息。
这个Logger对象会被分配一个LogRecord对象,该LogRecord对象存储了记录的消息。这个LogRecord对象会被转发到所有的handler,再由handler分派给Logger对象。logger和handler可以视需要使用一个与它们有关联的过滤器(Filter)来过滤日志消息。然后,handler会发布这些被日志记录的消息到外部的系统。
让我们从这个包中一些比较重要的类开始。
1.Logger and Level创建一个Logger类的logger对象来记录消息。logger对象会要求使用者提供一个名称和一组用于设置记录消息的等级的方法。虽然你可以提供任何一个名字到logger,但是建议使用包和类名来创建logger。
Level类提供7种日志级别
SEVERE (最高级别)
WARNING
INFO
CONFIG
FINE
FINER
FINEST (最低级别)
在Level中所有的级别(level)都被定义成静态常量字段(static final field)。你能使用任何一个级别,然后根据这些级别来记录消息。另外,它还提供了一个level OFF 可以关闭日志记录,一个level All用于打开所有级别的日志。
我们看一个关于如何创建和使用logger的示例。
LoggerExample.java
01 package com.javacodegeeks.corejava.util.logging; 02 03 import java.io.IOException; 04 import java.util.logging.Level; 05 import java.util.logging.Logger; 06 07 public class LoggerExample { 08 09 private static final Logger LOGGER = Logger.getLogger(LoggerExample.class.getName()); 10 public static void main(String[] args) throws SecurityException, IOException { 11 12 LOGGER.info("Logger Name: "+LOGGER.getName()); 13 14 LOGGER.warning("Can cause ArrayIndexOutOfBoundsException"); 15 16 //An array of size 3 17 int []a = {1,2,3}; 18 int index = 4; 19 LOGGER.config("index is set to "+index); 20 21 try{ 22 System.out.println(a[index]); 23 }catch(ArrayIndexOutOfBoundsException ex){ 24 LOGGER.log(Level.SEVERE, "Exception occur", ex); 25 } 26 27 28 } 29 30 }
如果我们运行以上代码,我们将得到如下结果:
1 Jun 08, 2014 1:19:30 PM com.javacodegeeks.corejava.util.logging.LoggerExample main 2 INFO: Logger Name: com.javacodegeeks.corejava.util.logging.LoggerExample 3 Jun 08, 2014 1:19:31 PM com.javacodegeeks.corejava.util.logging.LoggerExample main 4 WARNING: Can cause ArrayIndexOutOfBoundsException 5 Jun 08, 2014 1:19:31 PM com.javacodegeeks.corejava.util.logging.LoggerExample main 6 SEVERE: Exception occur 7 java.lang.ArrayIndexOutOfBoundsException: 4 8 at com.javacodegeeks.corejava.util.logging.LoggerExample.main(LoggerExample.java:22)
在上面这个示例中,我们使用getLogger静态方法(static method)创建了一个logger对象。然后,我们记录了不同级别的日志消息。为了阐述Logger的使用我们也尝试抛出了ArrayIndexOutOfBoundsException。
让我们看一看在本例中使用的方法。
Logger.getLogger(String name):该方法通过传递的name参数来创建或者发现一个logger。
void info(String msg):该实例方法用于记录INFO级别的日志消息,但是前提是当前的logger能够使用INFO级别的日志消息,否则该级别的日志消息将会被忽略。
void warning(String msg): 该实例方法用于记录WARNING级别的日志消息,但是前提是当前的logger能够使用INFO级别的日志消息,否则该级别的日志消息将会被忽略。
void config(String msg): 该实例方法用于记录CONFIG级别的日志消息,但是前提是当前的logger能够使用INFO级别的日志消息,否则该级别的日志消息将会被忽略。
void log(Level level, String msg, Object param1):该方法根据传递的日志级别来记录消息,同时传递的参数还有一个object。当你想存储一个对象在日志中的时候你可使用这个方法。正如我们上面的示例一样,我们记录了一个SEVERE级别的exception object。
请注意,INFO级别是logger的默认级别。所有低于INFO级别的消息记录将会被忽略。正如你所看到的那样,WARNING级别的消息记录被忽略了,并没有被打印在控制台上。(此处原文可能有误)
译者注:这里原文可能有错误,首先WARNING的级别是高于INFO级别的,其次WARNING级别的日志的确打印在控制台上。所以,译者认为这里应该是CONFIG级别。请读者注意。
2.HandlerHandler是日志框架的组件之一,它负责打印日志消息到目标目的地。这个目的地可以是控制台(console)也可以是文件(file)。Handler获得一个LogRecord对象形式的日志消息,并输出到目标目的地。一个Logger可以关联一个或者多个Handler,最后将日志消息转发给所有的Handler。Handler在Java 包 java.util.logging中是一个抽象类,同时它也是各种Handler的父类。
在Java中内置4种handler。
ConsoleHandler: ConsoleHandler 记录所有的System.in的日志消息,默认情况下,Logger是与此Handler相关联的。
FileHandler: FileHandler 记录所有的来自特定的文件或者一组文件集合的日志消息。
StreamHandler: StreamHandler会发布所有的日志消息到一个OutputStream.
SocketHandler: SocketHandler会发布LogRecords到一个网络连接流中。
MemoryHandler: 它是用来保持LogRecords内存缓冲区。如果缓冲区满了,新的LogRecords会覆盖旧的LogRecords。
HandlerExample.java
01 package com.javacodegeeks.corejava.util.logging; 02 03 import java.io.IOException; 04 import java.util.logging.ConsoleHandler; 05 import java.util.logging.FileHandler; 06 import java.util.logging.Handler; 07 import java.util.logging.Level; 08 import java.util.logging.Logger; 09 10 public class HandlerExample { 11 12 private static final Logger LOGGER = Logger.getLogger(LoggerExample.class.getName()); 13 public static void main(String[] args) { 14 15 Handler consoleHandler = null; 16 Handler fileHandler = null; 17 try{ 18 //Creating consoleHandler and fileHandler 19 consoleHandler = new ConsoleHandler(); 20 fileHandler = new FileHandler("./javacodegeeks.log"); 21 22 //Assigning handlers to LOGGER object 23 LOGGER.addHandler(consoleHandler); 24 LOGGER.addHandler(fileHandler); 25 26 //Setting levels to handlers and LOGGER 27 consoleHandler.setLevel(Level.ALL); 28 fileHandler.setLevel(Level.ALL); 29 LOGGER.setLevel(Level.ALL); 30 31 LOGGER.config("Configuration done."); 32 33 //Console handler removed 34 LOGGER.removeHandler(consoleHandler); 35 36 LOGGER.log(Level.FINE, "Finer logged"); 37 }catch(IOException exception){ 38 LOGGER.log(Level.SEVERE, "Error occur in FileHandler.", exception); 39 } 40 41 LOGGER.finer("Finest example on LOGGER handler completed."); 42 43 } 44 45 }
如果我们运行以上代码,我们将会得到以下结果:
1 Jun 08, 2014 1:43:19 PM com.javacodegeeks.corejava.util.logging.HandlerExample main 2 CONFIG: Configuration done.
该示例还会在项目的根目录下生成日志文件javacodegeeks.log。
该文件包含以下记录:
01 02 0304 05 152014-06-08T13:43:19 061402215199326 070 08com.javacodegeeks.corejava.util.logging.LoggerExample 09CONFIG 10com.javacodegeeks.corejava.util.logging.HandlerExample 11main 121 13Configuration done. 1416 262014-06-08T13:43:19 171402215199376 181 19com.javacodegeeks.corejava.util.logging.LoggerExample 20FINE 21com.javacodegeeks.corejava.util.logging.HandlerExample 22main 231 24Finer logged 2527 372014-06-08T13:43:19 281402215199376 292 30com.javacodegeeks.corejava.util.logging.LoggerExample 31FINER 32com.javacodegeeks.corejava.util.logging.HandlerExample 33main 341 35Finest example on LOGGER handler completed. 36
在该示例中,我们通过FileHandler 和ConsoleHandler记录日志消息。
我们将讨论上面的示例。
ConsoleHandler():构造函数,创建一个与system.err有关的ConsoleHandler
FileHandler(String pattern):构造函数,创建一个FileHandler,记录消息到指定文件。
void addHandler(Handler handler):该实例方法来自类Logger,分配一个handler给logger对象。你也可以分配多个handler给一个logger对象。就像该示例一样,我们分配了ConsoleHandler 和 FileHandler给了一个logger对象。
void setLevel(Level newLevel):Logger和Handler类都有该方法,logger对象通过它来设置指定的日志级别,规定哪些级别的消息可以被记录。消息级别小于指定的级别的将会被忽略。
void removeHandler(Handler handler):该方法会移除与logger对象相关联的handler,一旦该handler被移除,它将没有能力发布任何日志消息。在该示例中,我们移除了ConsoleHandler之后,接下来所有的日志消息将不会被打印在控制台。
void finer(String msg):该示例方法用来记录FINER级别的消息,如果当前允许FINER级别的日志消息则记录,否则忽略。
该日志消息通过FileHandler 发布,在上面的示例中被发布为XML格式。该格式是FileHandler 的默认格式,我们可以改变该handler 的格式。
在下一节中,我们将讨论关于Formatter类和它的使用。
3.FormatterFormatter 用于格式化LogRecord。每个handler会关联一个formatter。Java提供了两个内置的超类formatter:SimpleFormatter 和 XMLFormatter。让我们来看一些示例:
FormatterExample.java
01 package com.javacodegeeks.corejava.util.logging; 02 03 import java.io.IOException; 04 import java.util.logging.Formatter; 05 import java.util.logging.FileHandler; 06 import java.util.logging.Handler; 07 import java.util.logging.Level; 08 import java.util.logging.Logger; 09 import java.util.logging.SimpleFormatter; 10 11 public class FormatterExample { 12 13 private static final Logger LOGGER = Logger.getLogger(LoggerExample.class.getName()); 14 public static void main(String[] args) { 15 16 Handler fileHandler = null; 17 Formatter simpleFormatter = null; 18 try{ 19 20 // Creating FileHandler 21 fileHandler = new FileHandler("./javacodegeeks.formatter.log"); 22 23 // Creating SimpleFormatter 24 simpleFormatter = new SimpleFormatter(); 25 26 // Assigning handler to logger 27 LOGGER.addHandler(fileHandler); 28 29 // Logging message of Level info (this should be publish in the default format i.e. XMLFormat) 30 LOGGER.info("Finnest message: Logger with DEFAULT FORMATTER"); 31 32 // Setting formatter to the handler 33 fileHandler.setFormatter(simpleFormatter); 34 35 // Setting Level to ALL 36 fileHandler.setLevel(Level.ALL); 37 LOGGER.setLevel(Level.ALL); 38 39 // Logging message of Level finest (this should be publish in the simple format) 40 LOGGER.finest("Finnest message: Logger with SIMPLE FORMATTER"); 41 }catch(IOException exception){ 42 LOGGER.log(Level.SEVERE, "Error occur in FileHandler.", exception); 43 } 44 } 45 46 }
如果我们运行以上代码,我们将得到以下结果:
1 Jun 08, 2014 4:57:02 PM com.javacodegeeks.corejava.util.logging.FormatterExample main 2 INFO: Finnest message: Logger with DEFAULT FORMATTER
该示例也会在项目的根目录下生成一个日志文件:javacodegeeks.formatter.log。
在上面的示例中,我们使用SimpleFormatter以一种简单的,可读的格式打印LogRecord。请注意在设置handler的格式为 SimpleFormatter之前,我们的消息会发布到一个XML格式的文件中。因为FileHandler的默认格式是XMLFormatter。同时还要注意这个LogRecord也会被发布到控制台,因为 ConsoleHandler 和 Logger是默认关联的。
SimpleFormatter():这个构造函数用来创建一个SimpleFormatter对象.
void setFormatter(Formatter newFormatter):这个方法来自handler类,handler通过它设置formatter。
3.FilterFilter接口(interface)位与java.util.logging包下。 Handler通过它来控制消息的记录。每一个Logger和Handler可以选择一个Filter。Filter 有一个isLoggable方法,该方法返回一个boolean值。在Logger或者Handler发布消息之前会调用此方法,如果返回值为true就发布消息,否则就忽略。
FilterExample.java
01 package com.javacodegeeks.corejava.util.logging; 02 03 import java.util.logging.Filter; 04 import java.util.logging.LogRecord; 05 import java.util.logging.Logger; 06 07 public class FilterExample implements Filter{ 08 09 private static final Logger LOGGER = Logger.getLogger(LoggerExample.class.getName()); 10 public static void main(String[] args) { 11 //Setting filter FilterExample 12 LOGGER.setFilter(new FilterExample()); 13 //Since this message string does not contain the word important. Despite of being the Level SEVERE this will be ignored 14 LOGGER.severe("This is SEVERE message"); 15 //This will get published 16 LOGGER.warning("This is important warning message"); 17 18 } 19 20 // This method will return true only if the LogRecord object contains the message which contains the word important 21 @Override 22 public boolean isLoggable(LogRecord record) { 23 if(record == null) 24 return false; 25 26 String message = record.getMessage()==null?"":record.getMessage(); 27 28 if(message.contains("important")) 29 return true; 30 31 return false; 32 } 33 34 }
如果我们运行以上代码,我们将得到以下的结果:
1 Jun 08, 2014 5:13:46 PM com.javacodegeeks.corejava.util.logging.FilterExample main 2 WARNING: This is important warning message
boolean isLoggable(LogRecord record):该方法来自Filter的接口,它会检查LogRecord是否可以发布。
void setFilter(Filter newFilter): 该方法设置一个 Filter 控制 Logger的输出。
5.Configuration你可以通过一个配置文件把配置的属性提供给Logger。这有助于你移除配置代码并且提供一种更加简单的方法在不改变代码的情况下一次又一次的更改配置。通过类LogManager我们可以使用这种灵活的方式。
ConfigurationExample.java
01 package com.javacodegeeks.corejava.util.logging; 02 03 import java.io.FileInputStream; 04 import java.io.IOException; 05 import java.util.logging.Level; 06 import java.util.logging.LogManager; 07 import java.util.logging.Logger; 08 09 public class ConfigurationExample { 10 11 private static final LogManager logManager = LogManager.getLogManager(); 12 private static final Logger LOGGER = Logger.getLogger("confLogger"); 13 static{ 14 try { 15 logManager.readConfiguration(newFileInputStream("./javacodegeeks.properties")); 16 } catch (IOException exception) { 17 LOGGER.log(Level.SEVERE, "Error in loading configuration",exception); 18 } 19 } 20 public static void main(String[] args) { 21 LOGGER.fine("Fine message logged"); 22 } 23 }
该示例读取了包含以下属性的属性文件:
属性文件
1 handlers=java.util.logging.ConsoleHandler 2 .level=ALL 3 java.util.logging.ConsoleHandler.level=ALL 4 java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter 5 confLogger.level=ALL
如果运行以上代码,我们将获得以下结果:
1 Jun 08, 2014 5:23:25 PM com.javacodegeeks.corejava.util.logging.ConfigurationExample main 2 FINE: Fine message logged
让我们讨论该示例的代码和它所配置的属性。
handlers: 设置所有的logger使用默认的handler。
.level:设置所有logger的默认日志级别,值ALL表示开启所有级别的日志消息。
java.util.logging.ConsoleHandler.level: 设置所有ConsoleHandler 的默认日志级别为ALL,即对于ConsoleHandler开启所有级别的日志消息。
java.util.logging.ConsoleHandler.formatter: 设置 ConsoleHandler 的默认格式为SimpleFormatter.
confLogger.level: 设置名称为confLogger的默认级别为开启所有的级别的日志消息。
需要注意的是这些属性都可以在代码中被覆盖。
LogManager.getLogManager():该方法是一个静态方法,用于获取LogManager对象。该LogManager对象是全局的,用来维护一组共享状态和日志服务。
void readConfiguration(InputStream ins):该方法被用来重新初始化日志记录的属性,通过从stream中重新读取日志配置,该配置应该符合java.util.Properties的格式
6.Download the source code你可以从这里下载这个示例的源代码:LoggingExample.zip
失败是成功之母。
failure is mother of success.
失敗は成功の母。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/65813.html
摘要:注意,其是在编译源码过程中,帮你自动生成的。就是说,将极大减少你的代码总量。注解和类似,区别在于它会把所有成员变量默认定义为修饰,并且不会生成方法。不同的日志注解总结如下上面是注解,下面是编译后的代码参考资料下的安装以及使用简介注解介绍 Lombok有什么用 在我们实体Bean中有大量的Getter/Setter方法以及toString, hashCode等可能不会用到,但是某些时候仍...
摘要:定制日志文件简单的日志配置不能满足实际项目需求,那可以通过引用定制日志文件的形式达到目的。能根据类路径下的类库和配置文件自动配置对应的日志框架。看到这里,相信你对的日志应该有了一个全面的了解。 本节内容基于 Spring Boot 2.0. 你所需具备的基础 什么是 Spring Boot? Spring Boot 核心配置文件详解 Spring Boot 开启的 2 种方式 Spr...
摘要:在年首次发表了这种语言,另外与也是这语言的共同设计者。每种都可以通过配置使用控制台或者文件输出日志内容。可以通过是中的一个设置的日志级别。参考文档新年彩蛋自定义参考指南配置类配置详解 导读: 在上篇文章学习到了如何搭建一个简单的Spring Boot的项目,这篇文章我们主要围绕Spring Boot的外部化文件展开, 快速开始:外部化配置 首先是一个典型的Spring Boot的项...
摘要:理解在记录消息中的日志的不同级别是非常重要的。通常来说,当为指定了一个该会包含当前指定级别以及更高级别的日志。,将消息发送至单个一般文件或一个可回滚的文件集合。 本文网大多网络整理所得,出处太多,不一一列举 简介 Java 中的 Logging API 让 Java 应用可以记录不同级别的信息,它在debug过程中非常有用,如果系统因为各种各样的原因而崩溃,崩溃原因可以在日志中清晰地追...
摘要:默认情况下,如果使用,则使用进行日志记录,还包括适当的路由,以确保使用或的依赖库都能正确工作。分隔符,用于区分实际日志消息的开始。 26. 日志记录 Spring Boot为所有内部日志记录使用Commons Logging,但开放底层日志实现,提供了Java Util Logging、Log4J2和Logback的默认配置,在每种情况下,日志记录器都被预先配置为使用控制台输出,可选的...
阅读 1265·2023-04-26 00:35
阅读 2688·2023-04-25 18:32
阅读 3315·2021-11-24 11:14
阅读 758·2021-11-22 15:24
阅读 1362·2021-11-18 10:07
阅读 6311·2021-09-22 10:57
阅读 2755·2021-09-07 09:58
阅读 3547·2019-08-30 15:54