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. Java虚拟机工作原理

    Java虚拟机工作原理 首先我想从宏观上介绍一下Java虚拟机的工作原理.从最初的我们编写的Java源文件(.java文件)是如何一步步执行的,如下图所示,首先Java源文件经过前端编译器(javac ...

  2. Sublime安装Package Control插件

    一.简易安装 打开Sublime text的console.打开console的快捷时ctrl+,或者在菜单栏点击View->Show Sonsole`.打开后将下面的代码复制到console中 ...

  3. CentOS 中 YUM 安装桌面环境(转)

    使用 yum groupinstall 指令很容易就能安装上图形界面的桌面系统. 1. yum 的 group 指令 yum 可以以程序组的模式来安装成套的软件包.支持的软件包可以通过, # yum ...

  4. 组件之间使用Prop传递数据

    <div id="example"> <father></father> </div> <script src="h ...

  5. python多版本的pip共存问题解决办法

    python pip 多版本 问题情景 最开始学python的时候用的是py2,且一直用pip来安装库函数.后来py3出来了,所以就装上了,但是一装上出问题了,主要有两个主要的问题.下面将详细说明. ...

  6. flask mega-tutorial 1.0 documentation学习记录

    本文主要是记录在[用户登录]一节中出现的问题: 报错位置是在 if g.user is not None and g.user.is_authenticated(): return redirect( ...

  7. Kruskal算法的实现

    #include "stdio.h" #include "stdlib.h" struct edge { int m; int n; int d; }a[]; ...

  8. 机器学习:R语言中如何使用最小二乘法

    详细内容见上一篇文章:http://www.cnblogs.com/lc1217/p/6514734.html 这里只是介绍下R语言中如何使用最小二乘法解决一次函数的线性回归问题. 代码如下:(数据同 ...

  9. .net core 持续构建简易教程

    环境需求:jenkins和.netcore 由于jenkins在真机上的部署比较麻烦,所以在这里我使用基于jenkins的Docker,只要任何一台运行docker的环境都可以进行以下的操作. doc ...

  10. SQL case when 的使用总结

    在网上看到一篇关于case when语句的博客,写得很好,我这里是摘录的,还有我的一些体会,原博客地址:SQL Case when 的使用方法. Case具有两种格式.简单Case函数和Case搜索函 ...