1、Java应用中的日志功能

=================

一般的Java应用程序中都有记录日志的需求,目前主流的记录日志的方法是在应用程序中引入log4j,用log4j来生成日志。其实,JDK带有自己的日志系统,使用起来也很方便。

2、Java内置日志的使用方法

=================

JDK内置的日志系统相关的类都包含在java.util.logging这个包中。下面通过例子,由简到繁解释JDK内置日志系统的使用方法。

为了让应用程序有记录日志的能力,必须先在应用程序中获得一个日志记录器(logger),应用程序想记录的所有日志都发给这个日志记录器,日志记录器会帮助应用程序记录日志。

2.1 直接使用日志系统中的全局日志记录器来记录日志

----------------------------------------------------

下面的例子在Test应用中为了记录日志,获取了日志系统中的全局日志记录器,用这个全局日志记录器简单地记录了几个日志。

import java.util.logging.Logger;

public class Test
{
public static void main(String[] args)
{
Logger logger = Logger.getGlobal(); //获得日志系统中内置的全局日志记录器
//用获得的全局日志记录器logger记录七条日志记录
logger.severe("level.severe");
logger.warning("level.warning");
logger.info("level.info");
logger.config("level.config");
logger.fine("level.fine");
logger.finer("level.finer");
logger.finest("level.finest");
}
}

用javac Test.java命令编译Test应用后,用java Test命令运行Test应用,可以看到Test应用中用全局日志记录器输出的日志,如下:

在下面输出的日志中,每两行是一条日志记录(LogRecord),每条日志记录的第一行是此条日志记录输出的日期和时间,以及输出时所在的类和方法,下面一行是这条日志记录的日志级别(LogLevel)和具体的日志信息(log)。

由于上面的Test应用中输出了七条日志记录,所以运行Test应用后就输出了14行的日志信息,每两行是一条日志记录。

zzl@ZZL-PC /e/code/javacode/CoreJava
$ javac Test.java zzl@ZZL-PC /e/code/javacode/CoreJava
$ java Test
二月 24, 2017 6:29:14 下午 Test main
严重: level.severe
二月 24, 2017 6:29:14 下午 Test main
警告: level.warning
二月 24, 2017 6:29:14 下午 Test main
信息: level.info
二月 24, 2017 6:29:14 下午 Test main
配置: level.config
二月 24, 2017 6:29:14 下午 Test main
详细: level.fine
二月 24, 2017 6:29:14 下午 Test main
较详细: level.finer
二月 24, 2017 6:29:14 下午 Test main
非常详细: level.finest

2.2 使用应用专有的日志记录器来记录日志

-----------------------------------------

除了可以使用日志系统中的全局日志记录器之外,在实际的应用中,我们应该为每一个应用程序单独设置一个本应用程序自己的日志记录器。

可以使用如下语句为myapp应用创建一个名字为com.mycompany.myapp的日志记录器:

Logger myLogger = Logger.getLogger("com.mycompany.myapp");

从这里可以看出,日志记录器的名字和包名很类似,也是有层次结构的。但是它与包名的不同之处在于,对包来说,一个包和包含它的父包之间没有语义关系,但是日志记录器会共享一些属性。比如,名字为com.mycompany的日志记录器是名字为com.company.myapp的日志记录器的父亲,那么如果在日志记录器com.mycompany中设置了日志级别(LogLevel),日志记录器com.mycompany.myapp会继承这个日志级别的。

package com.mycompany;

import java.util.logging.Logger;
import java.util.logging.Level; public class MyApp
{
public static void main(String[] args)
{
//获取名字为com.mycompany.myapp的日志记录器
Logger logger = Logger.getLogger("com.mycompany.myapp");
//用获得的日志记录器记录七条日志记录
logger.severe("level.severe");
logger.warning("level.warning");
logger.info("level.info");
logger.config("level.config");
logger.fine("level.fine");
logger.finer("level.finer");
logger.finest("level.finest"); }
}

编译、运行以上的MyApp应用,会看到它输出了七条日志记录。

zzl@ZZL-PC /e/code/javacode/CoreJava
$ javac -d . com/mycompany/MyApp.java zzl@ZZL-PC /e/code/javacode/CoreJava
$ java com.mycompany.MyApp
二月 24, 2017 8:04:36 下午 com.mycompany.MyApp main
严重: level.severe
二月 24, 2017 8:04:36 下午 com.mycompany.MyApp main
警告: level.warning
二月 24, 2017 8:04:36 下午 com.mycompany.MyApp main
信息: level.info
二月 24, 2017 8:04:36 下午 com.mycompany.MyApp main
配置: level.config
二月 24, 2017 8:04:36 下午 com.mycompany.MyApp main
详细: level.fine
二月 24, 2017 8:04:36 下午 com.mycompany.MyApp main
较详细: level.finer
二月 24, 2017 8:04:36 下午 com.mycompany.MyApp main
非常详细: level.finest

以上的两个例子介绍了日志记录器的基本用法。

2.3 日志级别(LogLevel)

--------------------------

日志级别代表应用程序想要告诉外界的信息的不同的严重程序,比如特别关键的,不是那么要紧的等。JDK自带的日志系统中的每一个日志记录器都可以有7个日志级别(LogLevel),从高级到低级,它们分别是:SEVERE、WARNING、INFO、CONFIG、FINE、FINER、FINEST。在创建好一个日志记录器后,默认设置的日志级别是INFO,这表示这个日志记录器可以输出INFO及其以上级别的日志,也就是可以输出SEVER、WARNING、INFO这三个级别的日志记录,但是不能输出CONFIG、FINE、FINER、FINEST这四个级别的日志记录,即使在程序调用了相应的输出语句,也不会输出对应级别的日志。

具体见下面的例子。

package com.mycompany;

import java.util.logging.Logger;
import java.util.logging.Level; public class MyApp
{
public static void main(String[] args)
{
//获取名字为com.mycompany.myapp的日志记录器
Logger logger = Logger.getLogger("com.mycompany.myapp");
//用获得的日志记录器记录七条日志记录
//每一个Logger的默认级别是INFO,所以下面的前三条可以输出
//后四条无法输出
logger.severe("level.severe");
logger.warning("level.warning");
logger.info("level.info");
logger.config("level.config");
logger.fine("level.fine");
logger.finer("level.finer");
logger.finest("level.finest"); }
}

编译、运行之后,可以看到如下输出:

zzl@ZZL-PC /e/code/javacode/CoreJava
$ javac -d . com/mycompany/MyApp.java zzl@ZZL-PC /e/code/javacode/CoreJava
$ java com.mycompany.MyApp
二月 24, 2017 8:18:50 下午 com.mycompany.MyApp main
严重: level.severe
二月 24, 2017 8:18:50 下午 com.mycompany.MyApp main
警告: level.warning
二月 24, 2017 8:18:50 下午 com.mycompany.MyApp main
信息: level.info zzl@ZZL-PC /e/code/javacode/CoreJava
$

可以看到在INFO级别之下的日志记录都没有输出,只输出了前三个级别的日志记录。

当然可以在日志系统的配置文件中为日志记录器设置日志级别,对于com.mycompany.myapp这个日志记录器,可以在jre/lib/logging.properties中这样设置日志级别,在配置文件的最后,加上如下一句即可:

com.mycompany.myapp.level = FINE

此外,除了日志记录器有日志级别外,处理器也有自己的日志级别,而且处理器的日志级别比日志记录器的日志级别优先级更高,具体见下面一节“日志处理器”。

2.4 日志处理器(Handler)

---------------------------

日志处理器是日志记录实际被发送到的目的地,可以是控制台(console)、文件或者网络服务器。常用的三个系统自带日志处理器,分别是:代表控制台的ConsoleHandler、代表文件的FileHandler、代表网络服务器的SocketHandler。

在创建了一个日志记录器之后,如果没有显式地为其指定处理器,默认情况下,它会将日志记录发送到ConsoleHandler,并由ConsoleHandler输出到System.err中。需要注意的日志记录器除了会把日志记录发送到自己的处理器去,还会把日志记录发送到它的父日志记录器的处理器中去。

日志处理器和日志记录器一样,也有自己的日志级别。默认的ConsoleHandler的日志级别是

java.util.logging.ConsoleHandler.level = INFO

在自己的程序中,可以为自定义的日志记录器指定自己的日志处理器。参见下面的例子:

package com.mycompany;

import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.logging.Handler;
import java.util.logging.ConsoleHandler;
import java.util.logging.FileHandler;
import java.io.*; public class MyApp
{
public static void main(String[] args)
{
//获取名字为com.mycompany.myapp的日志记录器
Logger logger = Logger.getLogger("com.mycompany.myapp");
logger.setLevel(Level.ALL); //设置日志管理器的日记级别
logger.setUseParentHandlers(false); //为com.mycompany.myapp这个日志记录器设置一个ConsoleHandler处理器
Handler handler = new ConsoleHandler();
handler.setLevel(Level.ALL); //设置处理器的日志级别
logger.addHandler(handler); //再为com.mycompany.myapp这个日志记录器设置一个FileHandler处理器
FileHandler handler2 = null;
try
{
handler2= new FileHandler();
logger.addHandler(handler2);
}
catch (IOException e)
{
e.printStackTrace();
} logger.severe("level.severe");
logger.warning("level.warning");
logger.info("level.info");
logger.config("level.config");
logger.fine("level.fine");
logger.finer("level.finer");
logger.finest("level.finest");
}
}

上面的程序在编译、运行之后,它会把日志同时送到Console和File中。对于FileHandler,默认情况下,它会把日志记录存到一个名为javan.log(n是一个数字,当多次运行同一个应用程序时,每次n会不一样,这样每次运行的日志就会记录在不同的文件中)的xml文件中,该文件默认情况下位于user.home属性所指的目中,本例子中生成的log文件是c:\users\user1\java0.log。

这些就是日志处理器的基本知识,当然关于日志处理器还有更多可以了解的细节,请参考java.util.logging包中具体API的说明文档。

3、日志系统的配置文件

===============

日志系统的各种属性,比如日志级别等,可以通过日志系统的配置文件来修改。默认情况下,日志系统的配置文件是JAVA_HOME/jre/lib/logging.properties。如果想要为应用程序设置一个独有的配置文件,可以在启用应用程序的时候用java.util.logging.config.file属性来设置,比如,像下面这样:

java -Djava.util.logging.config.file=configFile MyApp

当然,如果想要修改日志系统的默认配置,可以直接编辑jre/lib/logging.properties文件。

编写自己的日志配置文件,可以参考jre/lib/logging.properties文件进行,这里不说了。

4、其他问题

=======

JDK自带的日志系统还有很多细节,这里介绍是一个基本知识,懂了这些就可以用起来,如果想更深入地了解,可以参考java.util.logging包的文档。另外值得注意的地方就是要在学习的过程中,搞清楚基本概念的含义。一定要分清楚,日志记录器、日志记录、日志处理器、日志级别、日志系统的默认配置文件等。

JDK内置日志系统的更多相关文章

  1. ASP.NET Core 2.1 : 十二.内置日志、使用Nlog将日志输出到文件

    应用离不开日志,虽然现在使用VS有强大的调试功能,开发过程中不复杂的情况懒得输出日志了(想起print和echo的有木有),但在一些复杂的过程中以及应用日常运行中的日志还是非常有用. ASP.NET ...

  2. ThinkPHP内置日志记录

    ThinkPHP内置日志记录日志记录http://document.thinkphp.cn/manual_3_2.html#log 日志的处理工作是由系统自动进行的,在开启日志记录的情况下,会记录下允 ...

  3. JDK内置性能监测工具使用

    Java自带的性能监测工具用法简介——jstack.jconsole.jinfo.jmap.jdb.jsta.jvisualvmJDK内置工具使用 一.javah命令(C Header and Stu ...

  4. JDK内置工具命令

    javap Java反编译工具,主要用于根据Java字节码文件反汇编为Java源代码文件用法:javap 用法 描述 javap -help —help -? 输出此用法消息 javap -versi ...

  5. 观察者模式 - Java 实现1(使用JDK内置的Observer模式)

    使用JDK内置的观察者模式 1. 可观察者(主题) 被观察的主题继承 Observable 对象, 使用该对象的调用 notifyObservers() 或 notifyObservers(arg) ...

  6. MyBatis 内置日志工厂基于运行时自省机制选择合适的日志工具

    mybatis – MyBatis 3 | 日志 http://www.mybatis.org/mybatis-3/zh/logging.html MyBatis 内置日志工厂基于运行时自省机制选择合 ...

  7. Future模式的学习以及JDK内置Future模式的源码分析

    并发程序设计之Future模式 一).使用Future模式的原因 当某一段程序提交了一个请求,期待得到一个答复,但服务程序对这个请求的处理可能很慢,在单线程的环境中,调用函数是同步的,必须等到服务程序 ...

  8. 第七节:Asp.Net Core内置日志和整合NLog(未完)

    一. Asp.Net Core内置日志 1. 默认支持三种输出方式:控制台.调试(底部输出窗口).EventSource,当然也可以在Program类中通过logging.ClearProviders ...

  9. adb将Apk内置到系统中(system/priv-app)

    https://blog.csdn.net/starhosea/article/details/78697007 so文件的处理是目前遇到过的问题.文章中解释了. 正文: 有时候我们在Android ...

随机推荐

  1. ZJOI2017 Day3 滚粗记

    私のZJOI Day3 2017-3-21 07:52:53 今天,考了人生当中的第一次省选(虽然只是普及组三等奖但仍然有幸能体会一下).据胡老师说,这就是来体验一下被大神虐--真的是这样,听课听不懂 ...

  2. centos6.7编译安装mysql5.7.17

    centos6.7编译安装mysql5.7.17 2017-03-24 09:57:15 提示:mysql5.7.17和之前5.56以前的版本安装不一样,需要用cmake 另外,看本文档的mysql编 ...

  3. .net Core 1.0.1 下的Web框架的的搭建过程step by step

    环境:ubuntu+VScode  数据库:mysql ,ORM框架:chloe 官网 看完本篇文章你能学会 在Vscode下创建项目,一些基础的命令 ,以及得到一个配置文件的简单读取实例 1,在VS ...

  4. HTML5 之文件操作(file)

    前言 在 HTML 文档中 <input type="file"> 标签每出现一次,一个 FileUpload 对象就会被创建. 该元素包含一个文本输入字段,用来输入文 ...

  5. javascript重修之书(一):如何判断变量的数据类型

    javascript重修之书(一):如何判断变量的数据类型 一:检测值类型 基本类型:(Undefined.Null.Boolean.Number和String) javascript之所以被称为一门 ...

  6. vuejs单一事件管理组件间的通信

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. sql server删除主键约束所想到的

    从网上找到了下面一段代码: declare @Pk varchar(100);select @Pk=Name from sysobjects where Parent_Obj=OBJECT_ID('表 ...

  8. SQL Server 获取本周,本月,本年等时间内记录

    datediff(week,zy_time,getdate())=0 //查询本周 datediff(month,zy_time,getdate())=0 //查询本月 本季:select * fro ...

  9. C#研究OpenXML之路(4-使用第三方库)

    一.悲催的OpenXML操作 学习并使用了一段时间的OpenXML,感觉用这个来操作Excel文件真是一件非常悲催的事情,由于我自己比较熟悉Excel COM的操作,但到了OpenXML中发现,之前所 ...

  10. Java设计模式面试题 01 - 六大原则

    Java设计模式面试题 01 - 六大原则 1. 单一职责原则 Single Responsibility Principle SRP原则 分清职责,接口一定要做到单一职责,方法也要做到,类尽量做到 ...