Java的标准日志
虽然开源社区有很多优秀的日志框架,但我们学习标准的java日志框架是为了更好的理解其他框架啊(近期项目要用ELK)
看自己以前写的Log4J简直不忍直视啊啊啊啊,那时还感觉自我良好
1. 为什么要使用日志
我们都试过在代码中插入System.out.println方法来进行调试吧,当找出问题根源后就把插入的print语句删除,若又出现问题则需再次插入这些语句,如此反复。那么日志API就是为了解决这个问题而设计的,使用日志的优势:
- 可随时开闭日志记录,还能分级别筛选日志,并且保留日志代码开销很小
- 日志可简单地被定向到控制台显示,文件保存,或者网络传输
- 日志可格式化其记录的格式
- 日志可由配置文件控制
- 日志利于日后错误的定位
2. Logger
java有标准的日志系统,在java.util.logging包下。因为它不太好用,就出现了各种补充的日志框架,其实我看着也还行,能够应付我的日常使用了
2.1 示例
看不懂没关系,码入下面的程序就可以看到日志记录的情况了
public class loggerTest {
public static void main(String[] args) {
// 1. 获得一个全局的日志记录器
Logger global = Logger.getGlobal();
// 2. 日志有七个级别,从高到低分别是:Sever、Warning、Info、Config、Fine、Finer、Finest
// 默认级别为INFO,意思只输出前三个级别的记录
global.info("INFO MSG");
global.warning("WARNING MSG");
global.severe("SERVE MSG");
// 3. 可通过setLevel来设置日志级别,来限制其他级别的记录
global.setLevel(Level.WARNING);
}
}
// 控制台输出
// 七月 23, 2021 8:57:17 下午 logging.loggerTest main
// 信息: INFO MSG
// 七月 23, 2021 8:57:17 下午 logging.loggerTest main
// 警告: WARNING MSG
// 七月 23, 2021 8:57:17 下午 logging.loggerTest main
// 严重: SERVE MSG
2.2 日志的记录器
记录器是用来 "记录"、定位日志记录的,一般我们不想把所有的日志都记录到一个全局记录器上,那么我们就可以自定义一个记录器
public class loggerTest {
// 未被任何变量引用的日志记录器可能被垃圾回收掉,所以采用了静态变量的方式
private static final Logger myLogger = Logger.getLogger("com.howl.logger.loggerTest");;
public static void main(String[] args) {
myLogger.info("this is my logger msg");
}
}
日志的记录器有类似于
包名继承
的层次结构,父记录器设置了日志级别,那么子记录器就会继承这个级别,所以日志框架的记录器命名都以类名限定
2.3 日志配置
java有个叫日志管理器的东西专门来管配置的,java9的配置文件是在 jre/conf/logging.properties。日志管理器在虚拟机启动时就初始化,就是在main方法执行之前
我们可以在启动项目时就指定日志的配置文件:java -Djava.util.logging.config.file=新文件名
也可在项目运行时用System.setProperty("java.util.logging.config.file", file)指定配置文件,并LogManager.getLogManager().readConfiguration()重新初始化日志管理器生效配置(食用配置文件形式不好,其他日志框架的配置在项目根目录,会自动读取的)
2.4 日志的处理器
处理器是用于处理记录的(也有日志级别),记录器有ConsoleHandler、FileHandler、SocketHandler。默认情况下记录器将记录发到ConsoleHandler然后输出,如想输出到其他地方就添加其他的处理器。具体流程的话,就是记录器将记录发给自己的处理器和父记录器的处理器,全部记录器的最终祖先是名为 "" 的一个记录器,它有一个ConsoleHandler,所以默认的日志记录都输出到控制台
public class loggerTest {
// 静态变量放垃圾回收
private static final Logger myLogger = Logger.getLogger("com.howl.logger.loggerTest");;
public static void main(String[] args) throws IOException {
// 文件、控制台处理器
FileHandler fileHandler = new FileHandler();
ConsoleHandler consoleHandler = new ConsoleHandler();
myLogger.addHandler(consoleHandler); // 这条语句在控制台输出了两次
myLogger.addHandler(fileHandler);
myLogger.info("add two handler");
}
}
// 控制台输出
// 七月 23, 2021 9:31:26 下午 logging.loggerTest main
// 信息: add two handler
// 七月 23, 2021 9:31:26 下午 logging.loggerTest main
// 信息: add two handler
怎么会有两条记录?
fileHander是输出文件的(不在控制台输出),日志文件默认保存在用户目录下的javaN.log中,其中N是唯一编号,默认格式为XML
上面说的myLogger发给自己处理器consoleHandler输出,也会发给父处理器输出,所以有两条,可配置userParentHandlers = false,取消使用父处理器
2.5 日志的过滤器
记录器,处理器只能根据日志级别来过滤,而过滤器则更加自由多样化。我们需要实现Filter接口(注意是Logger下的接口)然后将其交给记录器(是记录器啊,下面标题2.6的才是交给处理器)
public class loggerTest {
private static final Logger myLogger = Logger.getLogger("com.howl.logger.loggerTest");;
public static void main(String[] args) throws IOException {
// 过滤器
Filter filter = new Filter() {
@Override
public boolean isLoggable(LogRecord record) {
return record.getMessage().contains("HAHA"); // 记录包含了HAHA就不过滤
}
};
myLogger.setFilter(filter);
myLogger.info("add two handler");
myLogger.info("i am HAHA");
}
}
// 控制台输出
// 七月 23, 2021 9:43:27 下午 logging.loggerTest main
// 信息: i am HAHA
2.6 日志的格式化器
格式化器顾名思义是用来格式化记录的,看需要生成什么样格式的记录,我的话就在日志前加点东西就好了。也是需要实现format接口的,当然记录的格式化操作是交给处理器的
public class loggerTest {
private static final Logger myLogger = Logger.getLogger("com.howl.logger.loggerTest");;
public static void main(String[] args) throws IOException {
// 格式化器
Formatter formatter = new Formatter() {
@Override
public String format(LogRecord record) {
return "这里是格式化器: "+ record.getMessage() + "\n\n";
}
};
ConsoleHandler consoleHandler = new ConsoleHandler();
consoleHandler.setFormatter(formatter);
myLogger.addHandler(consoleHandler);
myLogger.info("i am HAHA");
}
}
// 控制台输出
// 这里是格式化器: i am HAHA
//
// 七月 23, 2021 9:52:58 下午 logging.loggerTest main
// 信息: i am HAHA
3. java日志的发展史
- Apache 的 log4j 日志框架最早出现(可用配置文件管理日志,并动态加载)
- java1.4 后面才添加的标准日志库 java.util.logging(JUL)
- Apache 推出日志门面Apache Commons Logging(JCL,提供了一套日志接口,兼容上面二者)
- 再然后 JCL 的作者弄了个新的日志门面 slf4j,并提供了其组件实现 logback
- 最后 Apache 重写log4j,推出 log4j2
- 因为 slf4j 门面后面才出现,所以推出了各种
补丁
使其兼容 JCL 的接口,看着好复杂
日志门面 | 组件实现 |
---|---|
JCL、slf4j | log4j、log4j、logback、JUL |
使用框架需选一个日志门面,然后再选择个门面的实现,不选择实现的话默认使用 java 的标准库
4. 项目中为什么不使用JUL
笔者还没在项目中实际用过日志框架,体会到的不多,目前只知道 JUL 的配置管理器实属败笔~ 。等笔者搭完这次项目用到的ELK之后再慢慢体会把
Java的标准日志的更多相关文章
- Java 标准日志工具 Log4j 的使用(附源代码)
源代码下载 Log4j 是事实上的 Java 标准日志工具.会不会用 Log4j 在一定程度上可以说是衡量一个开发人员是否是一位合格的 Java 程序员的标准.如果你是一名 Java 程序员,如果你还 ...
- Java平台标准版本
JDK Java Language Java Language Tools &Tool APIs java javac javadoc jar javap jdeps Script ...
- Java中的日志——Java.util.logging、log4j、commons-logging
Java中给项目程序添加log主要有三种方式,一使用JDK中的java.util.logging包,一种是log4j,一种是commons-logging.其中log4j和commons-loggin ...
- Java实时读取日志文件
古怪的需求 在实习的公司碰到一个古怪的需求:在一台服务器上写日志文件,每当日志文件写到一定大小时,比如是1G,会将这个日志文件改名成另一个名字,并新建一个与原文件名相同的日志文件,再往这个新建的日志文 ...
- Java学习-007-Log4J 日志记录配置文件详解及实例源代码
此文主要讲述在初学 Java 时,常用的 Log4J 日志记录配置文件详解及实例源代码整理.希望能对初学 Java 编程的亲们有所帮助.若有不足之处,敬请大神指正,不胜感激!源代码测试通过日期为:20 ...
- Python(2.7.6) 标准日志模块 - Logging Handler
Python 标准日志模块使用 Handler 控制日志消息写到不同的目的地,如文件.流.邮件.socket 等.除了StreamHandler. FileHandler 和 NullHandler ...
- JAVA 从GC日志分析堆内存 第七节
JAVA 从GC日志分析堆内存 第七节 在上一章中,我们只设置了整个堆的内存大小.但是我们知道,堆又分为了新生代,年老代.他们之间的内存怎么分配呢?新生代又分为Eden和Survivor,他们的比 ...
- [置顶] 遵循Java EE标准体系的开源GIS服务平台之二:平台部署
传送门 ☞ 系统架构设计 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229 传送门 ☞ GoF23种设计模式 ☞ 转载请注明 ☞ http://blog.csd ...
- [置顶] 遵循Java EE标准体系的开源GIS服务平台架构
传送门 ☞ 系统架构设计 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229 传送门 ☞ GoF23种设计模式 ☞ 转载请注明 ☞ http://blog.csd ...
随机推荐
- Hashing散列注意事项
Hashing散列注意事项 Numba支持内置功能hash(),只需__hash__()在提供的参数上调用成员函数即可 .这使得添加对新类型的哈希支持变得微不足道,这是因为扩展APIoverload_ ...
- C++标准模板库(STL)——queue常见用法详解
queue的定义 queue<typename> name; queue容器内元素的访问 由于队列本身就是一种先进先出的限制性数据结构,因此在STL中只能通过front()来访问队首元素, ...
- NCF 如何导入Excel数据
简介 学了上一节的WebApi之后,我们会发现一片新天地 本节跟大家聊一聊,如何把本地的Excel数据导入到NCF中 仓库地址:https://github.com/NeuCharFramework/ ...
- centos 7 iotop 安装
安装指令:yum -y install iotop 指定查看aubunt 用户的读写状态:iotop -u aubunt -P -k -t 允许在非交互模式下每隔3秒刷新一次,只刷新6次:iotop ...
- 十亿级流量下,我与Redis时延小突刺的战斗史
一.背景 某一日收到上游调用方的反馈,提供的某一个Dubbo接口,每天在固定的时间点被短时间熔断,抛出的异常信息为提供方dubbo线程池被耗尽.当前dubbo接口日请求量18亿次,报错请求94W/天, ...
- 20204107 孙嘉临 《PYTHON程序设计》实验四报告
课程:<Python程序设计>班级: 2041姓名: 孙嘉临学号: 20204107实验教师:王志强实验日期:2020年6月29日必修/选修: 公选课 ##作为一个轻度游戏玩家,当然是要写 ...
- python返回列表最大值(java返回数组最大值)
b=["3","2","1","6","5","2","1" ...
- excel VBA中Xldown和xlup用法
1.Worksheets("Sheet1").Range("A1").End(xlDown).Select '意思为自A1起,返回从上往下的最后一个非空 ...
- jenkins pipeline的声明式与脚本式
自从Jenkins 2.0 版本升级之后,支持了通过代码(Groovy DSL)来描述一个构建流水线,灵活方便地实现持续交付,大大提升 Jenkins Job 维护的效率,实现从 CI 到 CD 到转 ...
- POJ 1016 Numbers That Count 不难,但要注意细节
题意是将一串数字转换成另一种形式.比如5553141转换成2个1,1个3,1个4,3个5,即21131435.1000000000000转换成12011.数字的个数是可能超过9个的.n个m,m是从小到 ...