Java日志框架之JUL(java util logging)详解
定义:
JUL全称Java util logging,是java原生的日志框架,使用时不需要另外引入第三方类库,相对于其他框架使用方便,学习简单,能够在小型的应用中灵活使用。
架构:
- Application:我们的程序应用。
- LogManager:管理Logger,是个单例Bean。
- Logger:日志记录器,我们的应用程序通过获取日志记录器Logger对象,调用其API来发布日志信息,Logger通常是应用程序访问日志系统的入口。
- Handler:日志处理器,每个Logger会关联持有多个Handler,Logger会把日志交给Handler进行处理,由Handler负责日志记录。Handler在这里是一个抽象,其具体实现决定了日志输出的位置,比如控制台,文件等。
- Formattter:日志格式转化器,负责对日志的格式进行处理。决定了输出的日志的最终形式。
- Level:每条日志信息都有一个关联的日志级别,该级别处理指导了日志信息的重要性。我们可以将Level作用于Logger和Handler上。以便于我们过滤消息。
- Filter:过滤器,根据规则过滤掉某些日志信息。
总体流程:
- 初始化LogManager,加载logging.properties配置文件,添加Logger到LogManager中。
- 从单例Bean LogManager获取Logger。
- 设置日志级别Level。
- Handler处理日志输出。
- Formatter处理日志格式。
日志的级别:
JUL日志级别由类java.util.logging.Level记录,总共有七个日志级别,由高到低分别是:
SEVERE //错误信息,一般是记录导致系统终止的信息。
WARNING //警告信息,一般记录程序的问题,该问题不会导致系统终止,但是却值得我们关注。
INFO // 一般信息,一般记录一些连接信息,访问信息等。(这是JUL的默认级别)
CONFIG // 一般记录加载配置文件等日志信息。
FINE // Debug日志信息,一般记录程序一般运行的状态。执行的流程参数的传递等信息。
FINER //与FINE 类似,只是记录的颗粒度要高一些。
FINEST //与上面两个类似,只是记录的颗粒度要高一些。
还有两个特殊的级别:
OFF: 可用来关闭日志信息,不输出任何级别的日志。
ALL: 记录所有级别的日志信息。
当Logger或者Handler设置了某一日志级别,低于该级别的日志信息将不会被记录。
入门案例:
public class JULDemo {@Testpublic void testHelloWorld(){//创建日志记录器,传入参数是日志记录器的名称Logger logger = Logger.getLogger("juldemo.JULDemo");//记录severe级别信息logger.severe("severe信息");//记录warning级别信息logger.warning("warning信息");logger.info("info信息");logger.config("config信息");logger.fine("fine信息");logger.finer("finer信息");logger.finest("finest信息");}
}
输出结果:
因为默认的日志级别是INFO,所以比INFO级别低的 CONFIG、FINE、FINER、FINEST的日志记录消息没有记录。
自定义日志级别:
@Testpublic void testCustomLogLevel(){//创建日志记录器,传入参数是日志记录器的名称Logger logger = Logger.getLogger("juldemo.JULDemo");//创建一个输出到控制台的handlerConsoleHandler consoleHandler = new ConsoleHandler();//设置handler的日志级别为ALL,输出全部日志。consoleHandler.setLevel(Level.ALL);//把handler添加到logger中logger.addHandler(consoleHandler);//logger也设置日志级别为ALLlogger.setLevel(Level.ALL);//logger设置不使用父logger的handler,不然日志会重复记录。此处后面会讲logger.setUseParentHandlers(false);//记录severe级别信息logger.severe("severe信息");//记录warning级别信息logger.warning("warning信息");logger.info("info信息");logger.config("config信息");logger.fine("fine信息");logger.finer("finer信息");logger.finest("finest信息");}
结果:
七个级别的日志信息都输出了。
Logger之间的父子关系:
JUL的Logger之间会存在父子关系,这种父子关系通过树状关系存储。JUL在初始化时会创建一个顶层的RootLogger作为所有Logger的父Logger。RootLogger作为树结构的根节点,Logger之间的关系通过树路径来关联。Logger记录器是用名称作为标志的。子Logger和默认使用父Logger的Handler。
Logger的父子关系默认是通过名子的层级关系来确定的。层级关系用 . 号分开。
也可以通过手动设置父Logger。
@Testpublic void testLoggerParent(){//创建一个名称为aaa的loggerLogger logger1 = Logger.getLogger("aaa");//创建一个名称为aaa.bbb的loggerLogger logger2 = Logger.getLogger("aaa.bbb");//创建一个名称为aaa.bbb.ccc的loggerLogger logger3 = Logger.getLogger("aaa.bbb.ccc");//此时logger3的父Logger是logger2, logger2的父logger是logger1//判断logger3的父Logger是不是logger2System.out.println(logger3.getParent() == logger2);//判断logger2的父logger是不是logger1System.out.println(logger2.getParent() == logger1);//logger1的父节点是顶级Logger RootLoggerSystem.out.println("logger1的父logger是 " + logger1.getParent());//RootLogger的父LoggerSystem.out.println("RootLogger的父Logger是 " + logger1.getParent().getParent());//手动设置父Loggerlogger3.setParent(logger1);//判断设置是否成功System.out.println(logger3.getParent() == logger1);}
执行结果:
子Logger默认会使用父Logger的Handler:
@Testpublic void testUserParentHandler() throws IOException {//创建一个名为aaa的loggerLogger logger1 = Logger.getLogger("aaa");//创建一个名为aaa.bbb的logger,父Logger是handlerLogger logger2 = Logger.getLogger("aaa.bbb");//创建一个handlerConsoleHandler consoleHandler = new ConsoleHandler();//把handler添加到logger1和logger2中。logger1.addHandler(consoleHandler);logger2.addHandler(consoleHandler);//使用logger进行日志输出//记录severe级别信息logger2.severe("severe信息");//记录warning级别信息logger2.warning("warning信息");logger2.info("info信息");logger2.config("config信息");logger2.fine("fine信息");logger2.finer("finer信息");logger2.finest("finest信息");}
结果:
分析:
每个级别的日志信息输出了三次,因为logger2使用了父Logger logger1 ,父Logger的父Logger RootLogger、还有自身的handler共三个handler,所以日志会输出三倍。
使用logger2.setUseParentHandlers(false); 设置不使用父Logger的Handler。
结果:
只用了自身的handler。
使用FileHandler和SimpleFormatter
@Testpublic void testFileHandler(){Logger logger = Logger.getLogger("juldemo.JULDemo");logger.setLevel(Level.ALL);try {//创建一个输出到文件的handler,第一个参数是生成文件名的pattern,第二个参数是是否已追加的方式输出到文件,默认falseFileHandler fileHandler = new FileHandler("D:\\logs\\java%u.log",true);//创建一个SimpleFormatter,输出格式SimpleFormatter formatter = new SimpleFormatter();//设置formatterfileHandler.setFormatter(formatter);//设置日志级别fileHandler.setLevel(Level.ALL);//把handler添加到loggerlogger.addHandler(fileHandler);//设置不使用父Logger的handlerlogger.setUseParentHandlers(false);logger.severe("severe信息");//记录warning级别信息logger.warning("warning信息");logger.info("info信息");logger.config("config信息");logger.fine("fine信息");logger.finer("finer信息");logger.finest("finest信息");} catch (IOException e) {e.printStackTrace();}}
输出到文件:
配置文件详解:
上面的使用方式都是使用硬编码方式进行配置,现在介绍配置文件配置。
默认的配置文件:
$JAVA_HOME/jre/lib/logging.properties
默认配置:
#配置RootLogger的Handler,多个用逗号分隔。默认只有一个输出到控制台的handler
handlers= java.util.logging.ConsoleHandler#配置RootLogger的日志级别,默认是INFO
.level= INFO#配置FileHandler
#配置FileHandler的生成文件路径以及文件名的生成方式
java.util.logging.FileHandler.pattern = %h/java%u.log
#默认一个文件最多50000条日志记录
java.util.logging.FileHandler.limit = 50000
#默认生成一个文件
java.util.logging.FileHandler.count = 1
#默认使用XMLFormatter格式器
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter#ConsoleHandler的日志级别默认是INFO
java.util.logging.ConsoleHandler.level = INFO
#ConsoleHandler的默认格式化器时SimpleFormatter
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
我们可以使用自定义的文件或者修改默认配置文件进行配置。
#配置RootLogger的Handler,有java.util.logging.ConsoleHandler,java.util.logging.FileHandler
handlers= java.util.logging.ConsoleHandler,java.util.logging.FileHandler#配置RootLogger的日志级别ALL
.level= ALLjava.util.logging.FileHandler.pattern = D:/logs/java%u.log
#默认一个文件最多50000条日志记录
java.util.logging.FileHandler.limit = 50000
#设置FileHandle的日志级别为ALL
java.util.logging.FileHandler.level= ALL#配置生成一个文件
java.util.logging.FileHandler.count = 1
#配置使用SimpleFormatter格式器
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
#配置追加模式
java.util.logging.FileHandler.append=true#ConsoleHandler的日志级别默认是INFO
java.util.logging.ConsoleHandler.level = ALL
#ConsoleHandler的默认格式化器时SimpleFormatter
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter#设置日志格式
java.util.logging.SimpleFormatter.format= %1$tc %2$s%n%4$s: %5$s%6$s%n
使用:
@Testpublic void testCustomConfig(){LogManager logManager = LogManager.getLogManager();try {logManager.readConfiguration(this.getClass().getClassLoader().getResourceAsStream("logging.properties"));Logger logger = Logger.getLogger("juldemo.JULDemo");logger.severe("severe信息");//记录warning级别信息logger.warning("warning信息");logger.info("info信息");logger.config("config信息");logger.fine("fine信息");logger.finer("finer信息");logger.finest("finest信息");} catch (IOException e) {e.printStackTrace();}}
结果:
并且生成了日志文件,这里就不贴了。
如果不想用logmanager加载指定配置文件的话,就直接修改$JAVA_HOME/jre/lib/logging.properties文件也行。
Java日志框架之JUL(java util logging)详解相关推荐
- Java日志框架学习--JUL和Log4j--上
Java日志框架学习--JUL和Log4j--上 引言 日志框架 市面流行的日志框架 日志门面和日志框架的区别 JUL JUL简介 JUL组件介绍 实际使用 Logger之间的父子关系 默认配置文件位 ...
- java日志框架(一)JUL 学习 ,这个是什么,他在代码中如何使用,一篇文章讲清楚
这里写目录标题 JUL 是什么 JUL组件介绍 代码中如何使用(控制台输出) 日志级别 自定义输出级别 输出日志到文件(磁盘文件中) 日志对象父子关系 配置文件 使用方法总结 JUL 是什么 JUL全 ...
- Java自动化测试框架-12 - TestNG之xml文件详解篇 (详细教程)
1.简介 现在这篇,我们来学习TestNG.xml文件,前面我们已经知道,TestNG就是运行这个文件来执行测试用例的.通过本篇,你可以进一步了解到:这个文件是配置测试用例,测试套件.简单来说,利用这 ...
- Java日志框架学习笔记
Java日志框架学习笔记 文章目录 0 主流Java日志框架 1 log4j 1.1 理论知识 1.1.1 Loggers日志记录器 1.1.2 Appenders输出端 1.1.3 Layout日志 ...
- 学习Java日志框架之——搞懂JUL(java.util.logging)
文章目录 系列文章目录 一.JUL简介 二.JUL组件介绍 三.代码实例 1.入门案例 2.日志级别 (1)默认日志级别源码分析 3.自定义日志级别 4.将日志输出到文件中 5.Logger的父子关系 ...
- java日志框架JUL、JCL、Slf4j、Log4j、Log4j2、Logback 一网打尽
为什么程序需要记录日志 我们不可能实时的24小时对系统进行人工监控,那么如果程序出现异常错误时要如何排查呢?并且系统在运行时做了哪些事情我们又从何得知呢?这个时候日志这个概念就出现了,日志的出现对系统 ...
- Java日志框架 -- 日志框架介绍、日志门面技术、JUL日志(JUL架构、JUL入门示例、JUL日志级别、JUL日志的配置文件)
1. 日志的概念 日志文件是用于记录系统操作事件的文件集合,可分为事件日志和消息日志.具有处理历史数据.诊断问题的追踪以及理解系统的活动等重要作用. 2. Java日志框架 问题: 控制日志输出的内容 ...
- Java 日志框架 JUL
文章目录 日志文件的重要性 常见日志框架 什么是JUL JUL架构介绍 入门案例 JUL日志级别 Logger之间的父子关系 日志的配置文件 日志原理解析 日志文件的重要性 做开发最怕的就是线上系统出 ...
- 可能是全网最全,JAVA日志框架适配、冲突解决方案,可以早点下班了!
点击上方"Java基基",选择"设为星标" 做积极的人,而不是积极废人! 每天 14:00 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | Java ...
最新文章
- python find(urlopen.read())_Python小白必看之urlopen()详解
- CSS中position详解与常见应用实现
- STM32开发板入门教程(十三) - SPI模式读写SD卡
- 《JavaWeb从入门到改行》注册时向指定邮箱发送邮件激活
- 了解招聘中的这些潜台词,找工作少走弯路
- 局域网Ubuntu与WinXP实现文件共享
- HTML网站右键禁用F12代码 屏蔽审查元素 防止修改页面代码
- 微信生态圈盈利模式分析
- 机器学习中二分类逻辑回归的学习笔记
- 阿里云专家带你揭秘云计算数据底座——对象存储
- Rust : stevenbai.top学习站点
- 中国移动 · 边缘计算技术白皮书 | PDF下载
- mysql 获取百分比函数,并对结果保留2位小数。
- 分位数回归--基于R
- 格式工厂 wav 比特率_鸡娃常用工具系列一格式工厂(音频转换软件)
- 开源软件、自由软件、Copyleft、CC都是啥,傻傻分不清楚?
- 用python实现监听微信撤回消息
- 新手入门,想用VB给班上写一个自动播放上下课铃声的程序,求教
- 一个程序员的自白:我为什么写博客
- CF1005A Tanya and Stairways
热门文章
- Spring框架学习笔记05:Spring AOP基础
- 数据库笔记08:实现索引
- 【NOI2016】网格,离散化+求割点
- 中职计算机应用基础微课获奖视频,浅谈微课在中职计算机应用基础教学中的应用...
- linux配置iscsi无账号密码,linux配置ISCSI服务器的方法
- 【英语学习】【医学】无机化学 - 化合物命名(1) - 离子化合物
- python中template是什么意思啊_Python中Template使用的一个小技巧
- c#ref和out的相同点_C#中使用ref和out一点认识!
- cve-2020-0796_CVE20200796 | Windows SMBv3客户端/永痕之黑漏洞复现
- CCS 3.3中统计程序运行的时间