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类,它使用 ...
随机推荐
- 基于 HTML5 和 WebGL 的地铁站 3D 可视化系统
前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...
- Eureka实战-1【Eureka Server在线扩容】
1.准备工作 PS:为了偷懒,每个pom文件都要依赖的公共依赖配置放在下面: <parent> <groupId>org.springframework.boot</gr ...
- How to setup Electrum testnet mode and get BTC test coins
For some reason we need to use BTC test coins, but how to set up the Bitcoin testnet wallet and get ...
- 通过实例快速掌握k8s(Kubernetes)核心概念
容器技术是微服务技术的核心技术之一,并随着微服务的流行而迅速成为主流.Docker是容器技术的先驱和奠基者,它出现之后迅速占领市场,几乎成了容器的代名词.但它在开始的时候并没有很好地解决容器的集群问题 ...
- 高效解决「SQLite」数据库并发访问安全问题,只这一篇就够了
Concurrent database access 本文译自:https://dmytrodanylyk.com/articles/concurrent-database/ 对于 Android D ...
- jQuery鼠标滑过横向时间轴效果
jQuery鼠标滑过横向时间轴效果---效果图: jQuery鼠标滑过横向时间轴效果---全部代码: <!DOCTYPE html> <html> <head> & ...
- 痞子衡嵌入式:史上最强i.MX RT学习资源汇总(持续更新中...)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MX RT学习资源. 类别 资源 简介 官方汇总 i.MXRT产品主页 恩智浦官方i.MXRT产品主页,最权威的资料都在这里,参考手 ...
- 《构建之法》项目管理&典型用户和场景
项目管理 PM的能力要求和任务: 1.观察.理解和快速学习能力 2.分析管理能力 3.一定的专业能力 4.自省的能力 在一个项目中,PM的具体任务: 1.带领团队形成团队的目标/远景,把抽象的目标 ...
- Java的数组的作业11月06日
动手动脑 实验一:了解for循环得到棋盘结构 (1) 程序: import java.io.*; public class QiPan { //定义一个二维数组来充当棋盘 private String ...
- 最长上升子序列 LIS nlogn
给出一个 1 ∼ n (n ≤ 10^5) 的排列 P 求其最长上升子序列长度 Input 第一行一个正整数n,表示序列中整数个数: 第二行是空格隔开的n个整数组成的序列. Output 最长上升子序 ...