Java基础(十七)日志(Log)
1.日志的概念
在调试有问题的代码时,经常需要插入一些System.out.println方法来观察程序运行的操作过程。但是,一旦发现了问题并且解决了问题,就需要将这些System.out.println语句从代码中删除或者注释。如果接下来又出现了问题,就还要再插入几个System.out.println方法。日志API可以很好地解决这个问题。
日志API的优点:
- 可以很容易地取消全部日志记录,或者仅仅取消某个级别的日志,而且打开和关闭这个操作也很容易。
- 可以很简单地禁止日志的输出,因此,将这些日志代码留在程序中的开销很小。
- 日志记录器和处理器都可以对记录进行过滤。过滤器可以根据过滤实现其指定的标准丢弃无用的记录项。
- 日志记录可以采用不同的方式格式化,例如,纯文本或XML。
- 应用程序可以使用多个日志记录器,它们使用类似包名的具有层次结构的名字。
- 在默认情况下,日志系统的配置由配置文件控制。如果需要的话,应用程序可以替换配置文件。
2.基本日志
使用全局日志记录器(global logger)并调用info方法可以输出指定的信息。
输出有两行信息,第一行是调用日志方法的时间戳,包名,类名,方法名,第二行是用户指定的info信息。
package packageName; import java.util.logging.Logger; public class ClassName { public static void main(String[] args) {
int x = 100;
Logger.getGlobal().info("x的值为: " + x);
}
} 输出:
七月 20, 2018 9:11:20 上午 packageName.ClassName main
信息: x的值为: 100
同时,使用其setLevel方法可以很容易地取消日志的显示。
package packageName; import java.util.logging.Level;
import java.util.logging.Logger; public class ClassName { public static void main(String[] args) {
int x = 100;
Logger.getGlobal().setLevel(Level.OFF);
Logger.getGlobal().info("x的值为: " + x);
}
} 输出:
全局日志记录就是所有的日志都记录到一个日志记录器中:
package packageName; import java.util.logging.Logger; public class ClassName { public static void main(String[] args) {
int x = 100;
Logger.getGlobal().info("x的值为: " + x);
int y = 101;
Logger.getGlobal().info("y的值为: " + y);
}
} 输出:
七月 20, 2018 9:32:16 上午 packageName.ClassName main
信息: x的值为: 100
七月 20, 2018 9:32:16 上午 packageName.ClassName main
信息: y的值为: 101
3.高级日志
在一个专业的应用程序中,不要把所有的日志都记录到一个全局日志记录器中,而是可以自定义多个记录器。
使用Logger.getLogger方法来生成指定记录器名称的记录器,例如,下面的语句定义了两个日志记录器,日志记录器的名字之间有着很强的关联性,iplab就是school的子记录器。未被任何变量引用的日志记录器可能会被垃圾回收,为了防止这种情况,用一个静态变量存储日志记录器的引用。
private static Logger logger = Logger.getLogger("com.school");
private static Logger logger = Logger.getLogger("com.school.iplab");
如果对父记录器设置了日志级别,那么它的子记录器也会继承这个级别,级别一共有七种,SEVERE、WARNING、INFO、CONFIFG、FINE、FINER、FINEST在默认的情况下,只记录前三个级别,如果设置FINE,则FINE和更高的级别都可以记录下来。另外,还可以使用Level.ALL开启所有级别,以及Level.OFF关闭所有级别。
logger.setLevel(Level.FINE);
前面的info就是制定了日志级别,将记录信息指定成不同的级别可以使用下面的方法
logger.warning(message);
logger.fine(message);
logger.log(Level.FINE, message);
例如:由于main方法本身就是静态方法,所以logger就已经是静态的了。
package packageName; import java.util.logging.Logger; public class ClassName { public static void main(String[] args) { Logger logger = Logger.getLogger("com.school.iplab");
int x = 100;
logger.warning("The value of x is " + x);
}
} 输出:
七月 20, 2018 9:56:01 上午 packageName.ClassName main
警告: The value of x is 100
默认的日志记录将显示包含日志调用的类名和方法名,为了得到调用类和方法的确切位置,可以使用logp方法,指定日志记录器所在的包名和方法名以及记录信息。
package packageName; import java.util.logging.Level;
import java.util.logging.Logger; public class ClassName { public static void main(String[] args) { Logger logger = Logger.getLogger("com.school.iplab");
int x = 100;
logger.logp(Level.INFO, "包名", "方法名", "记录信息x=" + x);
}
} 输出:
七月 20, 2018 10:06:49 上午 包名 方法名
信息: 记录信息x=100
还可以跟踪执行流的方法,例如:entering方法记录一个进入read方法的日志,exiting方法记录一个退出read方法的日志。
int read(String file, String pattern) {
Logger logger = Logger.getLogger("com.school.iplab");
logger.entering("packageName.ClassName", "read", new Object[] {file, pattern});
...
logger.exiting("packageName.ClassName", "read", count);
return count; }
日志常见的用途值记录那些不可预料的异常,典型的用法是:
- 在try-catch语句块中,用来记录捕捉到的异常对象的日志。
- 在if语句中,用来记录抛出的异常对象的日志。
try
{
...
}
catch (IOException e)
{
Logger.getLogger("com.horstmann.corejava").log(Level.SEVERE,
"Can't create log file handler", e);
} if(...)
{
IOException exception = new IOException("...");
logger.throwing("类名", "方法名", exception);
throw exception;
}
4.修改日志管理器的配置
可以在jre/lib/logging.properties中修改配置文件,使得指定自己的日志记录级别:
com.xyz.foo.level = SEVERE
5.日志处理器
(1)ConsoleHandler处理器
在默认的情况下,日志记录器将记录发送到ConsoleHandler日志处理器中,并由它输出到System.err流中。另外,日志记录器还会将记录发送到父处理器中。与日志记录器一样,日志处理器也有日志记录级别,对于一个要被记录的日志,它的日志记录级别必须高于日志记录器和日志处理器的阈值。
配置文件中日志处理器的日志级别为:
java.util.logging.ConsoleHandler.level = INFO
要想记录比INFO低级别的日志,例如FINE级别的日志,就必须要修改配置文件的默认日志记录器级别和处理器级别,除了这个方法,还可以自己定义自己的处理器:步骤就是,首先创建一个日志记录器logger并设置日志记录器的记录级别,然后由于原始日志记录器将会把所有等于或高于INFO级别的记录发送到控制台,为了不让原始日志记录器发送而只让自己定义的日志记录器发送记录到控制台,调用setUseParentHandlers方法并传递参数false,然后创建自己的日志处理器,并将处理器的处理级别设置为FINE,最后将日志记录器发送到定义的日志处理器。
package packageName; import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger; public class ClassName { public static void main(String[] args) {
Logger logger = Logger.getLogger("com.school.iplab");
logger.info("info0");
logger.fine("fine0");
logger.setLevel(Level.FINE);
logger.setUseParentHandlers(false);
Handler handler = new ConsoleHandler();
handler.setLevel(Level.FINE);
logger.addHandler(handler);
logger.info("info1");
logger.fine("fine1");
}
} 输出:
七月 20, 2018 11:08:34 上午 packageName.ClassName main
信息: info0
七月 20, 2018 11:08:34 上午 packageName.ClassName main
信息: info1
七月 20, 2018 11:08:34 上午 packageName.ClassName main
详细: fine1
(2)FileHandler处理器用来本地化
package packageName; import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger; public class ClassName { public static void main(String[] args) throws SecurityException, IOException {
Logger logger = Logger.getLogger("com.school.iplab");
logger.info("info0");
logger.fine("fine0");
logger.setLevel(Level.FINE);
logger.setUseParentHandlers(false);
Handler handler = new FileHandler("myapp.log");
handler.setLevel(Level.FINE);
logger.addHandler(handler);
logger.info("info1");
logger.fine("fine1");
}
}
在项目的文件夹下会生成一个myapp.log文件,文件内容是XML格式的:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
<date>2018-07-20T11:23:21</date>
<millis>1532057001808</millis>
<sequence>1</sequence>
<logger>com.school.iplab</logger>
<level>INFO</level>
<class>packageName.ClassName</class>
<method>main</method>
<thread>1</thread>
<message>info1</message>
</record>
<record>
<date>2018-07-20T11:23:21</date>
<millis>1532057001808</millis>
<sequence>2</sequence>
<logger>com.school.iplab</logger>
<level>FINE</level>
<class>packageName.ClassName</class>
<method>main</method>
<thread>1</thread>
<message>fine1</message>
</record>
</log>
6.过滤器
在默认情况下,过滤器根据日志记录的级别进行过滤。每个日志记录器和处理器都可以有一个可选的过滤器来完成附加的过滤。
7.格式化器
ConsoleHandler类和FileHandler类可以生成文本和XML格式的日志记录。但是也可以自定义格式。继承Formatter类并使用setFormatter方法将格式化器安装到处理器中即可。
8.日志总结
(1)在创建应用程序的日志记录器时,最好和主程序的包名一致,为了方便起见,最好设置成静态域:
private static Logger logger = Logger.getLogger(包名);
(2)默认的日志配置文件将级别等于或高于INFO级别的所有日志消息输出到控制台,用户可以覆盖默认的配置文件,但是最好还是安装一个更加适合的自己定义的日志处理器,下面的代码确保将所有的消息记录到应用程序特定的文件中。
if (System.getProperty("java.util.logging.config.class") == null
&& System.getProperty("java.util.logging.config.file") == null)
{
try
{
Logger.getLogger("com.horstmann.corejava").setLevel(Level.ALL);
final int LOG_ROTATION_COUNT = 10;
Handler handler = new FileHandler("%h/LoggingImageViewer.log", 0, LOG_ROTATION_COUNT);
Logger.getLogger("com.horstmann.corejava").addHandler(handler);
}
catch (IOException e)
{
Logger.getLogger("com.horstmann.corejava").log(Level.SEVERE,
"Can't create log file handler", e);
}
}
(3)必须牢记的是,如果没有修改默认配置,那么所有级别为INFO、WARNING和SEVERE的消息都将被记录,因此最好只将对程序用户有意义的消息设置为这几个级别,将程序员想要的日志记录,设置为低级别的FINE是一个很好的选择。
(4)还要牢记的是,日志最大的用处是来记录异常,可以记录捕获的异常对象和抛出的异常对象。
Java基础(十七)日志(Log)的更多相关文章
- java基础(十七)----- 浅谈Java中的深拷贝和浅拷贝 —— 面试必问
假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short, ...
- java基础学习日志---File方法分析
package FunDemo; import java.io.File; import java.io.IOException; import java.util.Arrays; public cl ...
- java基础学习日志--String、StringBuffer方法案例
package StringDemo; import java.util.Arrays; /* * 常用String.StringBufer类的方法 */ public class Demo1 { p ...
- java基础学习日志--异常案例
package test7; public class InvalidScroreException extends Exception { public InvalidScroreException ...
- Java基础加强-日志
/*日志*/ 从功能上来说,日志API本身所需求的功能非常简单,只需要能够记录一段文本即可 API的使用者在需要记录时,根据当前的上下文信息构造出相应的文本信息,调用API完成记录.一般来说,日志AP ...
- java基础学习日志--Stirng内存案例
案例一: public class test1 { public static void mb_swap(String Str1,String Str2) { String temp=Str1; St ...
- 《手把手教你》系列基础篇(九十五)-java+ selenium自动化测试-框架之设计篇-java实现自定义日志输出(详解教程)
1.简介 前面宏哥一连几篇介绍如何通过开源jar包Log4j.jar.log4j2.jar和logback实现日志文件输出,Log4j和logback确实很强大,能生成三种日志文件,一种是保存到磁盘的 ...
- Java基础学习总结(40)——Java程序员最常用的8个Java日志框架
作为一名Java程序员,我们开发了很多Java应用程序,包括桌面应用.WEB应用以及移动应用.然而日志系统是一个成熟Java应用所必不可少的,在开发和调试阶段,日志可以帮助我们更好更快地定位bug:在 ...
- 第二十七节:Java基础面向对象-静态,单例模式,继承详情知识点
前言 Java基础面向对象-静态,单例模式,继承详情知识点.静态-static关键字,static变量,静态代码块,代码块(不加静态),对象创建过程,单例模式,继承. 静态-static关键字 // ...
- 7.20实习培训日志-Java基础程序设计结构
Java基础程序设计结构 在 Math 类中,为了达到最快的性能,所有的方法都使用计算机浮点单元中的例程,如果得到一个完全可预测的结果比运行速度更重要的话,那么就应该使用StrictMath类,它使用 ...
随机推荐
- Python日志产生器
Python日志产生器 写在前面 有的时候,可能就是我们做实时数据收集的时候,会有一个头疼的问题就是,你会发现,你可能一下子,没有日志的数据源.所以,我们可以简单使用python脚本来实现产生实时的数 ...
- Scrapy项目 - 实现豆瓣 Top250 电影信息爬取的爬虫设计
通过使Scrapy框架,掌握如何使用Twisted异步网络框架来处理网络通讯的问题,进行数据挖掘和对web站点页面提取结构化数据,可以加快我们的下载速度,也可深入接触各种中间件接口,灵活的完成各种需求 ...
- Python学习笔记整理总结【Django】:Model操作(一)
Model操作(一) 一.Django ORM基本配置 ORM:关系对象映射(Object Relational Mapping,简称ORM)db Frist:到目前为止,当我们的程序涉及到数据库相关 ...
- Springboot2.1.x配置Activiti7单独数据源问题
Springboot2.1.x配置Activiti7单独数据源问题 简介 最近基于最新的Activiti7配置了SpringBoot2. 简单上手使用了一番.发现市面上解决Activiti7的教程很少 ...
- ExcelDataReader read excel file
上篇文章向大家介绍了用DocumentFormat.OpenXml.dll读取excel的方法,这里再向大家介绍一种轻量级简便的方法,用的是Excel.dll,及ICSharpCode.SharpZi ...
- 使用.NET Core创建Windows服务(二) - 使用Topshelf方式
原文:Creating Windows Services In .NET Core – Part 2 – The "Topshelf" Way 作者:Dotnet Core Tut ...
- Kubernetes 系列(七):持久化存储StorageClass
前面的课程中我们学习了 PV 和 PVC 的使用方法,但是前面的 PV 都是静态的,什么意思?就是我要使用的一个 PVC 的话就必须手动去创建一个 PV,我们也说过这种方式在很大程度上并不能满足我们的 ...
- Dart数据类型
变量与常量: 变量: 使用var声明变量,可以赋予不同数据类型的值, 未初始化时默认值是null 使用final声明的变量只能被赋值一次 void main(){ var a; print(a); a ...
- java实现有道翻译爬虫
我的博文地址 https://www.cnblogs.com/lingdurebing/p/11618902.html 使用的库 1.commons-codec 主要是为了加密,可以直接用java原生 ...
- Spring IOC(3)----bean实例化
前面一节说到invokeBeanFactoryPostProcessors方法的调用来注册bean定义,这次来看看finishBeanFactoryInitialization这个方法实例化非懒加载的 ...