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类,它使用 ...
随机推荐
- Hbase入门(二)——安装与配置
本文讲述如何安装,部署,启停HBase集群,如何通过命令行对Hbase进行基本操作. 并介绍Hbase的配置文件. 在安装前需要将所有先决条件安装完成. 一.先决条件 1.JDK 和Hadoop一样, ...
- Maven 梳理 -聚合与继承
一.聚合 如果我们想一次构建多个项目模块,那我们就需要对多个项目模块进行聚合 1.1.聚合配置代码 1 <modules> 2 <module>模块一</module&g ...
- Spring 梳理-AOP
界面应用场景 日志.声明式事务.安全.缓存 AOP功能演化图 图片引用地址:https://www.cnblogs.com/best/p/5679656.html AOP设计模式-代理模式 静态代理: ...
- 从ASP.Net Core Web Api模板中移除MVC Razor依赖项
前言 :本篇文章,我将会介绍如何在不包括MVC / Razor功能和包的情况下,添加最少的依赖项到ASP.NET Core Web API项目中. 一.MVC VS WebApi (1)在ASP. ...
- 阿里云服务器CentOS6.9安装JDK
1:首先查看系统有没有自带jdk rpm -qa | grep java 2:将存在的一一卸载 rpm -ev java-1.7.0-openjdk-1.7.0.141-2.6.10.1.el6_9. ...
- 无法访问hadoop102:50070
~~~瞎忙了好久好久~~~ 第一次弄Hadoop完全式配置,全部跟着教程把操作做完之后,来到本机运行hadoop102:50070无法访问.... 以为是自己配错了就开始玩起了“找不同”游戏,玩得差不 ...
- 利用CSS制作图形效果
前言 关于如何使用CSS来制作图形,比如说圆形,半圆形,三角形等的相关教程还是挺多的,今天我主要想解释一下里面一些demo的实现原理,话不多说,开始吧 以下所有内容只使用一个HTML元素.任何类型 ...
- redis查找大key
redis中查找出比较大的key 下面直接上代码 (请在测试机上测试) #!/usr/bin/env python import sys import redis def check_big_key( ...
- [WP8.1]给Pivot的Header加上颜色
先上个效果图 以前想实现这个给Pivot加颜色时只找到8的,通过参考8的实现方式,8.1的实现如下,在Pivot的样式上做一些修改,如下图的红框处 另外如果要改Pivot的Header里文字的颜色又要 ...
- pinpoint1.8.5安装及使用指南
简介 pinpoint是开源在github上的一款APM监控工具,它是用Java编写的,用于大规模分布式系统监控.它对性能的影响最小(只增加约3%资源利用率),安装agent是无侵入式的. 各大APM ...