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. 通过Eclipse3.1以上启动Tomcat访问不到tomcat管理界面的问题(转载)

    通过Eclipse插件启动Tomcat的问题 默认分类   2009-10-23 15:54   阅读118   评论0   字号: 大  中  小 目前在通过Eclipse中插件启动Tomcat时遇 ...

  2. (6)简单说说java中的线程

    先甩出来两种创建线程的方法: private static int count = 100; public static void main(String[] args) { // 用继承Thread ...

  3. 【树莓派】Linux自动配置IP

    由于需要配置多台树莓派设备,但需要将IP配置为静态IP,而一台一台手动执行比较慢,所以写了一份脚本,sudo 执行即可. 将下面内容复制在家目录下,命名为auto.sh 然后执行 sudo sh au ...

  4. sticky footer布局,定位底部footer

    其作用就是当内容区域比较少时,让footer也能正常定位到底部,以前我们使用js来达到这种效果,其实用css也是完全可以的 <!DOCTYPE html> <html lang=&q ...

  5. javaScript对象学习笔记(一)

    一.什么是对象 对象: JavaScript的一种基本数据类型 对象是属性的无序集合,每个属性都是一个名/值对 JavaScript中的事物都是对象:字符串.数值.数组.函数... JavaScrip ...

  6. 20155206 2016-2017-2 《Java程序设计》第5周学习总结

    20155206 2016-2017-2 <Java程序设计>第5周学习总结 教材学习内容总结 Java中所有错误都会被打包为对象,运用try.catch,可以在错误发生时显示友好的错误信 ...

  7. Linux文件管理下

    文件操作 对于文件,我们可以读取(read),写入(write)和运行(execute).读取是从已经存在的文件中获得数据.写入是向新的文件或者旧的文件写入数据.如果文件储存的是可执行的二进制码,那么 ...

  8. Android IPC机制全解析<二>

    在AIDL文件中并不是所有的数据类型都可以使用,AIDL支持的数据类型如下: 基本数据类型(int.long.char.boolean.double等) String和CharSequence Lis ...

  9. ef code first

    , 网上有很多的ef  code first 的使用的方式,很乱,下面是我自己整理出来的,有什么不正确的地方还请指正,本人菜鸟一枚! 1.新建一个类库 =>引用 右击 管理NuGet程序包 添加 ...

  10. 爬虫入门系列(三):用 requests 构建知乎 API

    爬虫入门系列目录: 爬虫入门系列(一):快速理解HTTP协议 爬虫入门系列(二):优雅的HTTP库requests 爬虫入门系列(三):用 requests 构建知乎 API 在爬虫系列文章 优雅的H ...