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类,它使用 ...
随机推荐
- Dungeon Master POJ-2251 三维BFS
题目链接:http://poj.org/problem?id=2251 题目大意 你被困在了一个三维的迷宫,找出能通往出口的最短时间.如果走不到出口,输出被困. 思路 由于要找最短路径,其实就是BFS ...
- embedding技术
目录 word2vec 负采样 目标函数 反向梯度 层次softmax NPLM的目标函数和反向梯度 目标函数 反向梯度 GNN(图神经网络) deepwalk node2vec 附录 word2ve ...
- Mysql 笔记(一)
InnoDB存储引擎 mysql 存储引擎(好难用,看https://www.zybuluo.com/eqyun/note/27850) 简介 InnoDB是事务安全的MySQL存储引擎,从MySQL ...
- 虚拟机VMware14 pro下安装REHL5U11
1. 创建虚拟磁盘,自定义,磁盘类型选IDE,确保安装系统过程中只有一个物理光盘驱动/ISO镜像: 2. 安装VMware Tools 2.1 虚拟机>安装VMware Tools 2.2 在光 ...
- 将CDH中的hive和hbase相互整合使用
一..hbase与hive的兼容版本: hive0.90与hbase0.92是兼容的,早期的hive版本与hbase0.89/0.90兼容,不需要自己编译. hive1.x与hbase0.98.x或则 ...
- json与java对象的转换,以及struts2对json的支持,实现ajax技术
这两天学的东西有点多,今天抽个时间写下来,以此作为激励,这两天学了json,ajax,jQuery 一.使用第三方的工具java转换为json类型 首先就是java类型转换为json对象,首先要导入第 ...
- AVR单片机教程——数字IO寄存器
前两篇教程中我们学习了LED.按键.开关的基本原理,数字输入输出的使用以及两者之间的关系.我们用到了 pin_mode . pin_read 和 pin_write 这三个函数,实际上它们离最底层(至 ...
- Java基础学习笔记(二) - 面向对象基础
面向对象 一.面向对象概述 面向对象思想就是在计算机程序设计过程中,参照现实事物,将事物的属性特征.行为特征抽象出来,描述成计算机时间的设计思想.面向对象思想区别于面向过程思想,强调的是通过调用对象的 ...
- JavaScript 类型 检测
前言 ECMAScript中有5种数据类型,分别为Number,Boolean,Null,Undifined和String,以及一种复杂的数据类型Object(由名值对组成,是这门语言所有对象的基础类 ...
- VS Code配置Go语言开发环境(建议使用goland)
VS Code是微软开源的一款编辑器,插件系统十分的丰富.本文就介绍了如何使用VS Code搭建Go语言开发环境. VS Code配置Go语言开发环境 说在前面的话,Go语言是采用UTF8编码的,理论 ...