参考文章:
1.Java 日志从入门到实战
2.Java日志框架的发展历史,你不想了解一下吗
背景
想自定义 logback 配置文件进行日志分级别记录到不同文件,遇到了几个问题(使用的是 spring-boot 构建的项目,spring-boot 版本为 2.7.12):
1.出现如下报错(图1),得知是 logback 版本应该和配置写的 logback-spring.xml 的语法有出入,spring-boot 2.7.12 是通过使用 spring-booot-starter-logging 依赖引入的相关 logback 依赖,想到参考的 logback 官方文档可能和 logback 依赖包版本不一致,所以更新了 logback 依赖包(图2);
2.更新了 logback 版本之后,发现还是报错(图3),好像是缺少实现类的依赖包;
发现 Java Log 有点乱,涉及到的东西很多,于是就想系统的学习一下 Java Log。
Java 日志演化历史
1.System.out 与 System.err 记录日志;
2.Log4j:最先出现的是 Apache 的 Log4j(1996年初),是应用最广泛的日志工具,成为了 Java 日志的标准;作者 - Ceki Gülcü;
3.JUL(Java Util Log):Sun 公司在 2002 年 2 月 Jdk1.4 中,增加了 JUL(在 java.util.logging 包下),企图对抗 Log4j,造成 Java 目前记录日志局面的混乱 - 罪魁祸首;
为什么 JUL 的出现会导致开发局面混乱呢?
想象下你的项目应用使用 Log4j,然后使用了一个第三方库,而第三方库使用了 JUL,那么,你的应用就得同时使用 Log4j 和JUL两个日志工具了,然后又有需要使用另外一个第三方库,但是这个第三方库使用了 Log4j 和 JUL 之外的 simplelog。这个时候你的应用里各种 log 工具满天飞,这势必会使你的程序员感到崩溃。因为这些日志工具互相没有关联,替换和统一日志工具也就变成了比较棘手的一件事情。
如何解决这个问题?
使用”适配器“设计模式,把这个问题进行抽象,抽象出一个接口层,对每个日志实现都进行适配,这样这些提供给别人的库都直接使用抽象层即可。
4.JCL(Jakarta Commons Logging):为了搞定这个日常开发比较棘手的问题,Apache 开源社区在 2002 年 8 月推出了日志接口,叫 commons-logging,也被称为 JCL(Java common logging);JCL 对各种日志接口进行抽象,兼容了主流的 Log4j、JUL、simplelog 等日志实现;提供了 JCL 的默认实现 Simple Log;- spring 依赖了 JCL;
5.log4j 的作者 Ceki Gülcü 觉得 JCL 不够优雅,所以开发了更优雅的日志框架 SLF4J (抽象层,简单日志门面(Simple Logging Facade for Java));- 此时 Ceki Gülcü 已离开了 Apache;
但是 slf4j 只是日志接口,之前已经出现的日志产品,如 JUL 和 Log4j 都是没有实现这个接口的,所以 Ceki Gülcü 使用桥接设计方式开发了桥接包,对接 slf4j 和之前的日志实现。
6.logback 的诞生:Ceki Gülcü 觉得目前市场上的日志标准都是间接实现 slf4j 接口的,都需要桥接包,因此开发了 slf4j 的直接实现 logback,性能超越 log4j;
7. 2012 年,Apache 推出新项目 log4j2(完全不兼容 log4j),其也进行了接口和实现的分离设计,分成 log4j-api(日志接口) 和 log4j-core(日志实现);
Java 日志依赖包
1.接口:
JCL
slf4j
log4j-api
2.实现:
JCL 实现:JUL、log4j
slf4j 接口实现:logback
log4j-api 接口实现:log4j-core
3.桥接包:
JCL(接口)-----> jcl-over-slf4j(桥接包)-----> slf4j(接口)
JUL(产品)<----- slf4j-jdk14(桥接包)<----- slf4j(接口)
JUL(产品)-----> jul-to-slf4j(桥接包)-----> slf4j(接口)
log4j(产品)-----> log4j-over-slf4j(桥接包)-----> slf4j(接口)
log4j(产品)<----- slf4j-log4j12(桥接包)<----- slf4j(接口)
JCL(接口)<----- slf4j-jcl(桥接包)<----- slf4j(接口)
log4j-core(产品)<----- log4j-slf4j-impl(桥接包)<----- slf4j(接口)
log4j-api(接口)-----> log4j-to-slf4j(桥接包)-----> slf4j(接口)
JUL(产品)-----> log4j-jul(桥接包)-----> log4j-api(接口)
log4j(产品)-----> log4j-1.2-api(桥接包)-----> log4j-core(产品)
JCL(接口)-----> log4j-jcl(桥接包)-----> log4j-core(产品)
4.推荐记录日志的组合
logback 官方建议配合 slf4j 使用;
logback 主要由三个模块组成:
- logback-core:提供 Logback 的核心功能,是另外两个组件的基础;
- logback-classic:地位和作用等同于 log4j ,也被认为是 log4j 的改进版,它实现了 slf4j;
- logback-access:主要作为一个与 Servlet 容器交互的模块,比如说 tomcat 或者 jetty,提供一些与 HTTP 访问相关的功能;